diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/boards/atngw100/flash.c avr32-git/arch/avr32/boards/atngw100/flash.c
--- linux-2.6.21.3/arch/avr32/boards/atngw100/flash.c	1970-01-01 01:00:00.000000000 +0100
+++ avr32-git/arch/avr32/boards/atngw100/flash.c	2007-06-06 11:33:46.000000000 +0200
@@ -0,0 +1,95 @@
+/*
+ * ATNGW100 board-specific flash initialization
+ *
+ * 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/init.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+
+#include <asm/arch/smc.h>
+
+static struct smc_config flash_config __initdata = {
+	.ncs_read_setup		= 0,
+	.nrd_setup		= 40,
+	.ncs_write_setup	= 0,
+	.nwe_setup		= 10,
+
+	.ncs_read_pulse		= 80,
+	.nrd_pulse		= 40,
+	.ncs_write_pulse	= 65,
+	.nwe_pulse		= 55,
+
+	.read_cycle		= 120,
+	.write_cycle		= 120,
+
+	.bus_width		= 2,
+	.nrd_controlled		= 1,
+	.nwe_controlled		= 1,
+	.byte_write		= 1,
+};
+
+static struct mtd_partition flash_parts[] = {
+	{
+		.name           = "u-boot",
+		.offset         = 0x00000000,
+		.size           = 0x00020000,           /* 128 KiB */
+		.mask_flags     = MTD_WRITEABLE,
+	},
+	{
+		.name           = "root",
+		.offset         = 0x00020000,
+		.size           = 0x007d0000,
+	},
+	{
+		.name           = "env",
+		.offset         = 0x007f0000,
+		.size           = 0x00010000,
+		.mask_flags     = MTD_WRITEABLE,
+	},
+};
+
+static struct physmap_flash_data flash_data = {
+	.width		= 2,
+	.nr_parts	= ARRAY_SIZE(flash_parts),
+	.parts		= flash_parts,
+};
+
+static struct resource flash_resource = {
+	.start		= 0x00000000,
+	.end		= 0x007fffff,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device flash_device = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.resource	= &flash_resource,
+	.num_resources	= 1,
+	.dev		= {
+		.platform_data = &flash_data,
+	},
+};
+
+/* This needs to be called after the SMC has been initialized */
+static int __init atngw100_flash_init(void)
+{
+	int ret;
+
+	ret = smc_set_configuration(0, &flash_config);
+	if (ret < 0) {
+		printk(KERN_ERR "atngw100: failed to set NOR flash timing\n");
+		return ret;
+	}
+
+	platform_device_register(&flash_device);
+
+	return 0;
+}
+device_initcall(atngw100_flash_init);
diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/boards/atngw100/Makefile avr32-git/arch/avr32/boards/atngw100/Makefile
--- linux-2.6.21.3/arch/avr32/boards/atngw100/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ avr32-git/arch/avr32/boards/atngw100/Makefile	2007-06-06 11:33:46.000000000 +0200
@@ -0,0 +1 @@
+obj-y				+= setup.o flash.o
diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/boards/atngw100/setup.c avr32-git/arch/avr32/boards/atngw100/setup.c
--- linux-2.6.21.3/arch/avr32/boards/atngw100/setup.c	1970-01-01 01:00:00.000000000 +0100
+++ avr32-git/arch/avr32/boards/atngw100/setup.c	2007-06-06 11:33:46.000000000 +0200
@@ -0,0 +1,131 @@
+/*
+ * Board-specific setup code for the ATNGW100 Network Gateway
+ *
+ * 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/clk.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+#include <linux/linkage.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+#include <linux/spi/spi.h>
+
+#include <asm/io.h>
+#include <asm/setup.h>
+
+#include <asm/arch/at32ap7000.h>
+#include <asm/arch/board.h>
+#include <asm/arch/init.h>
+
+/* Initialized by bootloader-specific startup code. */
+struct tag *bootloader_tags __initdata;
+
+struct eth_addr {
+	u8 addr[6];
+};
+static struct eth_addr __initdata hw_addr[2];
+static struct eth_platform_data __initdata eth_data[2];
+
+static struct spi_board_info spi0_board_info[] __initdata = {
+	{
+		.modalias	= "mtd_dataflash",
+		.max_speed_hz	= 10000000,
+		.chip_select	= 0,
+	},
+};
+
+static struct mci_platform_data __initdata mci0_data = {
+	.detect_pin	= GPIO_PIN_PC(25),
+	.wp_pin		= GPIO_PIN_PE(0),
+};
+
+/*
+ * The next two functions should go away as the boot loader is
+ * supposed to initialize the macb address registers with a valid
+ * ethernet address. But we need to keep it around for a while until
+ * we can be reasonably sure the boot loader does this.
+ *
+ * The phy_id is ignored as the driver will probe for it.
+ */
+static int __init parse_tag_ethernet(struct tag *tag)
+{
+	int i;
+
+	i = tag->u.ethernet.mac_index;
+	if (i < ARRAY_SIZE(hw_addr))
+		memcpy(hw_addr[i].addr, tag->u.ethernet.hw_address,
+		       sizeof(hw_addr[i].addr));
+
+	return 0;
+}
+__tagtable(ATAG_ETHERNET, parse_tag_ethernet);
+
+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 >= ARRAY_SIZE(hw_addr))
+		return;
+
+	addr = hw_addr[pdev->id].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);
+}
+
+struct platform_device *at32_usart_map[1];
+unsigned int at32_nr_usarts = 1;
+
+void __init setup_board(void)
+{
+	at32_map_usart(1, 0);	/* USART 1: /dev/ttyS0, DB9 */
+	at32_setup_serial_console(0);
+}
+
+static int __init atngw100_init(void)
+{
+	/*
+	 * ATNGW100 uses 16-bit SDRAM interface, so we don't need to
+	 * reserve any pins for it.
+	 */
+
+	at32_add_system_devices();
+
+	at32_add_device_usart(0);
+
+	set_hw_addr(at32_add_device_eth(0, &eth_data[0]));
+	set_hw_addr(at32_add_device_eth(1, &eth_data[1]));
+
+	at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info));
+	at32_add_device_mci(0, &mci0_data);
+	at32_add_device_usba(0);
+
+	return 0;
+}
+postcore_initcall(atngw100_init);
diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/boards/atstk1000/atstk1000.h avr32-git/arch/avr32/boards/atstk1000/atstk1000.h
--- linux-2.6.21.3/arch/avr32/boards/atstk1000/atstk1000.h	1970-01-01 01:00:00.000000000 +0100
+++ avr32-git/arch/avr32/boards/atstk1000/atstk1000.h	2007-06-06 11:33:46.000000000 +0200
@@ -0,0 +1,15 @@
+/*
+ * ATSTK1000 setup code: Daughterboard 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __ARCH_AVR32_BOARDS_ATSTK1000_ATSTK1000_H
+#define __ARCH_AVR32_BOARDS_ATSTK1000_ATSTK1000_H
+
+extern struct atmel_lcdfb_info atstk1000_lcdc_data;
+
+#endif /* __ARCH_AVR32_BOARDS_ATSTK1000_ATSTK1000_H */
diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/boards/atstk1000/atstk1002.c avr32-git/arch/avr32/boards/atstk1000/atstk1002.c
--- linux-2.6.21.3/arch/avr32/boards/atstk1000/atstk1002.c	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/arch/avr32/boards/atstk1000/atstk1002.c	2007-06-06 11:33:46.000000000 +0200
@@ -16,6 +16,8 @@
 #include <linux/types.h>
 #include <linux/spi/spi.h>
 
+#include <video/atmel_lcdc.h>
+
 #include <asm/io.h>
 #include <asm/setup.h>
 #include <asm/arch/at32ap7000.h>
@@ -23,6 +25,7 @@
 #include <asm/arch/init.h>
 #include <asm/arch/portmux.h>
 
+#include "atstk1000.h"
 
 #define	SW2_DEFAULT		/* MMCI and UART_A available */
 
@@ -31,9 +34,7 @@
 };
 
 static struct eth_addr __initdata hw_addr[2];
-
 static struct eth_platform_data __initdata eth_data[2];
-extern struct lcdc_platform_data atstk1000_fb0_data;
 
 static struct spi_board_info spi0_board_info[] __initdata = {
 	{
@@ -41,9 +42,15 @@
 		.modalias	= "ltv350qv",
 		.max_speed_hz	= 16000000,
 		.chip_select	= 1,
+		.mode		= SPI_MODE_3,
 	},
 };
 
+static struct mci_platform_data __initdata mci0_data = {
+	.detect_pin	= GPIO_PIN_NONE,
+	.wp_pin		= GPIO_PIN_NONE,
+};
+
 /*
  * The next two functions should go away as the boot loader is
  * supposed to initialize the macb address registers with a valid
@@ -148,7 +155,12 @@
 	set_hw_addr(at32_add_device_eth(0, &eth_data[0]));
 
 	at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info));
-	at32_add_device_lcdc(0, &atstk1000_fb0_data);
+	at32_add_device_twi(0);
+	at32_add_device_mci(0, &mci0_data);
+	at32_add_device_lcdc(0, &atstk1000_lcdc_data,
+			     fbmem_start, fbmem_size);
+	at32_add_device_usba(0);
+	at32_add_device_abdac(0);
 
 	return 0;
 }
diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/boards/atstk1000/setup.c avr32-git/arch/avr32/boards/atstk1000/setup.c
--- linux-2.6.21.3/arch/avr32/boards/atstk1000/setup.c	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/arch/avr32/boards/atstk1000/setup.c	2007-06-06 11:33:46.000000000 +0200
@@ -8,43 +8,56 @@
  * published by the Free Software Foundation.
  */
 #include <linux/bootmem.h>
+#include <linux/fb.h>
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/linkage.h>
 
-#include <asm/setup.h>
+#include <video/atmel_lcdc.h>
 
+#include <asm/setup.h>
 #include <asm/arch/board.h>
 
+#include "atstk1000.h"
+
 /* Initialized by bootloader-specific startup code. */
 struct tag *bootloader_tags __initdata;
 
-struct lcdc_platform_data __initdata atstk1000_fb0_data;
-
-void __init board_setup_fbmem(unsigned long fbmem_start,
-			      unsigned long fbmem_size)
-{
-	if (!fbmem_size)
-		return;
-
-	if (!fbmem_start) {
-		void *fbmem;
-
-		fbmem = alloc_bootmem_low_pages(fbmem_size);
-		fbmem_start = __pa(fbmem);
-	} else {
-		pg_data_t *pgdat;
-
-		for_each_online_pgdat(pgdat) {
-			if (fbmem_start >= pgdat->bdata->node_boot_start
-			    && fbmem_start <= pgdat->bdata->node_low_pfn)
-				reserve_bootmem_node(pgdat, fbmem_start,
-						     fbmem_size);
-		}
-	}
-
-	printk("%luKiB framebuffer memory at address 0x%08lx\n",
-	       fbmem_size >> 10, fbmem_start);
-	atstk1000_fb0_data.fbmem_start = fbmem_start;
-	atstk1000_fb0_data.fbmem_size = fbmem_size;
-}
+static struct fb_videomode __initdata ltv350qv_modes[] = {
+	{
+		.name		= "320x240 @ 75",
+		.refresh	= 75,
+		.xres		= 320,		.yres		= 240,
+		.pixclock	= KHZ2PICOS(6891),
+
+		.left_margin	= 17,		.right_margin	= 33,
+		.upper_margin	= 10,		.lower_margin	= 10,
+		.hsync_len	= 16,		.vsync_len	= 1,
+
+		.sync		= 0,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+};
+
+static struct fb_monspecs __initdata atstk1000_default_monspecs = {
+	.manufacturer		= "SNG",
+	.monitor		= "LTV350QV",
+	.modedb			= ltv350qv_modes,
+	.modedb_len		= ARRAY_SIZE(ltv350qv_modes),
+	.hfmin			= 14820,
+	.hfmax			= 22230,
+	.vfmin			= 60,
+	.vfmax			= 90,
+	.dclkmax		= 30000000,
+};
+
+struct atmel_lcdfb_info __initdata atstk1000_lcdc_data = {
+	.default_bpp		= 24,
+	.default_dmacon		= ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN,
+	.default_lcdcon2	= (ATMEL_LCDC_DISTYPE_TFT
+				   | ATMEL_LCDC_INVCLK
+				   | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE
+				   | ATMEL_LCDC_MEMOR_BIG),
+	.default_monspecs	= &atstk1000_default_monspecs,
+	.guard_time		= 2,
+};
diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/drivers/dw-dmac.c avr32-git/arch/avr32/drivers/dw-dmac.c
--- linux-2.6.21.3/arch/avr32/drivers/dw-dmac.c	1970-01-01 01:00:00.000000000 +0100
+++ avr32-git/arch/avr32/drivers/dw-dmac.c	2007-06-06 11:33:46.000000000 +0200
@@ -0,0 +1,761 @@
+/*
+ * Driver for the Synopsys DesignWare DMA Controller
+ *
+ * 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/clk.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/dma-controller.h>
+#include <asm/io.h>
+
+#include "dw-dmac.h"
+
+#define DMAC_NR_CHANNELS 3
+#define DMAC_MAX_BLOCKSIZE 4095
+
+enum {
+	CH_STATE_FREE = 0,
+	CH_STATE_ALLOCATED,
+	CH_STATE_BUSY,
+};
+
+struct dw_dma_lli {
+	dma_addr_t	sar;
+	dma_addr_t	dar;
+	dma_addr_t	llp;
+	u32		ctllo;
+	u32		ctlhi;
+	u32		sstat;
+	u32		dstat;
+};
+
+struct dw_dma_block {
+	struct dw_dma_lli *lli_vaddr;
+	dma_addr_t lli_dma_addr;
+};
+
+struct dw_dma_channel {
+	unsigned int state;
+        int is_cyclic;
+	struct dma_request_sg *req_sg;
+	struct dma_request_cyclic *req_cyclic;
+	unsigned int nr_blocks;
+	int direction;
+	struct dw_dma_block *block;
+};
+
+struct dw_dma_controller {
+	spinlock_t lock;
+	void * __iomem	regs;
+	struct dma_pool *lli_pool;
+	struct clk *hclk;
+	struct dma_controller dma;
+	struct dw_dma_channel channel[DMAC_NR_CHANNELS];
+};
+#define to_dw_dmac(dmac) container_of(dmac, struct dw_dma_controller, dma)
+
+#define dmac_writel_hi(dmac, reg, value) \
+	__raw_writel((value), (dmac)->regs + DW_DMAC_##reg + 4)
+#define dmac_readl_hi(dmac, reg) \
+	__raw_readl((dmac)->regs + DW_DMAC_##reg + 4)
+#define dmac_writel_lo(dmac, reg, value) \
+	__raw_writel((value), (dmac)->regs + DW_DMAC_##reg)
+#define dmac_readl_lo(dmac, reg) \
+	__raw_readl((dmac)->regs + DW_DMAC_##reg)
+#define dmac_chan_writel_hi(dmac, chan, reg, value) \
+	__raw_writel((value), ((dmac)->regs + 0x58 * (chan) \
+			       + DW_DMAC_CHAN_##reg + 4))
+#define dmac_chan_readl_hi(dmac, chan, reg) \
+	__raw_readl((dmac)->regs + 0x58 * (chan) + DW_DMAC_CHAN_##reg + 4)
+#define dmac_chan_writel_lo(dmac, chan, reg, value) \
+	__raw_writel((value), (dmac)->regs + 0x58 * (chan) + DW_DMAC_CHAN_##reg)
+#define dmac_chan_readl_lo(dmac, chan, reg) \
+	__raw_readl((dmac)->regs + 0x58 * (chan) + DW_DMAC_CHAN_##reg)
+#define set_channel_bit(dmac, reg, chan) \
+	dmac_writel_lo(dmac, reg, (1 << (chan)) | (1 << ((chan) + 8)))
+#define clear_channel_bit(dmac, reg, chan) \
+	dmac_writel_lo(dmac, reg, (0 << (chan)) | (1 << ((chan) + 8)))
+
+static int dmac_alloc_channel(struct dma_controller *_dmac)
+{
+	struct dw_dma_controller *dmac = to_dw_dmac(_dmac);
+	struct dw_dma_channel *chan;
+	unsigned long flags;
+	int i;
+
+	spin_lock_irqsave(&dmac->lock, flags);
+	for (i = 0; i < DMAC_NR_CHANNELS; i++)
+		if (dmac->channel[i].state == CH_STATE_FREE)
+			break;
+
+	if (i < DMAC_NR_CHANNELS) {
+		chan = &dmac->channel[i];
+		chan->state = CH_STATE_ALLOCATED;
+	} else {
+		i = -EBUSY;
+	}
+
+	spin_unlock_irqrestore(&dmac->lock, flags);
+
+	return i;
+}
+
+static void dmac_release_channel(struct dma_controller *_dmac, int channel)
+{
+	struct dw_dma_controller *dmac = to_dw_dmac(_dmac);
+
+	BUG_ON(channel >= DMAC_NR_CHANNELS
+	       || dmac->channel[channel].state != CH_STATE_ALLOCATED);
+
+	dmac->channel[channel].state = CH_STATE_FREE;
+}
+
+static struct dw_dma_block *allocate_blocks(struct dw_dma_controller *dmac,
+					    unsigned int nr_blocks)
+{
+	struct dw_dma_block *block;
+	void *p;
+	unsigned int i;
+
+	block = kmalloc(nr_blocks * sizeof(*block),
+			GFP_KERNEL);
+	if (unlikely(!block))
+		return NULL;
+
+	for (i = 0; i < nr_blocks; i++) {
+		p = dma_pool_alloc(dmac->lli_pool, GFP_KERNEL,
+				   &block[i].lli_dma_addr);
+		block[i].lli_vaddr = p;
+		if (unlikely(!p))
+			goto fail;
+	}
+
+	return block;
+
+fail:
+	for (i = 0; i < nr_blocks; i++) {
+		if (!block[i].lli_vaddr)
+			break;
+		dma_pool_free(dmac->lli_pool, block[i].lli_vaddr,
+			      block[i].lli_dma_addr);
+	}
+	kfree(block);
+	return NULL;
+}
+
+static void cleanup_channel(struct dw_dma_controller *dmac,
+			    struct dw_dma_channel *chan)
+{
+	unsigned int i;
+
+	if (chan->nr_blocks > 1) {
+		for (i = 0; i < chan->nr_blocks; i++)
+			dma_pool_free(dmac->lli_pool, chan->block[i].lli_vaddr,
+				      chan->block[i].lli_dma_addr);
+		kfree(chan->block);
+	}
+
+	chan->state = CH_STATE_ALLOCATED;
+}
+
+static int dmac_prepare_request_sg(struct dma_controller *_dmac,
+				   struct dma_request_sg *req)
+{
+	struct dw_dma_controller *dmac = to_dw_dmac(_dmac);
+	struct dw_dma_channel *chan;
+	unsigned long ctlhi, ctllo, cfghi, cfglo;
+	unsigned long block_size;
+	unsigned int nr_blocks;
+	int ret, i, direction;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dmac->lock, flags);
+
+	ret = -EINVAL;
+	if (req->req.channel >= DMAC_NR_CHANNELS
+	    || dmac->channel[req->req.channel].state != CH_STATE_ALLOCATED
+	    || req->block_size > DMAC_MAX_BLOCKSIZE) {
+		spin_unlock_irqrestore(&dmac->lock, flags);
+		return -EINVAL;
+	}
+
+	chan = &dmac->channel[req->req.channel];
+	chan->state = CH_STATE_BUSY;
+	chan->req_sg = req;
+	chan->is_cyclic = 0;
+
+	/*
+	 * We have marked the channel as busy, so no need to keep the
+	 * lock as long as we only touch the channel-specific
+	 * registers
+	 */
+	spin_unlock_irqrestore(&dmac->lock, flags);
+
+	/*
+	 * There may be limitations in the driver and/or the DMA
+	 * controller that prevents us from sending a whole
+	 * scatterlist item in one go.  Taking this into account,
+	 * calculate the number of block transfers we need to set up.
+	 *
+	 * FIXME: Let the peripheral driver know about the maximum
+	 * block size we support. We really don't want to use a
+	 * different block size than what was suggested by the
+	 * peripheral.
+	 *
+	 * Each block will get its own Linked List Item (LLI) below.
+	 */
+	block_size = req->block_size;
+	nr_blocks = req->nr_blocks;
+	pr_debug("block_size %lu, nr_blocks %u nr_sg = %u\n",
+		 block_size, nr_blocks, req->nr_sg);
+
+	BUG_ON(nr_blocks == 0);
+	chan->nr_blocks = nr_blocks;
+
+	ret = -EINVAL;
+	cfglo = cfghi = 0;
+	switch (req->direction) {
+	case DMA_DIR_MEM_TO_PERIPH:
+		direction = DMA_TO_DEVICE;
+		cfghi = req->periph_id << (43 - 32);
+		break;
+
+	case DMA_DIR_PERIPH_TO_MEM:
+		direction = DMA_FROM_DEVICE;
+		cfghi = req->periph_id << (39 - 32);
+		break;
+	default:
+		goto out_unclaim_channel;
+	}
+
+        chan->direction = direction;
+
+	dmac_chan_writel_hi(dmac, req->req.channel, CFG, cfghi);
+	dmac_chan_writel_lo(dmac, req->req.channel, CFG, cfglo);
+
+	ctlhi = block_size >> req->width;
+	ctllo = ((req->direction << 20)
+		 // | (1 << 14) | (1 << 11) // source/dest burst trans len
+		 | (req->width << 4) | (req->width << 1)
+		 | (1 << 0));		 // interrupt enable
+
+	if (nr_blocks == 1) {
+		/* Only one block: No need to use block chaining */
+		if (direction == DMA_TO_DEVICE) {
+			dmac_chan_writel_lo(dmac, req->req.channel, SAR,
+					    req->sg->dma_address);
+			dmac_chan_writel_lo(dmac, req->req.channel, DAR,
+					    req->data_reg);
+			ctllo |= 2 << 7; // no dst increment
+		} else {
+			dmac_chan_writel_lo(dmac, req->req.channel, SAR,
+					    req->data_reg);
+			dmac_chan_writel_lo(dmac, req->req.channel, DAR,
+					    req->sg->dma_address);
+			ctllo |= 2 << 9; // no src increment
+		}
+		dmac_chan_writel_lo(dmac, req->req.channel, CTL, ctllo);
+		dmac_chan_writel_hi(dmac, req->req.channel, CTL, ctlhi);
+		pr_debug("ctl hi:lo 0x%lx:%lx\n", ctlhi, ctllo);
+	} else {
+		struct dw_dma_lli *lli, *lli_prev = NULL;
+		int j = 0, offset = 0;
+
+		ret = -ENOMEM;
+		chan->block = allocate_blocks(dmac, nr_blocks);
+		if (!chan->block)
+			goto out_unclaim_channel;
+
+		if (direction == DMA_TO_DEVICE)
+			ctllo |= 1 << 28 | 1 << 27 | 2 << 7;
+		else
+			ctllo |= 1 << 28 | 1 << 27 | 2 << 9;
+
+		/*
+		 * Map scatterlist items to blocks. One scatterlist
+		 * item may need more than one block for the reasons
+		 * mentioned above.
+		 */
+		for (i = 0; i < nr_blocks; i++) {
+			lli = chan->block[i].lli_vaddr;
+			if (lli_prev) {
+				lli_prev->llp = chan->block[i].lli_dma_addr;
+				pr_debug("lli[%d] (0x%p/0x%x): 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+					 i - 1, chan->block[i - 1].lli_vaddr,
+					 chan->block[i - 1].lli_dma_addr,
+					 lli_prev->sar, lli_prev->dar, lli_prev->llp,
+					 lli_prev->ctllo, lli_prev->ctlhi);
+			}
+			lli->llp = 0;
+			lli->ctllo = ctllo;
+			lli->ctlhi = ctlhi;
+			if (direction == DMA_TO_DEVICE) {
+				lli->sar = req->sg[j].dma_address + offset;
+				lli->dar = req->data_reg;
+			} else {
+				lli->sar = req->data_reg;
+				lli->dar = req->sg[j].dma_address + offset;
+			}
+			lli_prev = lli;
+
+			offset += block_size;
+			if (offset > req->sg[j].length) {
+				j++;
+				offset = 0;
+			}
+		}
+
+		pr_debug("lli[%d] (0x%p/0x%x): 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+			 i - 1, chan->block[i - 1].lli_vaddr,
+			 chan->block[i - 1].lli_dma_addr, lli_prev->sar,
+			 lli_prev->dar, lli_prev->llp,
+			 lli_prev->ctllo, lli_prev->ctlhi);
+
+		/*
+		 * SAR, DAR and CTL are initialized from the LLI. We
+		 * only have to enable the LLI bits in CTL.
+		 */
+		dmac_chan_writel_hi(dmac, req->req.channel, CTL, 0);
+		dmac_chan_writel_lo(dmac, req->req.channel, LLP,
+				    chan->block[0].lli_dma_addr);
+		dmac_chan_writel_lo(dmac, req->req.channel, CTL, 1 << 28 | 1 << 27);
+	}
+
+	set_channel_bit(dmac, MASK_XFER, req->req.channel);
+	set_channel_bit(dmac, MASK_ERROR, req->req.channel);
+	if (req->req.block_complete)
+		set_channel_bit(dmac, MASK_BLOCK, req->req.channel);
+	else
+		clear_channel_bit(dmac, MASK_BLOCK, req->req.channel);
+
+	return 0;
+
+out_unclaim_channel:
+	chan->state = CH_STATE_ALLOCATED;
+	return ret;
+}
+
+static int dmac_prepare_request_cyclic(struct dma_controller *_dmac,
+                                       struct dma_request_cyclic *req)
+{
+	struct dw_dma_controller *dmac = to_dw_dmac(_dmac);
+	struct dw_dma_channel *chan;
+	unsigned long ctlhi, ctllo, cfghi, cfglo;
+	unsigned long block_size;
+	int ret, i, direction;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dmac->lock, flags);
+
+        block_size = (req->buffer_size/req->periods) >> req->width;
+
+	ret = -EINVAL;
+	if (req->req.channel >= DMAC_NR_CHANNELS
+	    || dmac->channel[req->req.channel].state != CH_STATE_ALLOCATED
+            || (req->periods == 0)
+	    || block_size > DMAC_MAX_BLOCKSIZE) {
+		spin_unlock_irqrestore(&dmac->lock, flags);
+		return -EINVAL;
+	}
+
+	chan = &dmac->channel[req->req.channel];
+	chan->state = CH_STATE_BUSY;
+	chan->is_cyclic = 1;
+        chan->req_cyclic = req;
+
+	/*
+	 * We have marked the channel as busy, so no need to keep the
+	 * lock as long as we only touch the channel-specific
+	 * registers
+	 */
+	spin_unlock_irqrestore(&dmac->lock, flags);
+
+	/*
+          Setup
+	 */
+	BUG_ON(req->buffer_size % req->periods);
+	/* printk(KERN_INFO "block_size = %lu, periods = %u\n", block_size, req->periods); */
+
+	chan->nr_blocks = req->periods;
+
+	ret = -EINVAL;
+	cfglo = cfghi = 0;
+	switch (req->direction) {
+	case DMA_DIR_MEM_TO_PERIPH:
+		direction = DMA_TO_DEVICE;
+		cfghi = req->periph_id << (43 - 32);
+		break;
+
+	case DMA_DIR_PERIPH_TO_MEM:
+		direction = DMA_FROM_DEVICE;
+		cfghi = req->periph_id << (39 - 32);
+		break;
+	default:
+		goto out_unclaim_channel;
+	}
+
+        chan->direction = direction;
+
+	dmac_chan_writel_hi(dmac, req->req.channel, CFG, cfghi);
+	dmac_chan_writel_lo(dmac, req->req.channel, CFG, cfglo);
+
+	ctlhi = block_size;
+	ctllo = ((req->direction << 20)
+		 | (req->width << 4) | (req->width << 1)
+		 | (1 << 0));		 // interrupt enable
+
+        {
+		struct dw_dma_lli *lli = NULL, *lli_prev = NULL;
+
+		ret = -ENOMEM;
+		chan->block = allocate_blocks(dmac, req->periods);
+		if (!chan->block)
+			goto out_unclaim_channel;
+
+		if (direction == DMA_TO_DEVICE)
+			ctllo |= 1 << 28 | 1 << 27 | 2 << 7;
+		else
+			ctllo |= 1 << 28 | 1 << 27 | 2 << 9;
+
+		/*
+		 * Set up a linked list items where each period gets
+		 * an item. The linked list item for the last period
+		 * points back to the star of the buffer making a
+		 * cyclic buffer.
+		 */
+		for (i = 0; i < req->periods; i++) {
+			lli = chan->block[i].lli_vaddr;
+			if (lli_prev) {
+				lli_prev->llp = chan->block[i].lli_dma_addr;
+				/* printk(KERN_INFO "lli[%d] (0x%p/0x%x): 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+				   i - 1, chan->block[i - 1].lli_vaddr,
+				   chan->block[i - 1].lli_dma_addr,
+				   lli_prev->sar, lli_prev->dar, lli_prev->llp,
+				   lli_prev->ctllo, lli_prev->ctlhi);*/
+			}
+			lli->llp = 0;
+			lli->ctllo = ctllo;
+			lli->ctlhi = ctlhi;
+			if (direction == DMA_TO_DEVICE) {
+				lli->sar = req->buffer_start + i*(block_size << req->width);
+				lli->dar = req->data_reg;
+			} else {
+				lli->sar = req->data_reg;
+				lli->dar = req->buffer_start + i*(block_size << req->width);
+			}
+			lli_prev = lli;
+		}
+		lli->llp = chan->block[0].lli_dma_addr;
+
+		/*printk(KERN_INFO "lli[%d] (0x%p/0x%x): 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+		  i - 1, chan->block[i - 1].lli_vaddr,
+		  chan->block[i - 1].lli_dma_addr, lli_prev->sar,
+		  lli_prev->dar, lli_prev->llp,
+		  lli_prev->ctllo, lli_prev->ctlhi); */
+
+		/*
+		 * SAR, DAR and CTL are initialized from the LLI. We
+		 * only have to enable the LLI bits in CTL.
+		 */
+		dmac_chan_writel_lo(dmac, req->req.channel, LLP,
+				    chan->block[0].lli_dma_addr);
+		dmac_chan_writel_lo(dmac, req->req.channel, CTL, 1 << 28 | 1 << 27);
+	}
+
+	clear_channel_bit(dmac, MASK_XFER, req->req.channel);
+	set_channel_bit(dmac, MASK_ERROR, req->req.channel);
+	if (req->req.block_complete)
+		set_channel_bit(dmac, MASK_BLOCK, req->req.channel);
+	else
+		clear_channel_bit(dmac, MASK_BLOCK, req->req.channel);
+
+	return 0;
+
+out_unclaim_channel:
+	chan->state = CH_STATE_ALLOCATED;
+	return ret;
+}
+
+static int dmac_start_request(struct dma_controller *_dmac,
+			      unsigned int channel)
+{
+	struct dw_dma_controller *dmac = to_dw_dmac(_dmac);
+
+	BUG_ON(channel >= DMAC_NR_CHANNELS);
+
+	set_channel_bit(dmac, CH_EN, channel);
+
+	return 0;
+}
+
+static dma_addr_t dmac_get_current_pos(struct dma_controller *_dmac,
+                                       unsigned int channel)
+{
+	struct dw_dma_controller *dmac = to_dw_dmac(_dmac);
+	struct dw_dma_channel *chan;
+        dma_addr_t current_pos;
+
+	BUG_ON(channel >= DMAC_NR_CHANNELS);
+
+        chan = &dmac->channel[channel];
+
+	switch (chan->direction) {
+	case DMA_TO_DEVICE:
+		current_pos = dmac_chan_readl_lo(dmac, channel, SAR);
+		break;
+	case DMA_FROM_DEVICE:
+		current_pos = dmac_chan_readl_lo(dmac, channel, DAR);
+		break;
+	default:
+		return 0;
+	}
+
+
+        if (!current_pos) {
+		if (chan->is_cyclic) {
+			current_pos = chan->req_cyclic->buffer_start;
+		} else {
+			current_pos = chan->req_sg->sg->dma_address;
+		}
+	}
+
+	return current_pos;
+}
+
+
+static int dmac_stop_request(struct dma_controller *_dmac,
+                             unsigned int channel)
+{
+	struct dw_dma_controller *dmac = to_dw_dmac(_dmac);
+	struct dw_dma_channel *chan;
+
+	BUG_ON(channel >= DMAC_NR_CHANNELS);
+
+	chan = &dmac->channel[channel];
+	pr_debug("stop: st%u s%08x d%08x l%08x ctl0x%08x:0x%08x\n",
+		 chan->state, dmac_chan_readl_lo(dmac, channel, SAR),
+		 dmac_chan_readl_lo(dmac, channel, DAR),
+		 dmac_chan_readl_lo(dmac, channel, LLP),
+		 dmac_chan_readl_hi(dmac, channel, CTL),
+		 dmac_chan_readl_lo(dmac, channel, CTL));
+
+	if (chan->state == CH_STATE_BUSY) {
+		clear_channel_bit(dmac, CH_EN, channel);
+		cleanup_channel(dmac, &dmac->channel[channel]);
+	}
+
+	return 0;
+}
+
+
+static void dmac_block_complete(struct dw_dma_controller *dmac)
+{
+	struct dw_dma_channel *chan;
+	unsigned long status, chanid;
+
+	status = dmac_readl_lo(dmac, STATUS_BLOCK);
+
+	while (status) {
+		struct dma_request *req;
+		chanid = __ffs(status);
+		chan = &dmac->channel[chanid];
+
+                if (chan->is_cyclic) {
+			BUG_ON(!chan->req_cyclic
+			       || !chan->req_cyclic->req.block_complete);
+			req = &chan->req_cyclic->req;
+                } else {
+			BUG_ON(!chan->req_sg || !chan->req_sg->req.block_complete);
+			req = &chan->req_sg->req;
+                }
+		dmac_writel_lo(dmac, CLEAR_BLOCK, 1 << chanid);
+		req->block_complete(req);
+		status = dmac_readl_lo(dmac, STATUS_BLOCK);
+	}
+}
+
+static void dmac_xfer_complete(struct dw_dma_controller *dmac)
+{
+	struct dw_dma_channel *chan;
+	struct dma_request *req;
+	unsigned long status, chanid;
+
+	status = dmac_readl_lo(dmac, STATUS_XFER);
+
+	while (status) {
+		chanid = __ffs(status);
+		chan = &dmac->channel[chanid];
+
+		dmac_writel_lo(dmac, CLEAR_XFER, 1 << chanid);
+
+                req = &chan->req_sg->req;
+                BUG_ON(!req);
+                cleanup_channel(dmac, chan);
+                if (req->xfer_complete)
+			req->xfer_complete(req);
+
+		status = dmac_readl_lo(dmac, STATUS_XFER);
+	}
+}
+
+static void dmac_error(struct dw_dma_controller *dmac)
+{
+	struct dw_dma_channel *chan;
+	unsigned long status, chanid;
+
+	status = dmac_readl_lo(dmac, STATUS_ERROR);
+
+	while (status) {
+		struct dma_request *req;
+
+		chanid = __ffs(status);
+		chan = &dmac->channel[chanid];
+
+		dmac_writel_lo(dmac, CLEAR_ERROR, 1 << chanid);
+		clear_channel_bit(dmac, CH_EN, chanid);
+
+                if (chan->is_cyclic) {
+			BUG_ON(!chan->req_cyclic);
+			req = &chan->req_cyclic->req;
+                } else {
+			BUG_ON(!chan->req_sg);
+			req = &chan->req_sg->req;
+                }
+
+		cleanup_channel(dmac, chan);
+		if (req->error)
+			req->error(req);
+
+		status = dmac_readl_lo(dmac, STATUS_XFER);
+	}
+}
+
+static irqreturn_t dmac_interrupt(int irq, void *dev_id)
+{
+	struct dw_dma_controller *dmac = dev_id;
+	unsigned long status;
+	int ret = IRQ_NONE;
+
+	spin_lock(&dmac->lock);
+
+	status = dmac_readl_lo(dmac, STATUS_INT);
+
+	while (status) {
+		ret = IRQ_HANDLED;
+		if (status & 0x10)
+			dmac_error(dmac);
+		if (status & 0x02)
+			dmac_block_complete(dmac);
+		if (status & 0x01)
+			dmac_xfer_complete(dmac);
+
+		status = dmac_readl_lo(dmac, STATUS_INT);
+	}
+
+	spin_unlock(&dmac->lock);
+	return ret;
+}
+
+static int __devinit dmac_probe(struct platform_device *pdev)
+{
+	struct dw_dma_controller *dmac;
+	struct resource *regs;
+	int ret;
+
+	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!regs)
+		return -ENXIO;
+
+	dmac = kmalloc(sizeof(*dmac), GFP_KERNEL);
+	if (!dmac)
+		return -ENOMEM;
+	memset(dmac, 0, sizeof(*dmac));
+
+	dmac->hclk = clk_get(&pdev->dev, "hclk");
+	if (IS_ERR(dmac->hclk)) {
+		ret = PTR_ERR(dmac->hclk);
+		goto out_free_dmac;
+	}
+	clk_enable(dmac->hclk);
+
+	ret = -ENOMEM;
+	dmac->lli_pool = dma_pool_create("dmac", &pdev->dev,
+					 sizeof(struct dw_dma_lli), 4, 0);
+	if (!dmac->lli_pool)
+		goto out_disable_clk;
+
+	spin_lock_init(&dmac->lock);
+	dmac->dma.dev = &pdev->dev;
+	dmac->dma.alloc_channel = dmac_alloc_channel;
+	dmac->dma.release_channel = dmac_release_channel;
+	dmac->dma.prepare_request_sg = dmac_prepare_request_sg;
+	dmac->dma.prepare_request_cyclic = dmac_prepare_request_cyclic;
+	dmac->dma.start_request = dmac_start_request;
+	dmac->dma.stop_request = dmac_stop_request;
+	dmac->dma.get_current_pos = dmac_get_current_pos;
+
+	dmac->regs = ioremap(regs->start, regs->end - regs->start + 1);
+	if (!dmac->regs)
+		goto out_free_pool;
+
+	ret = request_irq(platform_get_irq(pdev, 0), dmac_interrupt,
+			  SA_SAMPLE_RANDOM, pdev->name, dmac);
+	if (ret)
+		goto out_unmap_regs;
+
+	/* Enable the DMA controller */
+	dmac_writel_lo(dmac, CFG, 1);
+
+	register_dma_controller(&dmac->dma);
+
+	printk(KERN_INFO
+	       "dmac%d: DesignWare DMA controller at 0x%p irq %d\n",
+	       dmac->dma.id, dmac->regs, platform_get_irq(pdev, 0));
+
+	return 0;
+
+out_unmap_regs:
+	iounmap(dmac->regs);
+out_free_pool:
+	dma_pool_destroy(dmac->lli_pool);
+out_disable_clk:
+	clk_disable(dmac->hclk);
+	clk_put(dmac->hclk);
+out_free_dmac:
+	kfree(dmac);
+	return ret;
+}
+
+static struct platform_driver dmac_driver = {
+	.probe		= dmac_probe,
+	.driver		= {
+		.name		= "dmaca",
+	},
+};
+
+static int __init dmac_init(void)
+{
+	return platform_driver_register(&dmac_driver);
+}
+subsys_initcall(dmac_init);
+
+static void __exit dmac_exit(void)
+{
+	platform_driver_unregister(&dmac_driver);
+}
+module_exit(dmac_exit);
+
+MODULE_DESCRIPTION("Synopsys DesignWare DMA Controller driver");
+MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>");
+MODULE_LICENSE("GPL");
diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/drivers/dw-dmac.h avr32-git/arch/avr32/drivers/dw-dmac.h
--- linux-2.6.21.3/arch/avr32/drivers/dw-dmac.h	1970-01-01 01:00:00.000000000 +0100
+++ avr32-git/arch/avr32/drivers/dw-dmac.h	2007-06-06 11:33:46.000000000 +0200
@@ -0,0 +1,42 @@
+/*
+ * Driver for the Synopsys DesignWare DMA Controller
+ *
+ * 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.
+ */
+#ifndef __AVR32_DW_DMAC_H__
+#define __AVR32_DW_DMAC_H__
+
+#define DW_DMAC_CFG		0x398
+#define DW_DMAC_CH_EN		0x3a0
+
+#define DW_DMAC_STATUS_XFER	0x2e8
+#define DW_DMAC_STATUS_BLOCK	0x2f0
+#define DW_DMAC_STATUS_ERROR	0x308
+
+#define DW_DMAC_MASK_XFER	0x310
+#define DW_DMAC_MASK_BLOCK	0x318
+#define DW_DMAC_MASK_ERROR	0x330
+
+#define DW_DMAC_CLEAR_XFER	0x338
+#define DW_DMAC_CLEAR_BLOCK	0x340
+#define DW_DMAC_CLEAR_ERROR	0x358
+
+#define DW_DMAC_STATUS_INT	0x360
+
+#define DW_DMAC_CHAN_SAR	0x000
+#define DW_DMAC_CHAN_DAR	0x008
+#define DW_DMAC_CHAN_LLP	0x010
+#define DW_DMAC_CHAN_CTL	0x018
+#define DW_DMAC_CHAN_SSTAT	0x020
+#define DW_DMAC_CHAN_DSTAT	0x028
+#define DW_DMAC_CHAN_SSTATAR	0x030
+#define DW_DMAC_CHAN_DSTATAR	0x038
+#define DW_DMAC_CHAN_CFG	0x040
+#define DW_DMAC_CHAN_SGR	0x048
+#define DW_DMAC_CHAN_DSR	0x050
+
+#endif /* __AVR32_DW_DMAC_H__ */
diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/drivers/Makefile avr32-git/arch/avr32/drivers/Makefile
--- linux-2.6.21.3/arch/avr32/drivers/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ avr32-git/arch/avr32/drivers/Makefile	2007-06-06 11:33:46.000000000 +0200
@@ -0,0 +1 @@
+obj-$(CONFIG_DW_DMAC)			+= dw-dmac.o
diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/Kconfig avr32-git/arch/avr32/Kconfig
--- linux-2.6.21.3/arch/avr32/Kconfig	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/arch/avr32/Kconfig	2007-06-06 11:33:46.000000000 +0200
@@ -57,9 +57,6 @@
 	bool
 	default n
 
-config GENERIC_BUST_SPINLOCK
-	bool
-
 config GENERIC_HWEIGHT
 	bool
 	default y
@@ -68,6 +65,11 @@
 	bool
 	default y
 
+config GENERIC_BUG
+	bool
+	default y
+	depends on BUG
+
 source "init/Kconfig"
 
 menu "System Type and features"
@@ -106,6 +108,9 @@
 config BOARD_ATSTK1000
 	bool "ATSTK1000 evaluation board"
 	select BOARD_ATSTK1002 if CPU_AT32AP7000
+
+config BOARD_ATNGW100
+	bool "ATNGW100 Network Gateway"
 endchoice
 
 choice
@@ -116,6 +121,8 @@
 	bool "U-Boot (or similar) bootloader"
 endchoice
 
+source "arch/avr32/mach-at32ap/Kconfig"
+
 config LOAD_ADDRESS
 	hex
 	default 0x10000000 if LOADER_U_BOOT=y && CPU_AT32AP7000=y
@@ -164,6 +171,10 @@
 	  enabling Nexus-compliant debuggers to keep track of the PID of the
 	  currently executing task.
 
+config DW_DMAC
+	tristate "Synopsys DesignWare DMA Controller support"
+	default y if CPU_AT32AP7000
+
 # FPU emulation goes here
 
 source "kernel/Kconfig.hz"
diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/kernel/cpu.c avr32-git/arch/avr32/kernel/cpu.c
--- linux-2.6.21.3/arch/avr32/kernel/cpu.c	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/arch/avr32/kernel/cpu.c	2007-06-06 11:33:46.000000000 +0200
@@ -209,16 +209,17 @@
 void __init setup_processor(void)
 {
 	unsigned long config0, config1;
+	unsigned long features;
 	unsigned cpu_id, cpu_rev, arch_id, arch_rev, mmu_type;
 	unsigned tmp;
 
-	config0 = sysreg_read(CONFIG0); /* 0x0000013e; */
-	config1 = sysreg_read(CONFIG1); /* 0x01f689a2; */
-	cpu_id = config0 >> 24;
-	cpu_rev = (config0 >> 16) & 0xff;
-	arch_id = (config0 >> 13) & 0x07;
-	arch_rev = (config0 >> 10) & 0x07;
-	mmu_type = (config0 >> 7) & 0x03;
+	config0 = sysreg_read(CONFIG0);
+	config1 = sysreg_read(CONFIG1);
+	cpu_id = SYSREG_BFEXT(PROCESSORID, config0);
+	cpu_rev = SYSREG_BFEXT(PROCESSORREVISION, config0);
+	arch_id = SYSREG_BFEXT(AT, config0);
+	arch_rev = SYSREG_BFEXT(AR, config0);
+	mmu_type = SYSREG_BFEXT(MMUT, config0);
 
 	boot_cpu_data.arch_type = arch_id;
 	boot_cpu_data.cpu_type = cpu_id;
@@ -226,16 +227,16 @@
 	boot_cpu_data.cpu_revision = cpu_rev;
 	boot_cpu_data.tlb_config = mmu_type;
 
-	tmp = (config1 >> 13) & 0x07;
+	tmp = SYSREG_BFEXT(ILSZ, config1);
 	if (tmp) {
-		boot_cpu_data.icache.ways = 1 << ((config1 >> 10) & 0x07);
-		boot_cpu_data.icache.sets = 1 << ((config1 >> 16) & 0x0f);
+		boot_cpu_data.icache.ways = 1 << SYSREG_BFEXT(IASS, config1);
+		boot_cpu_data.icache.sets = 1 << SYSREG_BFEXT(ISET, config1);
 		boot_cpu_data.icache.linesz = 1 << (tmp + 1);
 	}
-	tmp = (config1 >> 3) & 0x07;
+	tmp = SYSREG_BFEXT(DLSZ, config1);
 	if (tmp) {
-		boot_cpu_data.dcache.ways = 1 << (config1 & 0x07);
-		boot_cpu_data.dcache.sets = 1 << ((config1 >> 6) & 0x0f);
+		boot_cpu_data.dcache.ways = 1 << SYSREG_BFEXT(DASS, config1);
+		boot_cpu_data.dcache.sets = 1 << SYSREG_BFEXT(DSET, config1);
 		boot_cpu_data.dcache.linesz = 1 << (tmp + 1);
 	}
 
@@ -250,16 +251,39 @@
 		cpu_names[cpu_id], cpu_id, cpu_rev,
 		arch_names[arch_id], arch_rev);
 	printk ("CPU: MMU configuration: %s\n", mmu_types[mmu_type]);
+
 	printk ("CPU: features:");
-	if (config0 & (1 << 6))
-		printk(" fpu");
-	if (config0 & (1 << 5))
-		printk(" java");
-	if (config0 & (1 << 4))
-		printk(" perfctr");
-	if (config0 & (1 << 3))
+	features = 0;
+	if (config0 & SYSREG_BIT(CONFIG0_R)) {
+		features |= AVR32_FEATURE_RMW;
+		printk(" rmw");
+	}
+	if (config0 & SYSREG_BIT(CONFIG0_D)) {
+		features |= AVR32_FEATURE_DSP;
+		printk(" dsp");
+	}
+	if (config0 & SYSREG_BIT(CONFIG0_S)) {
+		features |= AVR32_FEATURE_SIMD;
+		printk(" simd");
+	}
+	if (config0 & SYSREG_BIT(CONFIG0_O)) {
+		features |= AVR32_FEATURE_OCD;
 		printk(" ocd");
+	}
+	if (config0 & SYSREG_BIT(CONFIG0_P)) {
+		features |= AVR32_FEATURE_PCTR;
+		printk(" perfctr");
+	}
+	if (config0 & SYSREG_BIT(CONFIG0_J)) {
+		features |= AVR32_FEATURE_JAVA;
+		printk(" java");
+	}
+	if (config0 & SYSREG_BIT(CONFIG0_F)) {
+		features |= AVR32_FEATURE_FPU;
+		printk(" fpu");
+	}
 	printk("\n");
+	boot_cpu_data.features = features;
 }
 
 #ifdef CONFIG_PROC_FS
diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/kernel/dma-controller.c avr32-git/arch/avr32/kernel/dma-controller.c
--- linux-2.6.21.3/arch/avr32/kernel/dma-controller.c	1970-01-01 01:00:00.000000000 +0100
+++ avr32-git/arch/avr32/kernel/dma-controller.c	2007-06-06 11:33:46.000000000 +0200
@@ -0,0 +1,34 @@
+/*
+ * Preliminary DMA controller framework for AVR32
+ *
+ * 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 <asm/dma-controller.h>
+
+static LIST_HEAD(controllers);
+
+int register_dma_controller(struct dma_controller *dmac)
+{
+	static int next_id;
+
+	dmac->id = next_id++;
+	list_add_tail(&dmac->list, &controllers);
+
+	return 0;
+}
+EXPORT_SYMBOL(register_dma_controller);
+
+struct dma_controller *find_dma_controller(int id)
+{
+	struct dma_controller *dmac;
+
+	list_for_each_entry(dmac, &controllers, list)
+		if (dmac->id == id)
+			return dmac;
+	return NULL;
+}
+EXPORT_SYMBOL(find_dma_controller);
diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/kernel/entry-avr32b.S avr32-git/arch/avr32/kernel/entry-avr32b.S
--- linux-2.6.21.3/arch/avr32/kernel/entry-avr32b.S	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/arch/avr32/kernel/entry-avr32b.S	2007-06-06 11:33:46.000000000 +0200
@@ -100,55 +100,49 @@
 
 	.global	tlb_miss_common
 tlb_miss_common:
-	mfsr	r0, SYSREG_PTBR
-	mfsr	r1, SYSREG_TLBEAR
+	mfsr	r0, SYSREG_TLBEAR
+	mfsr	r1, SYSREG_PTBR
 
 	/* Is it the vmalloc space? */
-	bld	r1, 31
+	bld	r0, 31
 	brcs	handle_vmalloc_miss
 
 	/* First level lookup */
 pgtbl_lookup:
-	lsr	r2, r1, PGDIR_SHIFT
-	ld.w	r0, r0[r2 << 2]
-	bld	r0, _PAGE_BIT_PRESENT
+	lsr	r2, r0, PGDIR_SHIFT
+	ld.w	r3, r1[r2 << 2]
+	bfextu	r1, r0, PAGE_SHIFT, PGDIR_SHIFT - PAGE_SHIFT
+	bld	r3, _PAGE_BIT_PRESENT
 	brcc	page_table_not_present
 
-	/* TODO: Check access rights on page table if necessary */
-
 	/* Translate to virtual address in P1. */
-	andl	r0, 0xf000
-	sbr	r0, 31
+	andl	r3, 0xf000
+	sbr	r3, 31
 
 	/* Second level lookup */
-	lsl	r1, (32 - PGDIR_SHIFT)
-	lsr	r1, (32 - PGDIR_SHIFT) + PAGE_SHIFT
-	add	r2, r0, r1 << 2
-	ld.w	r1, r2[0]
-	bld	r1, _PAGE_BIT_PRESENT
+	ld.w	r2, r3[r1 << 2]
+	mfsr	r0, SYSREG_TLBARLO
+	bld	r2, _PAGE_BIT_PRESENT
 	brcc	page_not_present
 
 	/* Mark the page as accessed */
-	sbr	r1, _PAGE_BIT_ACCESSED
-	st.w	r2[0], r1
+	sbr	r2, _PAGE_BIT_ACCESSED
+	st.w	r3[r1 << 2], r2
 
 	/* Drop software flags */
-	andl	r1, _PAGE_FLAGS_HARDWARE_MASK & 0xffff
-	mtsr	SYSREG_TLBELO, r1
+	andl	r2, _PAGE_FLAGS_HARDWARE_MASK & 0xffff
+	mtsr	SYSREG_TLBELO, r2
 
 	/* Figure out which entry we want to replace */
-	mfsr	r0, SYSREG_TLBARLO
+	mfsr	r1, SYSREG_MMUCR
 	clz	r2, r0
 	brcc	1f
-	mov	r1, -1			/* All entries have been accessed, */
-	mtsr	SYSREG_TLBARLO, r1	/* so reset TLBAR */
-	mov	r2, 0			/* and start at 0 */
-1:	mfsr	r1, SYSREG_MMUCR
-	lsl	r2, 14
-	andl	r1, 0x3fff, COH
-	or	r1, r2
-	mtsr	SYSREG_MMUCR, r1
+	mov	r3, -1			/* All entries have been accessed, */
+	mov	r2, 0			/* so start at 0 */
+	mtsr	SYSREG_TLBARLO, r3	/* and reset TLBAR */
 
+1:	bfins	r1, r2, SYSREG_DRP_OFFSET, SYSREG_DRP_SIZE
+	mtsr	SYSREG_MMUCR, r1
 	tlbw
 
 	tlbmiss_restore
@@ -156,8 +150,8 @@
 
 handle_vmalloc_miss:
 	/* Simply do the lookup in init's page table */
-	mov	r0, lo(swapper_pg_dir)
-	orh	r0, hi(swapper_pg_dir)
+	mov	r1, lo(swapper_pg_dir)
+	orh	r1, hi(swapper_pg_dir)
 	rjmp	pgtbl_lookup
 
 
@@ -340,12 +334,34 @@
 do_nmi_ll:
 	sub	sp, 4
 	stmts	--sp, r0-lr
-	/* FIXME: Make sure RAR_NMI and RSR_NMI are pushed instead of *_EX */
-	rcall	save_full_context_ex
+	mfsr	r9, SYSREG_RSR_NMI
+	mfsr	r8, SYSREG_RAR_NMI
+	bfextu	r0, r9, MODE_SHIFT, 3
+	brne	2f
+
+1:	pushm	r8, r9	/* PC and SR */
 	mfsr	r12, SYSREG_ECR
 	mov	r11, sp
 	rcall	do_nmi
-	rjmp	bad_return
+	popm	r8-r9
+	mtsr	SYSREG_RAR_NMI, r8
+	tst	r0, r0
+	mtsr	SYSREG_RSR_NMI, r9
+	brne	3f
+
+	ldmts	sp++, r0-lr
+	sub	sp, -4		/* skip r12_orig */
+	rete
+
+2:	sub	r10, sp, -(FRAME_SIZE_FULL - REG_LR)
+	stdsp	sp[4], r10	/* replace saved SP */
+	rjmp	1b
+
+3:	popm	lr
+	sub	sp, -4		/* skip sp */
+	popm	r0-r12
+	sub	sp, -4		/* skip r12_orig */
+	rete
 
 handle_address_fault:
 	sub	sp, 4
@@ -630,9 +646,12 @@
 	rcall	do_IRQ
 
 	lddsp	r4, sp[REG_SR]
-	andh	r4, (MODE_MASK >> 16), COH
+	bfextu	r4, r4, SYSREG_M0_OFFSET, 3
+	cp.w	r4, MODE_SUPERVISOR >> SYSREG_M0_OFFSET
+	breq	2f
+	cp.w	r4, MODE_USER >> SYSREG_M0_OFFSET
 #ifdef CONFIG_PREEMPT
-	brne	2f
+	brne	3f
 #else
 	brne	1f
 #endif
@@ -649,9 +668,18 @@
 	sub	sp, -4		/* ignore r12_orig */
 	rete
 
+2:	get_thread_info	r0
+	ld.w	r1, r0[TI_flags]
+	bld	r1, TIF_CPU_GOING_TO_SLEEP
 #ifdef CONFIG_PREEMPT
-2:
-	get_thread_info	r0
+	brcc	3f
+#else
+	brcc	1b
+#endif
+	sub	r1, pc, . - cpu_idle_skip_sleep
+	stdsp	sp[REG_PC], r1
+#ifdef CONFIG_PREEMPT
+3:	get_thread_info r0
 	ld.w	r2, r0[TI_preempt_count]
 	cp.w	r2, 0
 	brne	1b
@@ -662,12 +690,32 @@
 	bld	r4, SYSREG_GM_OFFSET
 	brcs	1b
 	rcall	preempt_schedule_irq
-	rjmp	1b
 #endif
+	rjmp	1b
 	.endm
 
 	.section .irq.text,"ax",@progbits
 
+.global cpu_idle_sleep
+cpu_idle_sleep:
+	mask_interrupts
+	get_thread_info r8
+	ld.w	r9, r8[TI_flags]
+	bld	r9, TIF_NEED_RESCHED
+	brcs	cpu_idle_enable_int_and_exit
+	sbr	r9, TIF_CPU_GOING_TO_SLEEP
+	st.w	r8[TI_flags], r9
+	unmask_interrupts
+	sleep 0
+cpu_idle_skip_sleep:
+	mask_interrupts
+	ld.w	r9, r8[TI_flags]
+	cbr	r9, TIF_CPU_GOING_TO_SLEEP
+	st.w	r8[TI_flags], r9
+cpu_idle_enable_int_and_exit:
+	unmask_interrupts
+	retal	r12
+
 	.global	irq_level0
 	.global	irq_level1
 	.global	irq_level2
diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/kernel/irq.c avr32-git/arch/avr32/kernel/irq.c
--- linux-2.6.21.3/arch/avr32/kernel/irq.c	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/arch/avr32/kernel/irq.c	2007-06-06 11:33:46.000000000 +0200
@@ -7,15 +7,6 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * This file contains the code used by various IRQ handling routines:
- * asking for different IRQ's should be done through these routines
- * instead of just grabbing them. Thus setups with different IRQ numbers
- * shouldn't result in any weird surprises, and installing new handlers
- * should be easier.
- *
- * IRQ's are in fact implemented a bit like signal handlers for the kernel.
- * Naturally it's not a 1:1 relation, but there are similarities.
  */
 
 #include <linux/interrupt.h>
diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/kernel/kprobes.c avr32-git/arch/avr32/kernel/kprobes.c
--- linux-2.6.21.3/arch/avr32/kernel/kprobes.c	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/arch/avr32/kernel/kprobes.c	2007-06-06 11:33:46.000000000 +0200
@@ -179,7 +179,7 @@
 	return 1;
 }
 
-static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 {
 	struct kprobe *cur = kprobe_running();
 
@@ -216,11 +216,6 @@
 		if (post_kprobe_handler(args->regs))
 			ret = NOTIFY_STOP;
 		break;
-	case DIE_FAULT:
-		if (kprobe_running()
-		    && kprobe_fault_handler(args->regs, args->trapnr))
-			ret = NOTIFY_STOP;
-		break;
 	default:
 		break;
 	}
diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/kernel/Makefile avr32-git/arch/avr32/kernel/Makefile
--- linux-2.6.21.3/arch/avr32/kernel/Makefile	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/arch/avr32/kernel/Makefile	2007-06-06 11:33:46.000000000 +0200
@@ -9,6 +9,7 @@
 obj-y				+= setup.o traps.o semaphore.o ptrace.o
 obj-y				+= signal.o sys_avr32.o process.o time.o
 obj-y				+= init_task.o switch_to.o cpu.o
+obj-y				+= dma-controller.o
 obj-$(CONFIG_MODULES)		+= module.o avr32_ksyms.o
 obj-$(CONFIG_KPROBES)		+= kprobes.o
 
diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/kernel/module.c avr32-git/arch/avr32/kernel/module.c
--- linux-2.6.21.3/arch/avr32/kernel/module.c	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/arch/avr32/kernel/module.c	2007-06-06 11:33:46.000000000 +0200
@@ -12,10 +12,11 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/moduleloader.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
+#include <linux/bug.h>
 #include <linux/elf.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleloader.h>
 #include <linux/vmalloc.h>
 
 void *module_alloc(unsigned long size)
@@ -315,10 +316,10 @@
 	vfree(module->arch.syminfo);
 	module->arch.syminfo = NULL;
 
-	return 0;
+	return module_bug_finalize(hdr, sechdrs, module);
 }
 
 void module_arch_cleanup(struct module *module)
 {
-
+	module_bug_cleanup(module);
 }
diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/kernel/process.c avr32-git/arch/avr32/kernel/process.c
--- linux-2.6.21.3/arch/avr32/kernel/process.c	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/arch/avr32/kernel/process.c	2007-06-06 11:33:46.000000000 +0200
@@ -11,6 +11,7 @@
 #include <linux/fs.h>
 #include <linux/ptrace.h>
 #include <linux/reboot.h>
+#include <linux/uaccess.h>
 #include <linux/unistd.h>
 
 #include <asm/sysreg.h>
@@ -19,6 +20,8 @@
 void (*pm_power_off)(void) = NULL;
 EXPORT_SYMBOL(pm_power_off);
 
+extern void cpu_idle_sleep(void);
+
 /*
  * This file handles the architecture-dependent parts of process handling..
  */
@@ -27,9 +30,8 @@
 {
 	/* endless idle loop with no priority at all */
 	while (1) {
-		/* TODO: Enter sleep mode */
 		while (!need_resched())
-			cpu_relax();
+			cpu_idle_sleep();
 		preempt_enable_no_resched();
 		schedule();
 		preempt_disable();
@@ -114,39 +116,178 @@
 	/* do nothing */
 }
 
+static void dump_mem(const char *str, const char *log_lvl,
+		     unsigned long bottom, unsigned long top)
+{
+	unsigned long p;
+	int i;
+
+	printk("%s%s(0x%08lx to 0x%08lx)\n", log_lvl, str, bottom, top);
+
+	for (p = bottom & ~31; p < top; ) {
+		printk("%s%04lx: ", log_lvl, p & 0xffff);
+
+		for (i = 0; i < 8; i++, p += 4) {
+			unsigned int val;
+
+			if (p < bottom || p >= top)
+				printk("         ");
+			else {
+				if (__get_user(val, (unsigned int __user *)p)) {
+					printk("\n");
+					goto out;
+				}
+				printk("%08x ", val);
+			}
+		}
+		printk("\n");
+	}
+
+out:
+	return;
+}
+
+static inline int valid_stack_ptr(struct thread_info *tinfo, unsigned long p)
+{
+	return (p > (unsigned long)tinfo)
+		&& (p < (unsigned long)tinfo + THREAD_SIZE - 3);
+}
+
+#ifdef CONFIG_FRAME_POINTER
+static void show_trace_log_lvl(struct task_struct *tsk, unsigned long *sp,
+			       struct pt_regs *regs, const char *log_lvl)
+{
+	unsigned long lr, fp;
+	struct thread_info *tinfo;
+
+	if (regs)
+		fp = regs->r7;
+	else if (tsk == current)
+		asm("mov %0, r7" : "=r"(fp));
+	else
+		fp = tsk->thread.cpu_context.r7;
+
+	/*
+	 * Walk the stack as long as the frame pointer (a) is within
+	 * the kernel stack of the task, and (b) it doesn't move
+	 * downwards.
+	 */
+	tinfo = task_thread_info(tsk);
+	printk("%sCall trace:\n", log_lvl);
+	while (valid_stack_ptr(tinfo, fp)) {
+		unsigned long new_fp;
+
+		lr = *(unsigned long *)fp;
+#ifdef CONFIG_KALLSYMS
+		printk("%s [<%08lx>] ", log_lvl, lr);
+#else
+		printk(" [<%08lx>] ", lr);
+#endif
+		print_symbol("%s\n", lr);
+
+		new_fp = *(unsigned long *)(fp + 4);
+		if (new_fp <= fp)
+			break;
+		fp = new_fp;
+	}
+	printk("\n");
+}
+#else
+static void show_trace_log_lvl(struct task_struct *tsk, unsigned long *sp,
+			       struct pt_regs *regs, const char *log_lvl)
+{
+	unsigned long addr;
+
+	printk("%sCall trace:\n", log_lvl);
+
+	while (!kstack_end(sp)) {
+		addr = *sp++;
+		if (kernel_text_address(addr)) {
+#ifdef CONFIG_KALLSYMS
+			printk("%s [<%08lx>] ", log_lvl, addr);
+#else
+			printk(" [<%08lx>] ", addr);
+#endif
+			print_symbol("%s\n", addr);
+		}
+	}
+	printk("\n");
+}
+#endif
+
+void show_stack_log_lvl(struct task_struct *tsk, unsigned long sp,
+			struct pt_regs *regs, const char *log_lvl)
+{
+	struct thread_info *tinfo;
+
+	if (sp == 0) {
+		if (tsk)
+			sp = tsk->thread.cpu_context.ksp;
+		else
+			sp = (unsigned long)&tinfo;
+	}
+	if (!tsk)
+		tsk = current;
+
+	tinfo = task_thread_info(tsk);
+
+	if (valid_stack_ptr(tinfo, sp)) {
+		dump_mem("Stack: ", log_lvl, sp,
+			 THREAD_SIZE + (unsigned long)tinfo);
+		show_trace_log_lvl(tsk, (unsigned long *)sp, regs, log_lvl);
+	}
+}
+
+void show_stack(struct task_struct *tsk, unsigned long *stack)
+{
+	show_stack_log_lvl(tsk, (unsigned long)stack, NULL, "");
+}
+
+void dump_stack(void)
+{
+	unsigned long stack;
+
+	show_trace_log_lvl(current, &stack, NULL, "");
+}
+EXPORT_SYMBOL(dump_stack);
+
 static const char *cpu_modes[] = {
 	"Application", "Supervisor", "Interrupt level 0", "Interrupt level 1",
 	"Interrupt level 2", "Interrupt level 3", "Exception", "NMI"
 };
 
-void show_regs(struct pt_regs *regs)
+void show_regs_log_lvl(struct pt_regs *regs, const char *log_lvl)
 {
 	unsigned long sp = regs->sp;
 	unsigned long lr = regs->lr;
 	unsigned long mode = (regs->sr & MODE_MASK) >> MODE_SHIFT;
 
-	if (!user_mode(regs))
+	if (!user_mode(regs)) {
 		sp = (unsigned long)regs + FRAME_SIZE_FULL;
 
-	print_symbol("PC is at %s\n", instruction_pointer(regs));
-	print_symbol("LR is at %s\n", lr);
-	printk("pc : [<%08lx>]    lr : [<%08lx>]    %s\n"
-	       "sp : %08lx  r12: %08lx  r11: %08lx\n",
-	       instruction_pointer(regs),
-	       lr, print_tainted(), sp, regs->r12, regs->r11);
-	printk("r10: %08lx  r9 : %08lx  r8 : %08lx\n",
-	       regs->r10, regs->r9, regs->r8);
-	printk("r7 : %08lx  r6 : %08lx  r5 : %08lx  r4 : %08lx\n",
-	       regs->r7, regs->r6, regs->r5, regs->r4);
-	printk("r3 : %08lx  r2 : %08lx  r1 : %08lx  r0 : %08lx\n",
-	       regs->r3, regs->r2, regs->r1, regs->r0);
-	printk("Flags: %c%c%c%c%c\n",
+		printk("%s", log_lvl);
+		print_symbol("PC is at %s\n", instruction_pointer(regs));
+		printk("%s", log_lvl);
+		print_symbol("LR is at %s\n", lr);
+	}
+
+	printk("%spc : [<%08lx>]    lr : [<%08lx>]    %s\n"
+	       "%ssp : %08lx  r12: %08lx  r11: %08lx\n",
+	       log_lvl, instruction_pointer(regs), lr, print_tainted(),
+	       log_lvl, sp, regs->r12, regs->r11);
+	printk("%sr10: %08lx  r9 : %08lx  r8 : %08lx\n",
+	       log_lvl, regs->r10, regs->r9, regs->r8);
+	printk("%sr7 : %08lx  r6 : %08lx  r5 : %08lx  r4 : %08lx\n",
+	       log_lvl, regs->r7, regs->r6, regs->r5, regs->r4);
+	printk("%sr3 : %08lx  r2 : %08lx  r1 : %08lx  r0 : %08lx\n",
+	       log_lvl, regs->r3, regs->r2, regs->r1, regs->r0);
+	printk("%sFlags: %c%c%c%c%c\n", log_lvl,
 	       regs->sr & SR_Q ? 'Q' : 'q',
 	       regs->sr & SR_V ? 'V' : 'v',
 	       regs->sr & SR_N ? 'N' : 'n',
 	       regs->sr & SR_Z ? 'Z' : 'z',
 	       regs->sr & SR_C ? 'C' : 'c');
-	printk("Mode bits: %c%c%c%c%c%c%c%c%c\n",
+	printk("%sMode bits: %c%c%c%c%c%c%c%c%c\n", log_lvl,
 	       regs->sr & SR_H ? 'H' : 'h',
 	       regs->sr & SR_R ? 'R' : 'r',
 	       regs->sr & SR_J ? 'J' : 'j',
@@ -156,9 +297,21 @@
 	       regs->sr & SR_I1M ? '1' : '.',
 	       regs->sr & SR_I0M ? '0' : '.',
 	       regs->sr & SR_GM ? 'G' : 'g');
-	printk("CPU Mode: %s\n", cpu_modes[mode]);
+	printk("%sCPU Mode: %s\n", log_lvl, cpu_modes[mode]);
+	printk("%sProcess: %s [%d] (task: %p thread: %p)\n",
+	       log_lvl, current->comm, current->pid, current,
+	       task_thread_info(current));
+}
+
+void show_regs(struct pt_regs *regs)
+{
+	unsigned long sp = regs->sp;
+
+	if (!user_mode(regs))
+		sp = (unsigned long)regs + FRAME_SIZE_FULL;
 
-	show_trace(NULL, (unsigned long *)sp, regs);
+	show_regs_log_lvl(regs, "");
+	show_trace_log_lvl(current, (unsigned long *)sp, regs, "");
 }
 EXPORT_SYMBOL(show_regs);
 
diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/kernel/setup.c avr32-git/arch/avr32/kernel/setup.c
--- linux-2.6.21.3/arch/avr32/kernel/setup.c	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/arch/avr32/kernel/setup.c	2007-06-06 11:33:46.000000000 +0200
@@ -8,12 +8,14 @@
 
 #include <linux/clk.h>
 #include <linux/init.h>
+#include <linux/initrd.h>
 #include <linux/sched.h>
 #include <linux/console.h>
 #include <linux/ioport.h>
 #include <linux/bootmem.h>
 #include <linux/fs.h>
 #include <linux/module.h>
+#include <linux/pfn.h>
 #include <linux/root_dev.h>
 #include <linux/cpu.h>
 #include <linux/kernel.h>
@@ -30,13 +32,6 @@
 extern int root_mountflags;
 
 /*
- * Bootloader-provided information about physical memory
- */
-struct tag_mem_range *mem_phys;
-struct tag_mem_range *mem_reserved;
-struct tag_mem_range *mem_ramdisk;
-
-/*
  * Initialize loops_per_jiffy as 5000000 (500MIPS).
  * Better make it too large than too small...
  */
@@ -48,48 +43,193 @@
 static char __initdata command_line[COMMAND_LINE_SIZE];
 
 /*
- * Should be more than enough, but if you have a _really_ complex
- * setup, you might need to increase the size of this...
+ * Standard memory resources
  */
-static struct tag_mem_range __initdata mem_range_cache[32];
-static unsigned mem_range_next_free;
+static struct resource __initdata kernel_data = {
+	.name	= "Kernel data",
+	.start	= 0,
+	.end	= 0,
+	.flags	= IORESOURCE_MEM,
+};
+static struct resource __initdata kernel_code = {
+	.name	= "Kernel code",
+	.start	= 0,
+	.end	= 0,
+	.flags	= IORESOURCE_MEM,
+	.sibling = &kernel_data,
+};
 
 /*
- * Standard memory resources
+ * Available system RAM and reserved regions as singly linked
+ * lists. These lists are traversed using the sibling pointer in
+ * struct resource and are kept sorted at all times.
  */
-static struct resource mem_res[] = {
-	{
-		.name	= "Kernel code",
-		.start	= 0,
-		.end	= 0,
-		.flags	= IORESOURCE_MEM
-	},
-	{
-		.name	= "Kernel data",
-		.start	= 0,
-		.end	= 0,
-		.flags	= IORESOURCE_MEM,
-	},
-};
+static struct resource *__initdata system_ram;
+static struct resource *__initdata reserved = &kernel_code;
+
+/*
+ * We need to allocate these before the bootmem allocator is up and
+ * running, so we need this "cache". 32 entries are probably enough
+ * for all but the most insanely complex systems.
+ */
+static struct resource __initdata res_cache[32];
+static unsigned int __initdata res_cache_next_free;
+
+static void __init resource_init(void)
+{
+	struct resource *mem, *res;
+	struct resource *new;
+
+	kernel_code.start = __pa(init_mm.start_code);
+
+	for (mem = system_ram; mem; mem = mem->sibling) {
+		new = alloc_bootmem_low(sizeof(struct resource));
+		memcpy(new, mem, sizeof(struct resource));
+
+		new->sibling = NULL;
+		if (request_resource(&iomem_resource, new))
+			printk(KERN_WARNING "Bad RAM resource %08x-%08x\n",
+			       mem->start, mem->end);
+	}
+
+	for (res = reserved; res; res = res->sibling) {
+		new = alloc_bootmem_low(sizeof(struct resource));
+		memcpy(new, res, sizeof(struct resource));
+
+		new->sibling = NULL;
+		if (insert_resource(&iomem_resource, new))
+			printk(KERN_WARNING
+			       "Bad reserved resource %s (%08x-%08x)\n",
+			       res->name, res->start, res->end);
+	}
+}
+
+static void __init
+add_physical_memory(resource_size_t start, resource_size_t end)
+{
+	struct resource *new, *next, **pprev;
+
+	for (pprev = &system_ram, next = system_ram; next;
+	     pprev = &next->sibling, next = next->sibling) {
+		if (end < next->start)
+			break;
+		if (start <= next->end) {
+			printk(KERN_WARNING
+			       "Warning: Physical memory map is broken\n");
+			printk(KERN_WARNING
+			       "Warning: %08x-%08x overlaps %08x-%08x\n",
+			       start, end, next->start, next->end);
+			return;
+		}
+	}
+
+	if (res_cache_next_free >= ARRAY_SIZE(res_cache)) {
+		printk(KERN_WARNING
+		       "Warning: Failed to add physical memory %08x-%08x\n",
+		       start, end);
+		return;
+	}
+
+	new = &res_cache[res_cache_next_free++];
+	new->start = start;
+	new->end = end;
+	new->name = "System RAM";
+	new->flags = IORESOURCE_MEM;
+
+	*pprev = new;
+}
+
+static int __init
+add_reserved_region(resource_size_t start, resource_size_t end,
+		    const char *name)
+{
+	struct resource *new, *next, **pprev;
+
+	if (end < start)
+		return -EINVAL;
+
+	if (res_cache_next_free >= ARRAY_SIZE(res_cache))
+		return -ENOMEM;
+
+	for (pprev = &reserved, next = reserved; next;
+	     pprev = &next->sibling, next = next->sibling) {
+		if (end < next->start)
+			break;
+		if (start <= next->end)
+			return -EBUSY;
+	}
+
+	new = &res_cache[res_cache_next_free++];
+	new->start = start;
+	new->end = end;
+	new->name = name;
+	new->flags = IORESOURCE_MEM;
 
-#define kernel_code	mem_res[0]
-#define kernel_data	mem_res[1]
+	*pprev = new;
+
+	return 0;
+}
+
+static unsigned long __init
+find_free_region(const struct resource *mem, resource_size_t size,
+		 resource_size_t align)
+{
+	struct resource *res;
+	unsigned long target;
+
+	target = ALIGN(mem->start, align);
+	for (res = reserved; res; res = res->sibling) {
+		if ((target + size) <= res->start)
+			break;
+		if (target <= res->end)
+			target = ALIGN(res->end + 1, align);
+	}
+
+	if ((target + size) > (mem->end + 1))
+		return mem->end + 1;
+
+	return target;
+}
+
+static int __init
+alloc_reserved_region(resource_size_t *start, resource_size_t size,
+		      resource_size_t align, const char *name)
+{
+	struct resource *mem;
+	resource_size_t target;
+	int ret;
+
+	for (mem = system_ram; mem; mem = mem->sibling) {
+		target = find_free_region(mem, size, align);
+		if (target <= mem->end) {
+			ret = add_reserved_region(target, target + size - 1,
+						  name);
+			if (!ret)
+				*start = target;
+			return ret;
+		}
+	}
+
+	return -ENOMEM;
+}
 
 /*
  * Early framebuffer allocation. Works as follows:
  *   - If fbmem_size is zero, nothing will be allocated or reserved.
  *   - If fbmem_start is zero when setup_bootmem() is called,
- *     fbmem_size bytes will be allocated from the bootmem allocator.
+ *     a block of fbmem_size bytes will be reserved before bootmem
+ *     initialization. It will be aligned to the largest page size
+ *     that fbmem_size is a multiple of.
  *   - If fbmem_start is nonzero, an area of size fbmem_size will be
- *     reserved at the physical address fbmem_start if necessary. If
- *     the area isn't in a memory region known to the kernel, it will
- *     be left alone.
+ *     reserved at the physical address fbmem_start if possible. If
+ *     it collides with other reserved memory, a different block of
+ *     same size will be allocated, just as if fbmem_start was zero.
  *
  * Board-specific code may use these variables to set up platform data
  * for the framebuffer driver if fbmem_size is nonzero.
  */
-static unsigned long __initdata fbmem_start;
-static unsigned long __initdata fbmem_size;
+resource_size_t __initdata fbmem_start;
+resource_size_t __initdata fbmem_size;
 
 /*
  * "fbmem=xxx[kKmM]" allocates the specified amount of boot memory for
@@ -103,48 +243,42 @@
  */
 static int __init early_parse_fbmem(char *p)
 {
+	int ret;
+	unsigned long align;
+
 	fbmem_size = memparse(p, &p);
-	if (*p == '@')
+	if (*p == '@') {
 		fbmem_start = memparse(p, &p);
-	return 0;
-}
-early_param("fbmem", early_parse_fbmem);
-
-static inline void __init resource_init(void)
-{
-	struct tag_mem_range *region;
-
-	kernel_code.start = __pa(init_mm.start_code);
-	kernel_code.end = __pa(init_mm.end_code - 1);
-	kernel_data.start = __pa(init_mm.end_code);
-	kernel_data.end = __pa(init_mm.brk - 1);
+		ret = add_reserved_region(fbmem_start,
+					  fbmem_start + fbmem_size - 1,
+					  "Framebuffer");
+		if (ret) {
+			printk(KERN_WARNING
+			       "Failed to reserve framebuffer memory\n");
+			fbmem_start = 0;
+		}
+	}
 
-	for (region = mem_phys; region; region = region->next) {
-		struct resource *res;
-		unsigned long phys_start, phys_end;
-
-		if (region->size == 0)
-			continue;
-
-		phys_start = region->addr;
-		phys_end = phys_start + region->size - 1;
-
-		res = alloc_bootmem_low(sizeof(*res));
-		res->name = "System RAM";
-		res->start = phys_start;
-		res->end = phys_end;
-		res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
-
-		request_resource (&iomem_resource, res);
-
-		if (kernel_code.start >= res->start &&
-		    kernel_code.end <= res->end)
-			request_resource (res, &kernel_code);
-		if (kernel_data.start >= res->start &&
-		    kernel_data.end <= res->end)
-			request_resource (res, &kernel_data);
+	if (!fbmem_start) {
+		if ((fbmem_size & 0x000fffffUL) == 0)
+			align = 0x100000;	/* 1 MiB */
+		else if ((fbmem_size & 0x0000ffffUL) == 0)
+			align = 0x10000;	/* 64 KiB */
+		else
+			align = 0x1000;		/* 4 KiB */
+
+		ret = alloc_reserved_region(&fbmem_start, fbmem_size,
+					    align, "Framebuffer");
+		if (ret) {
+			printk(KERN_WARNING
+			       "Failed to allocate framebuffer memory\n");
+			fbmem_size = 0;
+		}
 	}
+
+	return 0;
 }
+early_param("fbmem", early_parse_fbmem);
 
 static int __init parse_tag_core(struct tag *tag)
 {
@@ -157,11 +291,9 @@
 }
 __tagtable(ATAG_CORE, parse_tag_core);
 
-static int __init parse_tag_mem_range(struct tag *tag,
-				      struct tag_mem_range **root)
+static int __init parse_tag_mem(struct tag *tag)
 {
-	struct tag_mem_range *cur, **pprev;
-	struct tag_mem_range *new;
+	unsigned long start, end;
 
 	/*
 	 * Ignore zero-sized entries. If we're running standalone, the
@@ -171,34 +303,53 @@
 	if (tag->u.mem_range.size == 0)
 		return 0;
 
-	/*
-	 * Copy the data so the bootmem init code doesn't need to care
-	 * about it.
-	 */
-	if (mem_range_next_free >= ARRAY_SIZE(mem_range_cache))
-		panic("Physical memory map too complex!\n");
+	start = tag->u.mem_range.addr;
+	end = tag->u.mem_range.addr + tag->u.mem_range.size - 1;
 
-	new = &mem_range_cache[mem_range_next_free++];
-	*new = tag->u.mem_range;
+	add_physical_memory(start, end);
+	return 0;
+}
+__tagtable(ATAG_MEM, parse_tag_mem);
 
-	pprev = root;
-	cur = *root;
-	while (cur) {
-		pprev = &cur->next;
-		cur = cur->next;
+static int __init parse_tag_rdimg(struct tag *tag)
+{
+#ifdef CONFIG_INITRD
+	struct tag_mem_range *mem = &tag->u.mem_range;
+	int ret;
+
+	if (initrd_start) {
+		printk(KERN_WARNING
+		       "Warning: Only the first initrd image will be used\n");
+		return 0;
 	}
 
-	*pprev = new;
-	new->next = NULL;
+	ret = add_reserved_region(mem->start, mem->start + mem->size - 1,
+				  "initrd");
+	if (ret) {
+		printk(KERN_WARNING
+		       "Warning: Failed to reserve initrd memory\n");
+		return ret;
+	}
+
+	initrd_start = (unsigned long)__va(mem->addr);
+	initrd_end = initrd_start + mem->size;
+#else
+	printk(KERN_WARNING "RAM disk image present, but "
+	       "no initrd support in kernel, ignoring\n");
+#endif
 
 	return 0;
 }
+__tagtable(ATAG_RDIMG, parse_tag_rdimg);
 
-static int __init parse_tag_mem(struct tag *tag)
+static int __init parse_tag_rsvd_mem(struct tag *tag)
 {
-	return parse_tag_mem_range(tag, &mem_phys);
+	struct tag_mem_range *mem = &tag->u.mem_range;
+
+	return add_reserved_region(mem->addr, mem->addr + mem->size - 1,
+				   "Reserved");
 }
-__tagtable(ATAG_MEM, parse_tag_mem);
+__tagtable(ATAG_RSVD_MEM, parse_tag_rsvd_mem);
 
 static int __init parse_tag_cmdline(struct tag *tag)
 {
@@ -207,12 +358,6 @@
 }
 __tagtable(ATAG_CMDLINE, parse_tag_cmdline);
 
-static int __init parse_tag_rdimg(struct tag *tag)
-{
-	return parse_tag_mem_range(tag, &mem_ramdisk);
-}
-__tagtable(ATAG_RDIMG, parse_tag_rdimg);
-
 static int __init parse_tag_clock(struct tag *tag)
 {
 	/*
@@ -223,12 +368,6 @@
 }
 __tagtable(ATAG_CLOCK, parse_tag_clock);
 
-static int __init parse_tag_rsvd_mem(struct tag *tag)
-{
-	return parse_tag_mem_range(tag, &mem_reserved);
-}
-__tagtable(ATAG_RSVD_MEM, parse_tag_rsvd_mem);
-
 /*
  * Scan the tag table for this tag, and call its parse function. The
  * tag table is built by the linker from all the __tagtable
@@ -260,10 +399,137 @@
 			       t->hdr.tag);
 }
 
+/*
+ * Find a free memory region large enough for storing the
+ * bootmem bitmap.
+ */
+static unsigned long __init
+find_bootmap_pfn(const struct resource *mem)
+{
+	unsigned long bootmap_pages, bootmap_len;
+	unsigned long node_pages = PFN_UP(mem->end - mem->start + 1);
+	unsigned long bootmap_start;
+
+	bootmap_pages = bootmem_bootmap_pages(node_pages);
+	bootmap_len = bootmap_pages << PAGE_SHIFT;
+
+	/*
+	 * Find a large enough region without reserved pages for
+	 * storing the bootmem bitmap. We can take advantage of the
+	 * fact that all lists have been sorted.
+	 *
+	 * We have to check that we don't collide with any reserved
+	 * regions, which includes the kernel image and any RAMDISK
+	 * images.
+	 */
+	bootmap_start = find_free_region(mem, bootmap_len, PAGE_SIZE);
+
+	return bootmap_start >> PAGE_SHIFT;
+}
+
+#define MAX_LOWMEM	HIGHMEM_START
+#define MAX_LOWMEM_PFN	PFN_DOWN(MAX_LOWMEM)
+
+static void __init setup_bootmem(void)
+{
+	unsigned bootmap_size;
+	unsigned long first_pfn, bootmap_pfn, pages;
+	unsigned long max_pfn, max_low_pfn;
+	unsigned node = 0;
+	struct resource *res;
+
+	printk(KERN_INFO "Physical memory:\n");
+	for (res = system_ram; res; res = res->sibling)
+		printk("  %08x-%08x\n", res->start, res->end);
+	printk(KERN_INFO "Reserved memory:\n");
+	for (res = reserved; res; res = res->sibling)
+		printk("  %08x-%08x: %s\n",
+		       res->start, res->end, res->name);
+
+	nodes_clear(node_online_map);
+
+	if (system_ram->sibling)
+		printk(KERN_WARNING "Only using first memory bank\n");
+
+	for (res = system_ram; res; res = NULL) {
+		first_pfn = PFN_UP(res->start);
+		max_low_pfn = max_pfn = PFN_DOWN(res->end + 1);
+		bootmap_pfn = find_bootmap_pfn(res);
+		if (bootmap_pfn > max_pfn)
+			panic("No space for bootmem bitmap!\n");
+
+		if (max_low_pfn > MAX_LOWMEM_PFN) {
+			max_low_pfn = MAX_LOWMEM_PFN;
+#ifndef CONFIG_HIGHMEM
+			/*
+			 * Lowmem is memory that can be addressed
+			 * directly through P1/P2
+			 */
+			printk(KERN_WARNING
+			       "Node %u: Only %ld MiB of memory will be used.\n",
+			       node, MAX_LOWMEM >> 20);
+			printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n");
+#else
+#error HIGHMEM is not supported by AVR32 yet
+#endif
+		}
+
+		/* Initialize the boot-time allocator with low memory only. */
+		bootmap_size = init_bootmem_node(NODE_DATA(node), bootmap_pfn,
+						 first_pfn, max_low_pfn);
+
+		/*
+		 * Register fully available RAM pages with the bootmem
+		 * allocator.
+		 */
+		pages = max_low_pfn - first_pfn;
+		free_bootmem_node (NODE_DATA(node), PFN_PHYS(first_pfn),
+				   PFN_PHYS(pages));
+
+		/* Reserve space for the bootmem bitmap... */
+		reserve_bootmem_node(NODE_DATA(node),
+				     PFN_PHYS(bootmap_pfn),
+				     bootmap_size);
+
+		/* ...and any other reserved regions. */
+		for (res = reserved; res; res = res->sibling) {
+			if (res->start > PFN_PHYS(max_pfn))
+				break;
+
+			/*
+			 * resource_init will complain about partial
+			 * overlaps, so we'll just ignore such
+			 * resources for now.
+			 */
+			if (res->start >= PFN_PHYS(first_pfn)
+			    && res->end < PFN_PHYS(max_pfn))
+				reserve_bootmem_node(
+					NODE_DATA(node), res->start,
+					res->end - res->start + 1);
+		}
+
+		node_set_online(node);
+	}
+}
+
 void __init setup_arch (char **cmdline_p)
 {
 	struct clk *cpu_clk;
 
+	init_mm.start_code = (unsigned long)_text;
+	init_mm.end_code = (unsigned long)_etext;
+	init_mm.end_data = (unsigned long)_edata;
+	init_mm.brk = (unsigned long)_end;
+
+	/*
+	 * Include .init section to make allocations easier. It will
+	 * be removed before the resource is actually requested.
+	 */
+	kernel_code.start = __pa(__init_begin);
+	kernel_code.end = __pa(init_mm.end_code - 1);
+	kernel_data.start = __pa(init_mm.end_code);
+	kernel_data.end = __pa(init_mm.brk - 1);
+
 	parse_tags(bootloader_tags);
 
 	setup_processor();
@@ -289,24 +555,16 @@
 		       ((cpu_hz + 500) / 1000) % 1000);
 	}
 
-	init_mm.start_code = (unsigned long) &_text;
-	init_mm.end_code = (unsigned long) &_etext;
-	init_mm.end_data = (unsigned long) &_edata;
-	init_mm.brk = (unsigned long) &_end;
-
 	strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
 	*cmdline_p = command_line;
 	parse_early_param();
 
 	setup_bootmem();
 
-	board_setup_fbmem(fbmem_start, fbmem_size);
-
 #ifdef CONFIG_VT
 	conswitchp = &dummy_con;
 #endif
 
 	paging_init();
-
 	resource_init();
 }
diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/kernel/time.c avr32-git/arch/avr32/kernel/time.c
--- linux-2.6.21.3/arch/avr32/kernel/time.c	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/arch/avr32/kernel/time.c	2007-06-06 11:33:46.000000000 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2006 Atmel Corporation
+ * Copyright (C) 2004-2007 Atmel Corporation
  *
  * Based on MIPS implementation arch/mips/kernel/time.c
  *   Copyright 2001 MontaVista Software Inc.
@@ -20,18 +20,25 @@
 #include <linux/init.h>
 #include <linux/profile.h>
 #include <linux/sysdev.h>
+#include <linux/err.h>
 
 #include <asm/div64.h>
 #include <asm/sysreg.h>
 #include <asm/io.h>
 #include <asm/sections.h>
 
-static cycle_t read_cycle_count(void)
+/* how many counter cycles in a jiffy? */
+static u32 cycles_per_jiffy;
+
+/* the count value for the next timer interrupt */
+static u32 expirelo;
+
+cycle_t __weak read_cycle_count(void)
 {
 	return (cycle_t)sysreg_read(COUNT);
 }
 
-static struct clocksource clocksource_avr32 = {
+struct clocksource __weak clocksource_avr32 = {
 	.name		= "avr32",
 	.rating		= 350,
 	.read		= read_cycle_count,
@@ -40,12 +47,20 @@
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
+irqreturn_t __weak timer_interrupt(int irq, void *dev_id);
+
+struct irqaction timer_irqaction = {
+	.handler	= timer_interrupt,
+	.flags		= IRQF_DISABLED,
+	.name		= "timer",
+};
+
 /*
  * By default we provide the null RTC ops
  */
 static unsigned long null_rtc_get_time(void)
 {
-	return mktime(2004, 1, 1, 0, 0, 0);
+	return mktime(2007, 1, 1, 0, 0, 0);
 }
 
 static int null_rtc_set_time(unsigned long sec)
@@ -56,23 +71,14 @@
 static unsigned long (*rtc_get_time)(void) = null_rtc_get_time;
 static int (*rtc_set_time)(unsigned long) = null_rtc_set_time;
 
-/* how many counter cycles in a jiffy? */
-static unsigned long cycles_per_jiffy;
-
-/* cycle counter value at the previous timer interrupt */
-static unsigned int timerhi, timerlo;
-
-/* the count value for the next timer interrupt */
-static unsigned int expirelo;
-
 static void avr32_timer_ack(void)
 {
-	unsigned int count;
+	u32 count;
 
 	/* Ack this timer interrupt and set the next one */
 	expirelo += cycles_per_jiffy;
+	/* setting COMPARE to 0 stops the COUNT-COMPARE */
 	if (expirelo == 0) {
-		printk(KERN_DEBUG "expirelo == 0\n");
 		sysreg_write(COMPARE, expirelo + 1);
 	} else {
 		sysreg_write(COMPARE, expirelo);
@@ -86,27 +92,56 @@
 	}
 }
 
-static unsigned int avr32_hpt_read(void)
+int __weak avr32_hpt_init(void)
 {
-	return sysreg_read(COUNT);
+	int ret;
+	unsigned long mult, shift, count_hz;
+
+	count_hz = clk_get_rate(boot_cpu_data.clk);
+	shift = clocksource_avr32.shift;
+	mult = clocksource_hz2mult(count_hz, shift);
+	clocksource_avr32.mult = mult;
+
+	{
+		u64 tmp;
+
+		tmp = TICK_NSEC;
+		tmp <<= shift;
+		tmp += mult / 2;
+		do_div(tmp, mult);
+
+		cycles_per_jiffy = tmp;
+	}
+
+	ret = setup_irq(0, &timer_irqaction);
+	if (ret) {
+		pr_debug("timer: could not request IRQ 0: %d\n", ret);
+		return -ENODEV;
+	}
+
+	printk(KERN_INFO "timer: AT32AP COUNT-COMPARE at irq 0, "
+			"%lu.%03lu MHz\n",
+			((count_hz + 500) / 1000) / 1000,
+			((count_hz + 500) / 1000) % 1000);
+
+	return 0;
 }
 
 /*
  * Taken from MIPS c0_hpt_timer_init().
  *
- * Why is it so complicated, and what is "count"?  My assumption is
- * that `count' specifies the "reference cycle", i.e. the cycle since
- * reset that should mean "zero". The reason COUNT is written twice is
- * probably to make sure we don't get any timer interrupts while we
- * are messing with the counter.
+ * The reason COUNT is written twice is probably to make sure we don't get any
+ * timer interrupts while we are messing with the counter.
  */
-static void avr32_hpt_init(unsigned int count)
+int __weak avr32_hpt_start(void)
 {
-	count = sysreg_read(COUNT) - count;
+	u32 count = sysreg_read(COUNT);
 	expirelo = (count / cycles_per_jiffy + 1) * cycles_per_jiffy;
 	sysreg_write(COUNT, expirelo - cycles_per_jiffy);
 	sysreg_write(COMPARE, expirelo);
 	sysreg_write(COUNT, count);
+
+	return 0;
 }
 
 /*
@@ -115,26 +150,18 @@
  *
  * In UP mode, it is invoked from the (global) timer_interrupt.
  */
-static void local_timer_interrupt(int irq, void *dev_id)
+void local_timer_interrupt(int irq, void *dev_id)
 {
 	if (current->pid)
 		profile_tick(CPU_PROFILING);
 	update_process_times(user_mode(get_irq_regs()));
 }
 
-static irqreturn_t
-timer_interrupt(int irq, void *dev_id)
+irqreturn_t __weak timer_interrupt(int irq, void *dev_id)
 {
-	unsigned int count;
-
 	/* ack timer interrupt and try to set next interrupt */
-	count = avr32_hpt_read();
 	avr32_timer_ack();
 
-	/* Update timerhi/timerlo for intra-jiffy calibration */
-	timerhi += count < timerlo;	/* Wrap around */
-	timerlo = count;
-
 	/*
 	 * Call the generic timer interrupt handler
 	 */
@@ -153,60 +180,37 @@
 	return IRQ_HANDLED;
 }
 
-static struct irqaction timer_irqaction = {
-	.handler	= timer_interrupt,
-	.flags		= IRQF_DISABLED,
-	.name		= "timer",
-};
-
 void __init time_init(void)
 {
-	unsigned long mult, shift, count_hz;
 	int ret;
 
+	/*
+	 * Make sure we don't get any COMPARE interrupts before we can
+	 * handle them.
+	 */
+	sysreg_write(COMPARE, 0);
+
 	xtime.tv_sec = rtc_get_time();
 	xtime.tv_nsec = 0;
 
 	set_normalized_timespec(&wall_to_monotonic,
 				-xtime.tv_sec, -xtime.tv_nsec);
 
-	printk("Before time_init: count=%08lx, compare=%08lx\n",
-	       (unsigned long)sysreg_read(COUNT),
-	       (unsigned long)sysreg_read(COMPARE));
-
-	count_hz = clk_get_rate(boot_cpu_data.clk);
-	shift = clocksource_avr32.shift;
-	mult = clocksource_hz2mult(count_hz, shift);
-	clocksource_avr32.mult = mult;
-
-	printk("Cycle counter: mult=%lu, shift=%lu\n", mult, shift);
-
-	{
-		u64 tmp;
-
-		tmp = TICK_NSEC;
-		tmp <<= shift;
-		tmp += mult / 2;
-		do_div(tmp, mult);
-
-		cycles_per_jiffy = tmp;
+	ret = avr32_hpt_init();
+	if (ret) {
+		pr_debug("timer: failed setup: %d\n", ret);
+		return;
 	}
 
-	/* This sets up the high precision timer for the first interrupt. */
-	avr32_hpt_init(avr32_hpt_read());
-
-	printk("After time_init: count=%08lx, compare=%08lx\n",
-	       (unsigned long)sysreg_read(COUNT),
-	       (unsigned long)sysreg_read(COMPARE));
-
 	ret = clocksource_register(&clocksource_avr32);
 	if (ret)
-		printk(KERN_ERR
-		       "timer: could not register clocksource: %d\n", ret);
+		pr_debug("timer: could not register clocksource: %d\n", ret);
 
-	ret = setup_irq(0, &timer_irqaction);
-	if (ret)
-		printk("timer: could not request IRQ 0: %d\n", ret);
+	ret = avr32_hpt_start();
+	if (ret) {
+		pr_debug("timer: failed starting: %d\n", ret);
+		return;
+	}
 }
 
 static struct sysdev_class timer_class = {
diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/kernel/traps.c avr32-git/arch/avr32/kernel/traps.c
--- linux-2.6.21.3/arch/avr32/kernel/traps.c	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/arch/avr32/kernel/traps.c	2007-06-06 11:33:46.000000000 +0200
@@ -5,158 +5,25 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#undef DEBUG
-#include <linux/sched.h>
+
+#include <linux/bug.h>
 #include <linux/init.h>
-#include <linux/module.h>
 #include <linux/kallsyms.h>
+#include <linux/module.h>
 #include <linux/notifier.h>
+#include <linux/sched.h>
+#include <linux/uaccess.h>
 
-#include <asm/traps.h>
-#include <asm/sysreg.h>
 #include <asm/addrspace.h>
-#include <asm/ocd.h>
 #include <asm/mmu_context.h>
-#include <asm/uaccess.h>
-
-static void dump_mem(const char *str, unsigned long bottom, unsigned long top)
-{
-	unsigned long p;
-	int i;
-
-	printk("%s(0x%08lx to 0x%08lx)\n", str, bottom, top);
-
-	for (p = bottom & ~31; p < top; ) {
-		printk("%04lx: ", p & 0xffff);
-
-		for (i = 0; i < 8; i++, p += 4) {
-			unsigned int val;
-
-			if (p < bottom || p >= top)
-				printk("         ");
-			else {
-				if (__get_user(val, (unsigned int __user *)p)) {
-					printk("\n");
-					goto out;
-				}
-				printk("%08x ", val);
-			}
-		}
-		printk("\n");
-	}
-
-out:
-	return;
-}
-
-static inline int valid_stack_ptr(struct thread_info *tinfo, unsigned long p)
-{
-	return (p > (unsigned long)tinfo)
-		&& (p < (unsigned long)tinfo + THREAD_SIZE - 3);
-}
-
-#ifdef CONFIG_FRAME_POINTER
-static inline void __show_trace(struct task_struct *tsk, unsigned long *sp,
-				struct pt_regs *regs)
-{
-	unsigned long lr, fp;
-	struct thread_info *tinfo;
-
-	tinfo = (struct thread_info *)
-		((unsigned long)sp & ~(THREAD_SIZE - 1));
-
-	if (regs)
-		fp = regs->r7;
-	else if (tsk == current)
-		asm("mov %0, r7" : "=r"(fp));
-	else
-		fp = tsk->thread.cpu_context.r7;
-
-	/*
-	 * Walk the stack as long as the frame pointer (a) is within
-	 * the kernel stack of the task, and (b) it doesn't move
-	 * downwards.
-	 */
-	while (valid_stack_ptr(tinfo, fp)) {
-		unsigned long new_fp;
-
-		lr = *(unsigned long *)fp;
-		printk(" [<%08lx>] ", lr);
-		print_symbol("%s\n", lr);
-
-		new_fp = *(unsigned long *)(fp + 4);
-		if (new_fp <= fp)
-			break;
-		fp = new_fp;
-	}
-	printk("\n");
-}
-#else
-static inline void __show_trace(struct task_struct *tsk, unsigned long *sp,
-				struct pt_regs *regs)
-{
-	unsigned long addr;
-
-	while (!kstack_end(sp)) {
-		addr = *sp++;
-		if (kernel_text_address(addr)) {
-			printk(" [<%08lx>] ", addr);
-			print_symbol("%s\n", addr);
-		}
-	}
-}
-#endif
-
-void show_trace(struct task_struct *tsk, unsigned long *sp,
-		       struct pt_regs *regs)
-{
-	if (regs &&
-	    (((regs->sr & MODE_MASK) == MODE_EXCEPTION) ||
-	     ((regs->sr & MODE_MASK) == MODE_USER)))
-		return;
-
-	printk ("Call trace:");
-#ifdef CONFIG_KALLSYMS
-	printk("\n");
-#endif
-
-	__show_trace(tsk, sp, regs);
-	printk("\n");
-}
-
-void show_stack(struct task_struct *tsk, unsigned long *sp)
-{
-	unsigned long stack;
-
-	if (!tsk)
-		tsk = current;
-	if (sp == 0) {
-		if (tsk == current) {
-			register unsigned long *real_sp __asm__("sp");
-			sp = real_sp;
-		} else {
-			sp = (unsigned long *)tsk->thread.cpu_context.ksp;
-		}
-	}
-
-	stack = (unsigned long)sp;
-	dump_mem("Stack: ", stack,
-		 THREAD_SIZE + (unsigned long)tsk->thread_info);
-	show_trace(tsk, sp, NULL);
-}
-
-void dump_stack(void)
-{
-	show_stack(NULL, NULL);
-}
-EXPORT_SYMBOL(dump_stack);
+#include <asm/ocd.h>
+#include <asm/sysreg.h>
+#include <asm/traps.h>
 
 ATOMIC_NOTIFIER_HEAD(avr32_die_chain);
 
 int register_die_notifier(struct notifier_block *nb)
 {
-	pr_debug("register_die_notifier: %p\n", nb);
-
 	return atomic_notifier_chain_register(&avr32_die_chain, nb);
 }
 EXPORT_SYMBOL(register_die_notifier);
@@ -169,98 +36,108 @@
 
 static DEFINE_SPINLOCK(die_lock);
 
-void __die(const char *str, struct pt_regs *regs, unsigned long err,
-	   const char *file, const char *func, unsigned long line)
+void NORET_TYPE die(const char *str, struct pt_regs *regs, long err)
 {
-	struct task_struct *tsk = current;
 	static int die_counter;
 
 	console_verbose();
 	spin_lock_irq(&die_lock);
 	bust_spinlocks(1);
 
-	printk(KERN_ALERT "%s", str);
-	if (file && func)
-		printk(" in %s:%s, line %ld", file, func, line);
-	printk("[#%d]:\n", ++die_counter);
-	print_modules();
-	show_regs(regs);
-	printk("Process %s (pid: %d, stack limit = 0x%p)\n",
-	       tsk->comm, tsk->pid, tsk->thread_info + 1);
-
-	if (!user_mode(regs) || in_interrupt()) {
-		dump_mem("Stack: ", regs->sp,
-			 THREAD_SIZE + (unsigned long)tsk->thread_info);
+	printk(KERN_ALERT "Oops: %s, sig: %ld [#%d]\n" KERN_EMERG,
+	       str, err, ++die_counter);
+#ifdef CONFIG_PREEMPT
+	printk("PREEMPT ");
+#endif
+#ifdef CONFIG_FRAME_POINTER
+	printk("FRAME_POINTER ");
+#endif
+	if (current_cpu_data.features & AVR32_FEATURE_OCD) {
+		unsigned long did = __mfdr(DBGREG_DID);
+		printk("chip: 0x%03lx:0x%04lx rev %lu\n",
+		       (did >> 1) & 0x7ff,
+		       (did >> 12) & 0x7fff,
+		       (did >> 28) & 0xf);
+	} else {
+		printk("cpu: arch %u r%u / core %u r%u\n",
+		       current_cpu_data.arch_type,
+		       current_cpu_data.arch_revision,
+		       current_cpu_data.cpu_type,
+		       current_cpu_data.cpu_revision);
 	}
 
+	print_modules();
+	show_regs_log_lvl(regs, KERN_EMERG);
+	show_stack_log_lvl(current, regs->sp, regs, KERN_EMERG);
 	bust_spinlocks(0);
 	spin_unlock_irq(&die_lock);
-	do_exit(SIGSEGV);
+
+	if (in_interrupt())
+		panic("Fatal exception in interrupt");
+
+	if (panic_on_oops)
+		panic("Fatal exception");
+
+	do_exit(err);
 }
 
-void __die_if_kernel(const char *str, struct pt_regs *regs, unsigned long err,
-		     const char *file, const char *func, unsigned long line)
+void _exception(long signr, struct pt_regs *regs, int code,
+		unsigned long addr)
 {
+	siginfo_t info;
+
 	if (!user_mode(regs))
-		__die(str, regs, err, file, func, line);
-}
+		die("Unhandled exception in kernel mode", regs, signr);
+
+	memset(&info, 0, sizeof(info));
+	info.si_signo = signr;
+	info.si_code = code;
+	info.si_addr = (void __user *)addr;
+	force_sig_info(signr, &info, current);
 
-asmlinkage void do_nmi(unsigned long ecr, struct pt_regs *regs)
-{
-#ifdef CONFIG_SUBARCH_AVR32B
 	/*
-	 * The exception entry always saves RSR_EX. For NMI, this is
-	 * wrong; it should be RSR_NMI
+	 * Init gets no signals that it doesn't have a handler for.
+	 * That's all very well, but if it has caused a synchronous
+	 * exception and we ignore the resulting signal, it will just
+	 * generate the same exception over and over again and we get
+	 * nowhere.  Better to kill it and let the kernel panic.
 	 */
-	regs->sr = sysreg_read(RSR_NMI);
-#endif
+	if (is_init(current)) {
+		__sighandler_t handler;
 
-	printk("NMI taken!!!!\n");
-	die("NMI", regs, ecr);
-	BUG();
+		spin_lock_irq(&current->sighand->siglock);
+		handler = current->sighand->action[signr-1].sa.sa_handler;
+		spin_unlock_irq(&current->sighand->siglock);
+		if (handler == SIG_DFL) {
+			/* init has generated a synchronous exception
+			   and it doesn't have a handler for the signal */
+			printk(KERN_CRIT "init has generated signal %ld "
+			       "but has no handler for it\n", signr);
+			do_exit(signr);
+		}
+	}
+}
+
+asmlinkage void do_nmi(unsigned long ecr, struct pt_regs *regs)
+{
+	printk(KERN_ALERT "Got Non-Maskable Interrupt, dumping regs\n");
+	show_regs_log_lvl(regs, KERN_ALERT);
+	show_stack_log_lvl(current, regs->sp, regs, KERN_ALERT);
 }
 
 asmlinkage void do_critical_exception(unsigned long ecr, struct pt_regs *regs)
 {
-	printk("Unable to handle critical exception %lu at pc = %08lx!\n",
-	       ecr, regs->pc);
-	die("Oops", regs, ecr);
-	BUG();
+	die("Critical exception", regs, SIGKILL);
 }
 
 asmlinkage void do_address_exception(unsigned long ecr, struct pt_regs *regs)
 {
-	siginfo_t info;
-
-	die_if_kernel("Oops: Address exception in kernel mode", regs, ecr);
-
-#ifdef DEBUG
-	if (ecr == ECR_ADDR_ALIGN_X)
-		pr_debug("Instruction Address Exception at pc = %08lx\n",
-			 regs->pc);
-	else if (ecr == ECR_ADDR_ALIGN_R)
-		pr_debug("Data Address Exception (Read) at pc = %08lx\n",
-			 regs->pc);
-	else if (ecr == ECR_ADDR_ALIGN_W)
-		pr_debug("Data Address Exception (Write) at pc = %08lx\n",
-			 regs->pc);
-	else
-		BUG();
-
-	show_regs(regs);
-#endif
-
-	info.si_signo = SIGBUS;
-	info.si_errno = 0;
-	info.si_code = BUS_ADRALN;
-	info.si_addr = (void __user *)regs->pc;
-
-	force_sig_info(SIGBUS, &info, current);
+	_exception(SIGBUS, regs, BUS_ADRALN, regs->pc);
 }
 
 /* This way of handling undefined instructions is stolen from ARM */
 static LIST_HEAD(undef_hook);
-static spinlock_t undef_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(undef_lock);
 
 void register_undef_hook(struct undef_hook *hook)
 {
@@ -280,7 +157,8 @@
 {
 	int cop_nr;
 	u32 cpucr;
-	if ( (insn & 0xfdf00000) == 0xf1900000 )
+
+	if ((insn & 0xfdf00000) == 0xf1900000)
 		/* LDC0 */
 		cop_nr = 0;
 	else
@@ -292,136 +170,91 @@
 	sysreg_write(CPUCR, cpucr);
 
 	cpucr = sysreg_read(CPUCR);
-	if ( !(cpucr & (1 << (24 + cop_nr))) ){
-		printk("Coprocessor #%i not found!\n", cop_nr);
-		return -1;
-	}
+	if (!(cpucr & (1 << (24 + cop_nr))))
+		return -ENODEV;
 
 	return 0;
 }
 
-#ifdef CONFIG_BUG
-#ifdef CONFIG_DEBUG_BUGVERBOSE
-static inline void do_bug_verbose(struct pt_regs *regs, u32 insn)
-{
-	char *file;
-	u16 line;
-	char c;
-
-	if (__get_user(line, (u16 __user *)(regs->pc + 2)))
-		return;
-	if (__get_user(file, (char * __user *)(regs->pc + 4))
-	    || (unsigned long)file < PAGE_OFFSET
-	    || __get_user(c, file))
-		file = "<bad filename>";
-
-	printk(KERN_ALERT "kernel BUG at %s:%d!\n", file, line);
-}
-#else
-static inline void do_bug_verbose(struct pt_regs *regs, u32 insn)
+int is_valid_bugaddr(unsigned long pc)
 {
+	unsigned short opcode;
+
+	if (pc < PAGE_OFFSET)
+		return 0;
+	if (probe_kernel_address((u16 *)pc, opcode))
+		return 0;
 
+	return opcode == AVR32_BUG_OPCODE;
 }
-#endif
-#endif
 
 asmlinkage void do_illegal_opcode(unsigned long ecr, struct pt_regs *regs)
 {
 	u32 insn;
 	struct undef_hook *hook;
-	siginfo_t info;
 	void __user *pc;
+	long code;
 
-	if (!user_mode(regs))
-		goto kernel_trap;
+	if (!user_mode(regs) && (ecr == ECR_ILLEGAL_OPCODE)) {
+		enum bug_trap_type type;
+
+		type = report_bug(regs->pc);
+		switch (type) {
+		case BUG_TRAP_TYPE_NONE:
+			break;
+		case BUG_TRAP_TYPE_WARN:
+			regs->pc += 2;
+			return;
+		case BUG_TRAP_TYPE_BUG:
+			die("Kernel BUG", regs, SIGKILL);
+		}
+	}
 
 	local_irq_enable();
 
-	pc = (void __user *)instruction_pointer(regs);
-	if (__get_user(insn, (u32 __user *)pc))
-		goto invalid_area;
+	if (user_mode(regs)) {
+		pc = (void __user *)instruction_pointer(regs);
+		if (get_user(insn, (u32 __user *)pc))
+			goto invalid_area;
 
-        if (ecr == ECR_COPROC_ABSENT) {
-		if (do_cop_absent(insn) == 0)
+		if (ecr == ECR_COPROC_ABSENT && !do_cop_absent(insn))
 			return;
-        }
 
-	spin_lock_irq(&undef_lock);
-	list_for_each_entry(hook, &undef_hook, node) {
-		if ((insn & hook->insn_mask) == hook->insn_val) {
-			if (hook->fn(regs, insn) == 0) {
-				spin_unlock_irq(&undef_lock);
-				return;
+		spin_lock_irq(&undef_lock);
+		list_for_each_entry(hook, &undef_hook, node) {
+			if ((insn & hook->insn_mask) == hook->insn_val) {
+				if (hook->fn(regs, insn) == 0) {
+					spin_unlock_irq(&undef_lock);
+					return;
+				}
 			}
 		}
+		spin_unlock_irq(&undef_lock);
 	}
-	spin_unlock_irq(&undef_lock);
-
-invalid_area:
 
-#ifdef DEBUG
-	printk("Illegal instruction at pc = %08lx\n", regs->pc);
-	if (regs->pc < TASK_SIZE) {
-		unsigned long ptbr, pgd, pte, *p;
-
-		ptbr = sysreg_read(PTBR);
-		p = (unsigned long *)ptbr;
-		pgd = p[regs->pc >> 22];
-		p = (unsigned long *)((pgd & 0x1ffff000) | 0x80000000);
-		pte = p[(regs->pc >> 12) & 0x3ff];
-		printk("page table: 0x%08lx -> 0x%08lx -> 0x%08lx\n", ptbr, pgd, pte);
-	}
-#endif
-
-	info.si_signo = SIGILL;
-	info.si_errno = 0;
-	info.si_addr = (void __user *)regs->pc;
 	switch (ecr) {
-	case ECR_ILLEGAL_OPCODE:
-	case ECR_UNIMPL_INSTRUCTION:
-		info.si_code = ILL_ILLOPC;
-		break;
 	case ECR_PRIVILEGE_VIOLATION:
-		info.si_code = ILL_PRVOPC;
+		code = ILL_PRVOPC;
 		break;
 	case ECR_COPROC_ABSENT:
-		info.si_code = ILL_COPROC;
+		code = ILL_COPROC;
 		break;
 	default:
-		BUG();
+		code = ILL_ILLOPC;
+		break;
 	}
 
-	force_sig_info(SIGILL, &info, current);
+	_exception(SIGILL, regs, code, regs->pc);
 	return;
 
-kernel_trap:
-#ifdef CONFIG_BUG
-	if (__kernel_text_address(instruction_pointer(regs))) {
-		insn = *(u16 *)instruction_pointer(regs);
-		if (insn == AVR32_BUG_OPCODE) {
-			do_bug_verbose(regs, insn);
-			die("Kernel BUG", regs, 0);
-			return;
-		}
-	}
-#endif
-
-	die("Oops: Illegal instruction in kernel code", regs, ecr);
+invalid_area:
+	_exception(SIGSEGV, regs, SEGV_MAPERR, regs->pc);
 }
 
 asmlinkage void do_fpe(unsigned long ecr, struct pt_regs *regs)
 {
-	siginfo_t info;
-
-	printk("Floating-point exception at pc = %08lx\n", regs->pc);
-
-	/* We have no FPU... */
-	info.si_signo = SIGILL;
-	info.si_errno = 0;
-	info.si_addr = (void __user *)regs->pc;
-	info.si_code = ILL_COPROC;
-
-	force_sig_info(SIGILL, &info, current);
+	/* We have no FPU yet */
+	_exception(SIGILL, regs, ILL_COPROC, regs->pc);
 }
 
 
diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/kernel/vmlinux.lds.c avr32-git/arch/avr32/kernel/vmlinux.lds.c
--- linux-2.6.21.3/arch/avr32/kernel/vmlinux.lds.c	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/arch/avr32/kernel/vmlinux.lds.c	2007-06-06 11:33:46.000000000 +0200
@@ -26,10 +26,16 @@
 			_sinittext = .;
 			*(.text.reset)
 			*(.init.text)
+			/*
+			 * .exit.text is discarded at runtime, not
+			 * link time, to deal with references from
+			 * __bug_table
+			 */
+			*(.exit.text)
 			_einittext = .;
 		. = ALIGN(4);
 		__tagtable_begin = .;
-			*(.taglist)
+			*(.taglist.init)
 		__tagtable_end = .;
 			*(.init.data)
 		. = ALIGN(16);
@@ -86,6 +92,8 @@
 		__stop___ex_table = .;
 	}
 
+	BUG_TABLE
+
 	RODATA
 
 	. = ALIGN(8192);
@@ -126,7 +134,6 @@
 	 * thrown away, as cleanup code is never called unless it's a module.
 	 */
 	/DISCARD/       	: {
-		*(.exit.text)
 		*(.exit.data)
 		*(.exitcall.exit)
 	}
diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/mach-at32ap/at32ap7000.c avr32-git/arch/avr32/mach-at32ap/at32ap7000.c
--- linux-2.6.21.3/arch/avr32/mach-at32ap/at32ap7000.c	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/arch/avr32/mach-at32ap/at32ap7000.c	2007-06-06 11:33:46.000000000 +0200
@@ -6,6 +6,7 @@
  * published by the Free Software Foundation.
  */
 #include <linux/clk.h>
+#include <linux/fb.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
@@ -17,7 +18,10 @@
 #include <asm/arch/portmux.h>
 #include <asm/arch/sm.h>
 
+#include <video/atmel_lcdc.h>
+
 #include "clock.h"
+#include "hmatrix.h"
 #include "pio.h"
 #include "sm.h"
 
@@ -416,7 +420,15 @@
 	.resource	= sm_resource,
 	.num_resources	= ARRAY_SIZE(sm_resource),
 };
-DEV_CLK(pclk, at32_sm, pbb, 0);
+static struct clk at32_sm_pclk = {
+	.name		= "pclk",
+	.dev		= &at32_sm_device.dev,
+	.parent		= &pbb_clk,
+	.mode		= pbb_clk_mode,
+	.get_rate	= pbb_clk_get_rate,
+	.users		= 1,
+	.index		= 0,
+};
 
 static struct resource intc0_resource[] = {
 	PBMEM(0xfff00400),
@@ -442,6 +454,7 @@
 	.mode		= hsb_clk_mode,
 	.get_rate	= hsb_clk_get_rate,
 	.users		= 1,
+	.index		= 3,
 };
 
 static struct resource smc0_resource[] = {
@@ -466,6 +479,68 @@
 	.users		= 1,
 };
 
+static struct resource dmaca0_resource[] = {
+	{
+		.start	= 0xff200000,
+		.end	= 0xff20ffff,
+		.flags	= IORESOURCE_MEM,
+	},
+	IRQ(2),
+};
+DEFINE_DEV(dmaca, 0);
+DEV_CLK(hclk, dmaca0, hsb, 10);
+
+/* --------------------------------------------------------------------
+ * HMATRIX
+ * -------------------------------------------------------------------- */
+
+static struct clk hmatrix_clk = {
+	.name		= "hmatrix_clk",
+	.parent		= &pbb_clk,
+	.mode		= pbb_clk_mode,
+	.get_rate	= pbb_clk_get_rate,
+	.index		= 2,
+	.users		= 1,
+};
+#define HMATRIX_BASE	((void __iomem *)0xfff00800)
+
+#define hmatrix_readl(reg)					\
+	__raw_readl((HMATRIX_BASE) + HMATRIX_##reg)
+#define hmatrix_writel(reg,value)				\
+	__raw_writel((value), (HMATRIX_BASE) + HMATRIX_##reg)
+
+/*
+ * Set bits in the HMATRIX Special Function Register (SFR) used by the
+ * External Bus Interface (EBI). This can be used to enable special
+ * features like CompactFlash support, NAND Flash support, etc. on
+ * certain chipselects.
+ */
+static inline void set_ebi_sfr_bits(u32 mask)
+{
+	u32 sfr;
+
+	clk_enable(&hmatrix_clk);
+	sfr = hmatrix_readl(SFR4);
+	sfr |= mask;
+	hmatrix_writel(SFR4, sfr);
+	clk_disable(&hmatrix_clk);
+}
+
+/* --------------------------------------------------------------------
+ *  System Timer/Counter (TC)
+ * -------------------------------------------------------------------- */
+static struct resource at32_systc0_resource[] = {
+	PBMEM(0xfff00c00),
+	IRQ(22),
+};
+struct platform_device at32_systc0_device = {
+	.name		= "systc",
+	.id		= 0,
+	.resource	= at32_systc0_resource,
+	.num_resources	= ARRAY_SIZE(at32_systc0_resource),
+};
+DEV_CLK(pclk, at32_systc0, pbb, 3);
+
 /* --------------------------------------------------------------------
  *  PIO
  * -------------------------------------------------------------------- */
@@ -513,6 +588,9 @@
 	platform_device_register(&at32_intc0_device);
 	platform_device_register(&smc0_device);
 	platform_device_register(&pdc_device);
+	platform_device_register(&dmaca0_device);
+
+	platform_device_register(&at32_systc0_device);
 
 	platform_device_register(&pio0_device);
 	platform_device_register(&pio1_device);
@@ -816,22 +894,105 @@
 }
 
 /* --------------------------------------------------------------------
+ *  TWI
+ * -------------------------------------------------------------------- */
+
+static struct resource atmel_twi0_resource[] = {
+	PBMEM(0xffe00800),
+	IRQ(5),
+};
+DEFINE_DEV(atmel_twi, 0);
+DEV_CLK(pclk,atmel_twi0,pba,2);
+
+struct platform_device *__init
+at32_add_device_twi(unsigned int id)
+{
+	struct platform_device *pdev;
+
+	switch (id) {
+	case 0:
+		pdev = &atmel_twi0_device;
+		select_peripheral(PA(6),  PERIPH_A, 0);	/* SDA	*/
+		select_peripheral(PA(7),  PERIPH_A, 0);	/* SCL	*/
+		break;
+
+	default:
+		return NULL;
+	}
+
+	platform_device_register(pdev);
+	return pdev;
+}
+
+/* --------------------------------------------------------------------
+ * MMC
+ * -------------------------------------------------------------------- */
+static struct mci_platform_data atmel_mci0_data = {
+	.detect_pin	= GPIO_PIN_NONE,
+	.wp_pin		= GPIO_PIN_NONE,
+};
+static struct resource atmel_mci0_resource[] = {
+	PBMEM(0xfff02400),
+	IRQ(28),
+};
+DEFINE_DEV_DATA(atmel_mci, 0);
+DEV_CLK(mci_clk, atmel_mci0, pbb, 9);
+
+struct platform_device *__init
+at32_add_device_mci(unsigned int id, struct mci_platform_data *data)
+{
+	struct platform_device *pdev;
+
+	switch (id) {
+	case 0:
+		pdev = &atmel_mci0_device;
+		select_peripheral(PA(10), PERIPH_A, 0);	/* CLK	 */
+		select_peripheral(PA(11), PERIPH_A, 0);	/* CMD	 */
+		select_peripheral(PA(12), PERIPH_A, 0);	/* DATA0 */
+		select_peripheral(PA(13), PERIPH_A, 0);	/* DATA1 */
+		select_peripheral(PA(14), PERIPH_A, 0);	/* DATA2 */
+		select_peripheral(PA(15), PERIPH_A, 0);	/* DATA3 */
+		break;
+	default:
+		return NULL;
+	}
+
+	if (data) {
+		if (data->detect_pin != GPIO_PIN_NONE)
+			at32_select_gpio(data->detect_pin, 0);
+		if (data->wp_pin != GPIO_PIN_NONE)
+			at32_select_gpio(data->wp_pin, 0);
+		memcpy(pdev->dev.platform_data, data,
+		       sizeof(struct mci_platform_data));
+	}
+
+	platform_device_register(pdev);
+	return pdev;
+}
+
+/* --------------------------------------------------------------------
  *  LCDC
  * -------------------------------------------------------------------- */
-static struct lcdc_platform_data lcdc0_data;
-static struct resource lcdc0_resource[] = {
+static struct atmel_lcdfb_info atmel_lcdfb0_data;
+static struct resource atmel_lcdfb0_resource[] = {
 	{
 		.start		= 0xff000000,
 		.end		= 0xff000fff,
 		.flags		= IORESOURCE_MEM,
 	},
 	IRQ(1),
+	{
+		/* Placeholder for pre-allocated fb memory */
+		.start		= 0x00000000,
+		.end		= 0x00000000,
+		.flags		= 0,
+	},
 };
-DEFINE_DEV_DATA(lcdc, 0);
-DEV_CLK(hclk, lcdc0, hsb, 7);
-static struct clk lcdc0_pixclk = {
-	.name		= "pixclk",
-	.dev		= &lcdc0_device.dev,
+DEFINE_DEV_DATA(atmel_lcdfb, 0);
+DEV_CLK(hck1, atmel_lcdfb0, hsb, 7);
+static struct clk atmel_lcdfb0_pixclk = {
+	.name		= "lcdc_clk",
+	.dev		= &atmel_lcdfb0_device.dev,
 	.mode		= genclk_mode,
 	.get_rate	= genclk_get_rate,
 	.set_rate	= genclk_set_rate,
@@ -840,13 +1001,34 @@
 };
 
 struct platform_device *__init
-at32_add_device_lcdc(unsigned int id, struct lcdc_platform_data *data)
+at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data,
+		     unsigned long fbmem_start, unsigned long fbmem_len)
 {
 	struct platform_device *pdev;
+	struct atmel_lcdfb_info *info;
+	struct fb_monspecs *monspecs;
+	struct fb_videomode *modedb;
+	unsigned int modedb_size;
+
+	/*
+	 * Do a deep copy of the fb data, monspecs and modedb. Make
+	 * sure all allocations are done before setting up the
+	 * portmux.
+	 */
+	monspecs = kmemdup(data->default_monspecs,
+			   sizeof(struct fb_monspecs), GFP_KERNEL);
+	if (!monspecs)
+		return NULL;
+
+	modedb_size = sizeof(struct fb_videomode) * monspecs->modedb_len;
+	modedb = kmemdup(monspecs->modedb, modedb_size, GFP_KERNEL);
+	if (!modedb)
+		goto err_dup_modedb;
+	monspecs->modedb = modedb;
 
 	switch (id) {
 	case 0:
-		pdev = &lcdc0_device;
+		pdev = &atmel_lcdfb0_device;
 		select_peripheral(PC(19), PERIPH_A, 0);	/* CC	  */
 		select_peripheral(PC(20), PERIPH_A, 0);	/* HSYNC  */
 		select_peripheral(PC(21), PERIPH_A, 0);	/* PCLK	  */
@@ -879,16 +1061,133 @@
 		select_peripheral(PD(16), PERIPH_A, 0);	/* DATA22 */
 		select_peripheral(PD(17), PERIPH_A, 0);	/* DATA23 */
 
-		clk_set_parent(&lcdc0_pixclk, &pll0);
-		clk_set_rate(&lcdc0_pixclk, clk_get_rate(&pll0));
+		clk_set_parent(&atmel_lcdfb0_pixclk, &pll0);
+		clk_set_rate(&atmel_lcdfb0_pixclk, clk_get_rate(&pll0));
+		break;
+
+	default:
+		goto err_invalid_id;
+	}
+
+	if (fbmem_len) {
+		pdev->resource[2].start = fbmem_start;
+		pdev->resource[2].end = fbmem_start + fbmem_len - 1;
+		pdev->resource[2].flags = IORESOURCE_MEM;
+	}
+
+	info = pdev->dev.platform_data;
+	memcpy(info, data, sizeof(struct atmel_lcdfb_info));
+	info->default_monspecs = monspecs;
+
+	platform_device_register(pdev);
+	return pdev;
+
+err_invalid_id:
+	kfree(modedb);
+err_dup_modedb:
+	kfree(monspecs);
+	return NULL;
+}
+
+/* --------------------------------------------------------------------
+ *  USB Device Controller
+ * -------------------------------------------------------------------- */
+static struct resource usba0_resource[] = {
+	{
+		.start		= 0xff300000,
+		.end		= 0xff3fffff,
+		.flags		= IORESOURCE_MEM,
+	},
+	PBMEM(0xfff03000),
+	IRQ(31),
+};
+DEFINE_DEV(usba, 0);
+DEV_CLK(pclk, usba0, pbb, 12);
+DEV_CLK(hclk, usba0, hsb, 6);
+
+struct platform_device *__init at32_add_device_usba(unsigned int id)
+{
+	struct platform_device *pdev;
+
+	switch (id) {
+	case 0:
+		pdev = &usba0_device;
+		/* USB pads are not multiplexed */
 		break;
+	default:
+		return NULL;
+	}
+
+	platform_device_register(pdev);
+	return pdev;
+}
+
+/* --------------------------------------------------------------------
+ *  AC97C
+ * -------------------------------------------------------------------- */
+static struct resource atmel_ac97c0_resource[] = {
+	PBMEM(0xfff02800),
+	IRQ(29),
+};
+DEFINE_DEV(atmel_ac97c, 0);
+DEV_CLK(pclk, atmel_ac97c0, pbb, 10);
 
+struct platform_device *__init
+at32_add_device_ac97c(unsigned int id)
+{
+	struct platform_device *pdev;
+
+	switch (id) {
+	case 0:
+		pdev = &atmel_ac97c0_device;
+		select_peripheral(PB(20), PERIPH_B, 0);	/* SYNC	*/
+		select_peripheral(PB(21), PERIPH_B, 0);	/* SDO	*/
+		select_peripheral(PB(22), PERIPH_B, 0);	/* SDI	*/
+		select_peripheral(PB(23), PERIPH_B, 0);	/* SCLK	*/
+		break;
 	default:
 		return NULL;
 	}
 
-	memcpy(pdev->dev.platform_data, data,
-	       sizeof(struct lcdc_platform_data));
+	platform_device_register(pdev);
+	return pdev;
+}
+
+/* --------------------------------------------------------------------
+ *  DAC
+ * -------------------------------------------------------------------- */
+static struct resource abdac0_resource[] = {
+	PBMEM(0xfff02000),
+	IRQ(27),
+};
+DEFINE_DEV(abdac, 0);
+DEV_CLK(pclk, abdac0, pbb, 8);
+static struct clk abdac0_sample_clk = {
+	.name           = "sample_clk",
+	.dev            = &abdac0_device.dev,
+	.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_abdac(unsigned int id)
+{
+	struct platform_device *pdev;
+
+	switch (id) {
+	case 0:
+		pdev = &abdac0_device;
+		select_peripheral(PB(20), PERIPH_A, 0);	/* DATA1	*/
+		select_peripheral(PB(21), PERIPH_A, 0);	/* DATA0	*/
+		select_peripheral(PB(22), PERIPH_A, 0);	/* DATAN1	*/
+		select_peripheral(PB(23), PERIPH_A, 0);	/* DATAN0	*/
+		break;
+	default:
+		return NULL;
+	}
 
 	platform_device_register(pdev);
 	return pdev;
@@ -950,18 +1249,21 @@
 	&pbb_clk,
 	&at32_sm_pclk,
 	&at32_intc0_pclk,
+	&hmatrix_clk,
 	&ebi_clk,
 	&hramc_clk,
 	&smc0_pclk,
 	&smc0_mck,
 	&pdc_hclk,
 	&pdc_pclk,
+	&dmaca0_hclk,
 	&pico_clk,
 	&pio0_mck,
 	&pio1_mck,
 	&pio2_mck,
 	&pio3_mck,
 	&pio4_mck,
+	&at32_systc0_pclk,
 	&atmel_usart0_usart,
 	&atmel_usart1_usart,
 	&atmel_usart2_usart,
@@ -972,8 +1274,15 @@
 	&macb1_pclk,
 	&atmel_spi0_spi_clk,
 	&atmel_spi1_spi_clk,
-	&lcdc0_hclk,
-	&lcdc0_pixclk,
+	&atmel_twi0_pclk,
+	&atmel_mci0_mci_clk,
+	&atmel_lcdfb0_hck1,
+	&atmel_lcdfb0_pixclk,
+	&usba0_pclk,
+	&usba0_hclk,
+	&atmel_ac97c0_pclk,
+	&abdac0_pclk,
+	&abdac0_sample_clk,
 	&gclk0,
 	&gclk1,
 	&gclk2,
@@ -1012,7 +1321,8 @@
 	genclk_init_parent(&gclk2);
 	genclk_init_parent(&gclk3);
 	genclk_init_parent(&gclk4);
-	genclk_init_parent(&lcdc0_pixclk);
+	genclk_init_parent(&atmel_lcdfb0_pixclk);
+	genclk_init_parent(&abdac0_sample_clk);
 
 	/*
 	 * Turn on all clocks that have at least one user already, and
@@ -1024,6 +1334,9 @@
 	for (i = 0; i < ARRAY_SIZE(at32_clock_list); i++) {
 		struct clk *clk = at32_clock_list[i];
 
+		if (clk->users == 0)
+			continue;
+
 		if (clk->mode == &cpu_clk_mode)
 			cpu_mask |= 1 << clk->index;
 		else if (clk->mode == &hsb_clk_mode)
diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/mach-at32ap/clock.c avr32-git/arch/avr32/mach-at32ap/clock.c
--- linux-2.6.21.3/arch/avr32/mach-at32ap/clock.c	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/arch/avr32/mach-at32ap/clock.c	2007-06-06 11:33:46.000000000 +0200
@@ -18,7 +18,7 @@
 
 #include "clock.h"
 
-static spinlock_t clk_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(clk_lock);
 
 struct clk *clk_get(struct device *dev, const char *id)
 {
diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/mach-at32ap/hmatrix.h avr32-git/arch/avr32/mach-at32ap/hmatrix.h
--- linux-2.6.21.3/arch/avr32/mach-at32ap/hmatrix.h	1970-01-01 01:00:00.000000000 +0100
+++ avr32-git/arch/avr32/mach-at32ap/hmatrix.h	2007-06-06 11:33:46.000000000 +0200
@@ -0,0 +1,182 @@
+/*
+ * Register definitions for High-Speed Bus Matrix
+ */
+#ifndef __HMATRIX_H
+#define __HMATRIX_H
+
+/* HMATRIX register offsets */
+#define HMATRIX_MCFG0				0x0000
+#define HMATRIX_MCFG1				0x0004
+#define HMATRIX_MCFG2				0x0008
+#define HMATRIX_MCFG3				0x000c
+#define HMATRIX_MCFG4				0x0010
+#define HMATRIX_MCFG5				0x0014
+#define HMATRIX_MCFG6				0x0018
+#define HMATRIX_MCFG7				0x001c
+#define HMATRIX_MCFG8				0x0020
+#define HMATRIX_MCFG9				0x0024
+#define HMATRIX_MCFG10				0x0028
+#define HMATRIX_MCFG11				0x002c
+#define HMATRIX_MCFG12				0x0030
+#define HMATRIX_MCFG13				0x0034
+#define HMATRIX_MCFG14				0x0038
+#define HMATRIX_MCFG15				0x003c
+#define HMATRIX_SCFG0				0x0040
+#define HMATRIX_SCFG1				0x0044
+#define HMATRIX_SCFG2				0x0048
+#define HMATRIX_SCFG3				0x004c
+#define HMATRIX_SCFG4				0x0050
+#define HMATRIX_SCFG5				0x0054
+#define HMATRIX_SCFG6				0x0058
+#define HMATRIX_SCFG7				0x005c
+#define HMATRIX_SCFG8				0x0060
+#define HMATRIX_SCFG9				0x0064
+#define HMATRIX_SCFG10				0x0068
+#define HMATRIX_SCFG11				0x006c
+#define HMATRIX_SCFG12				0x0070
+#define HMATRIX_SCFG13				0x0074
+#define HMATRIX_SCFG14				0x0078
+#define HMATRIX_SCFG15				0x007c
+#define HMATRIX_PRAS0				0x0080
+#define HMATRIX_PRBS0				0x0084
+#define HMATRIX_PRAS1				0x0088
+#define HMATRIX_PRBS1				0x008c
+#define HMATRIX_PRAS2				0x0090
+#define HMATRIX_PRBS2				0x0094
+#define HMATRIX_PRAS3				0x0098
+#define HMATRIX_PRBS3				0x009c
+#define HMATRIX_PRAS4				0x00a0
+#define HMATRIX_PRBS4				0x00a4
+#define HMATRIX_PRAS5				0x00a8
+#define HMATRIX_PRBS5				0x00ac
+#define HMATRIX_PRAS6				0x00b0
+#define HMATRIX_PRBS6				0x00b4
+#define HMATRIX_PRAS7				0x00b8
+#define HMATRIX_PRBS7				0x00bc
+#define HMATRIX_PRAS8				0x00c0
+#define HMATRIX_PRBS8				0x00c4
+#define HMATRIX_PRAS9				0x00c8
+#define HMATRIX_PRBS9				0x00cc
+#define HMATRIX_PRAS10				0x00d0
+#define HMATRIX_PRBS10				0x00d4
+#define HMATRIX_PRAS11				0x00d8
+#define HMATRIX_PRBS11				0x00dc
+#define HMATRIX_PRAS12				0x00e0
+#define HMATRIX_PRBS12				0x00e4
+#define HMATRIX_PRAS13				0x00e8
+#define HMATRIX_PRBS13				0x00ec
+#define HMATRIX_PRAS14				0x00f0
+#define HMATRIX_PRBS14				0x00f4
+#define HMATRIX_PRAS15				0x00f8
+#define HMATRIX_PRBS15				0x00fc
+#define HMATRIX_MRCR				0x0100
+#define HMATRIX_SFR0				0x0110
+#define HMATRIX_SFR1				0x0114
+#define HMATRIX_SFR2				0x0118
+#define HMATRIX_SFR3				0x011c
+#define HMATRIX_SFR4				0x0120
+#define HMATRIX_SFR5				0x0124
+#define HMATRIX_SFR6				0x0128
+#define HMATRIX_SFR7				0x012c
+#define HMATRIX_SFR8				0x0130
+#define HMATRIX_SFR9				0x0134
+#define HMATRIX_SFR10				0x0138
+#define HMATRIX_SFR11				0x013c
+#define HMATRIX_SFR12				0x0140
+#define HMATRIX_SFR13				0x0144
+#define HMATRIX_SFR14				0x0148
+#define HMATRIX_SFR15				0x014c
+
+/* Bitfields in MCFGx */
+#define HMATRIX_ULBT_OFFSET			0
+#define HMATRIX_ULBT_SIZE			3
+
+/* Bitfields in SCFGx */
+#define HMATRIX_SLOT_CYCLE_OFFSET		0
+#define HMATRIX_SLOT_CYCLE_SIZE			8
+#define HMATRIX_DEFMSTR_TYPE_OFFSET		16
+#define HMATRIX_DEFMSTR_TYPE_SIZE		2
+#define HMATRIX_FIXED_DEFMSTR_OFFSET		18
+#define HMATRIX_FIXED_DEFMSTR_SIZE		4
+#define HMATRIX_ARBT_OFFSET			24
+#define HMATRIX_ARBT_SIZE			2
+
+/* Bitfields in PRASx */
+#define HMATRIX_M0PR_OFFSET			0
+#define HMATRIX_M0PR_SIZE			4
+#define HMATRIX_M1PR_OFFSET			4
+#define HMATRIX_M1PR_SIZE			4
+#define HMATRIX_M2PR_OFFSET			8
+#define HMATRIX_M2PR_SIZE			4
+#define HMATRIX_M3PR_OFFSET			12
+#define HMATRIX_M3PR_SIZE			4
+#define HMATRIX_M4PR_OFFSET			16
+#define HMATRIX_M4PR_SIZE			4
+#define HMATRIX_M5PR_OFFSET			20
+#define HMATRIX_M5PR_SIZE			4
+#define HMATRIX_M6PR_OFFSET			24
+#define HMATRIX_M6PR_SIZE			4
+#define HMATRIX_M7PR_OFFSET			28
+#define HMATRIX_M7PR_SIZE			4
+
+/* Bitfields in PRBSx */
+#define HMATRIX_M8PR_OFFSET			0
+#define HMATRIX_M8PR_SIZE			4
+#define HMATRIX_M9PR_OFFSET			4
+#define HMATRIX_M9PR_SIZE			4
+#define HMATRIX_M10PR_OFFSET			8
+#define HMATRIX_M10PR_SIZE			4
+#define HMATRIX_M11PR_OFFSET			12
+#define HMATRIX_M11PR_SIZE			4
+#define HMATRIX_M12PR_OFFSET			16
+#define HMATRIX_M12PR_SIZE			4
+#define HMATRIX_M13PR_OFFSET			20
+#define HMATRIX_M13PR_SIZE			4
+#define HMATRIX_M14PR_OFFSET			24
+#define HMATRIX_M14PR_SIZE			4
+#define HMATRIX_M15PR_OFFSET			28
+#define HMATRIX_M15PR_SIZE			4
+
+/* Bitfields in SFR4 */
+#define HMATRIX_CS1A_OFFSET			1
+#define HMATRIX_CS1A_SIZE			1
+#define HMATRIX_CS3A_OFFSET			3
+#define HMATRIX_CS3A_SIZE			1
+#define HMATRIX_CS4A_OFFSET			4
+#define HMATRIX_CS4A_SIZE			1
+#define HMATRIX_CS5A_OFFSET			5
+#define HMATRIX_CS5A_SIZE			1
+#define HMATRIX_DBPUC_OFFSET			8
+#define HMATRIX_DBPUC_SIZE			1
+
+/* Constants for ULBT */
+#define HMATRIX_ULBT_INFINITE			0
+#define HMATRIX_ULBT_SINGLE			1
+#define HMATRIX_ULBT_FOUR_BEAT			2
+#define HMATRIX_ULBT_EIGHT_BEAT			3
+#define HMATRIX_ULBT_SIXTEEN_BEAT		4
+
+/* Constants for DEFMSTR_TYPE */
+#define HMATRIX_DEFMSTR_TYPE_NO_DEFAULT		0
+#define HMATRIX_DEFMSTR_TYPE_LAST_DEFAULT	1
+#define HMATRIX_DEFMSTR_TYPE_FIXED_DEFAULT	2
+
+/* Constants for ARBT */
+#define HMATRIX_ARBT_ROUND_ROBIN		0
+#define HMATRIX_ARBT_FIXED_PRIORITY		1
+
+/* Bit manipulation macros */
+#define HMATRIX_BIT(name)					\
+	(1 << HMATRIX_##name##_OFFSET)
+#define HMATRIX_BF(name,value)					\
+	(((value) & ((1 << HMATRIX_##name##_SIZE) - 1))		\
+	 << HMATRIX_##name##_OFFSET)
+#define HMATRIX_BFEXT(name,value)				\
+	(((value) >> HMATRIX_##name##_OFFSET)			\
+	 & ((1 << HMATRIX_##name##_SIZE) - 1))
+#define HMATRIX_BFINS(name,value,old)				\
+	(((old) & ~(((1 << HMATRIX_##name##_SIZE) - 1)		\
+		    << HMATRIX_##name##_OFFSET))		\
+	 | HMATRIX_BF(name,value))
+
+#endif /* __HMATRIX_H */
diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/mach-at32ap/hsmc.c avr32-git/arch/avr32/mach-at32ap/hsmc.c
--- linux-2.6.21.3/arch/avr32/mach-at32ap/hsmc.c	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/arch/avr32/mach-at32ap/hsmc.c	2007-06-06 11:33:46.000000000 +0200
@@ -75,12 +75,35 @@
 		return -EINVAL;
 	}
 
+	switch (config->nwait_mode) {
+	case 0:
+		mode |= HSMC_BF(EXNW_MODE, HSMC_EXNW_MODE_DISABLED);
+		break;
+	case 1:
+		mode |= HSMC_BF(EXNW_MODE, HSMC_EXNW_MODE_RESERVED);
+		break;
+	case 2:
+		mode |= HSMC_BF(EXNW_MODE, HSMC_EXNW_MODE_FROZEN);
+		break;
+	case 3:
+		mode |= HSMC_BF(EXNW_MODE, HSMC_EXNW_MODE_READY);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (config->tdf_cycles) {
+		mode |= HSMC_BF(TDF_CYCLES, config->tdf_cycles);
+	}
+
 	if (config->nrd_controlled)
 		mode |= HSMC_BIT(READ_MODE);
 	if (config->nwe_controlled)
 		mode |= HSMC_BIT(WRITE_MODE);
 	if (config->byte_write)
 		mode |= HSMC_BIT(BAT);
+	if (config->tdf_mode)
+		mode |= HSMC_BIT(TDF_MODE);
 
 	pr_debug("smc cs%d: setup/%08x pulse/%08x cycle/%08x mode/%08x\n",
 		 cs, setup, pulse, cycle, mode);
diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/mach-at32ap/Kconfig avr32-git/arch/avr32/mach-at32ap/Kconfig
--- linux-2.6.21.3/arch/avr32/mach-at32ap/Kconfig	1970-01-01 01:00:00.000000000 +0100
+++ avr32-git/arch/avr32/mach-at32ap/Kconfig	2007-06-06 11:33:46.000000000 +0200
@@ -0,0 +1,31 @@
+if PLATFORM_AT32AP
+
+menu "Atmel AVR32 AP options"
+
+choice
+	prompt "AT32AP7000 static memory bus width"
+	depends on CPU_AT32AP7000
+	default AP7000_16_BIT_SMC
+	help
+	  Define the width of the AP7000 external static memory interface.
+	  This is used to determine how to mangle the address and/or data
+	  when doing little-endian port access.
+
+	  The current code can only support a single external memory bus
+	  width for all chip selects, excluding the flash (which is using
+	  raw access and is thus not affected by any of this.)
+
+config AP7000_32_BIT_SMC
+	bool "32 bit"
+
+config AP7000_16_BIT_SMC
+	bool "16 bit"
+
+config AP7000_8_BIT_SMC
+	bool "8 bit"
+
+endchoice
+
+endmenu
+
+endif # PLATFORM_AT32AP
diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/mach-at32ap/Makefile avr32-git/arch/avr32/mach-at32ap/Makefile
--- linux-2.6.21.3/arch/avr32/mach-at32ap/Makefile	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/arch/avr32/mach-at32ap/Makefile	2007-06-06 11:33:46.000000000 +0200
@@ -1,2 +1,3 @@
 obj-y				+= at32ap.o clock.o intc.o extint.o pio.o hsmc.o
 obj-$(CONFIG_CPU_AT32AP7000)	+= at32ap7000.o
+obj-$(CONFIG_CPU_AT32AP7000)	+= time-tc.o
diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/mach-at32ap/time-tc.c avr32-git/arch/avr32/mach-at32ap/time-tc.c
--- linux-2.6.21.3/arch/avr32/mach-at32ap/time-tc.c	1970-01-01 01:00:00.000000000 +0100
+++ avr32-git/arch/avr32/mach-at32ap/time-tc.c	2007-06-06 11:33:46.000000000 +0200
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2004-2007 Atmel Corporation
+ *
+ * Based on MIPS implementation arch/mips/kernel/time.c
+ *   Copyright 2001 MontaVista Software Inc.
+ *
+ * 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/clocksource.h>
+#include <linux/time.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel_stat.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/profile.h>
+#include <linux/sysdev.h>
+#include <linux/err.h>
+
+#include <asm/div64.h>
+#include <asm/sysreg.h>
+#include <asm/io.h>
+#include <asm/sections.h>
+
+#include <asm/arch/time.h>
+
+/* how many counter cycles in a jiffy? */
+static u32 cycles_per_jiffy;
+
+/* the count value for the next timer interrupt */
+static u32 expirelo;
+
+/* the I/O registers of the TC module */
+static void __iomem *ioregs;
+
+cycle_t read_cycle_count(void)
+{
+	return (cycle_t)timer_read(ioregs, 0, CV);
+}
+
+struct clocksource clocksource_avr32 = {
+	.name		= "avr32",
+	.rating		= 342,
+	.read		= read_cycle_count,
+	.mask		= CLOCKSOURCE_MASK(16),
+	.shift		= 16,
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static void avr32_timer_ack(void)
+{
+	u16 count = expirelo;
+
+	/* Ack this timer interrupt and set the next one, use a u16
+	 * variable so it will wrap around correctly */
+	count += cycles_per_jiffy;
+	expirelo = count;
+	timer_write(ioregs, 0, RC, expirelo);
+
+	/* Check to see if we have missed any timer interrupts */
+	count = timer_read(ioregs, 0, CV);
+	if ((count - expirelo) < 0x7fff) {
+		expirelo = count + cycles_per_jiffy;
+		timer_write(ioregs, 0, RC, expirelo);
+	}
+}
+
+u32 avr32_hpt_read(void)
+{
+	return timer_read(ioregs, 0, CV);
+}
+
+static int avr32_timer_calc_div_and_set_jiffies(struct clk *pclk)
+{
+	unsigned int cycles_max = (clocksource_avr32.mask + 1) / 2;
+	unsigned int divs[] = { 4, 8, 16, 32 };
+	int divs_size = sizeof(divs) / sizeof(*divs);
+	int i = 0;
+	unsigned long count_hz;
+	unsigned long shift;
+	unsigned long mult;
+	int clock_div = -1;
+	u64 tmp;
+
+	shift = clocksource_avr32.shift;
+
+	do {
+		count_hz = clk_get_rate(pclk) / divs[i];
+		mult = clocksource_hz2mult(count_hz, shift);
+		clocksource_avr32.mult = mult;
+
+		tmp = TICK_NSEC;
+		tmp <<= shift;
+		tmp += mult / 2;
+		do_div(tmp, mult);
+
+		cycles_per_jiffy = tmp;
+	} while (cycles_per_jiffy > cycles_max && ++i < divs_size);
+
+	clock_div = i + 1;
+
+	if (clock_div > divs_size) {
+		pr_debug("timer: could not calculate clock divider\n");
+		return -EFAULT;
+	}
+
+	/* Set the clock divider */
+	timer_write(ioregs, 0, CMR, TIMER_BF(CMR_TCCLKS, clock_div));
+
+	return 0;
+}
+
+int avr32_hpt_init(unsigned int count)
+{
+	struct resource *regs;
+	struct clk *pclk;
+	int irq = -1;
+	int ret = 0;
+
+	ret = -ENXIO;
+
+	irq = platform_get_irq(&at32_systc0_device, 0);
+	if (irq < 0) {
+		pr_debug("timer: could not get irq\n");
+		goto out_error;
+	}
+
+	pclk = clk_get(&at32_systc0_device.dev, "pclk");
+	if (IS_ERR(pclk)) {
+		pr_debug("timer: could not get clk: %ld\n", PTR_ERR(pclk));
+		goto out_error;
+	}
+	clk_enable(pclk);
+
+	regs = platform_get_resource(&at32_systc0_device, IORESOURCE_MEM, 0);
+	if (!regs) {
+		pr_debug("timer: could not get resource\n");
+		goto out_error_clk;
+	}
+
+	ioregs = ioremap(regs->start, regs->end - regs->start + 1);
+	if (!ioregs) {
+		pr_debug("timer: could not get ioregs\n");
+		goto out_error_clk;
+	}
+
+	ret = avr32_timer_calc_div_and_set_jiffies(pclk);
+	if (ret)
+		goto out_error_io;
+
+	ret = setup_irq(irq, &timer_irqaction);
+	if (ret) {
+		pr_debug("timer: could not request irq %d: %d\n",
+				irq, ret);
+		goto out_error_io;
+	}
+
+	expirelo = (timer_read(ioregs, 0, CV) / cycles_per_jiffy + 1)
+		* cycles_per_jiffy;
+
+	/* Enable clock and interrupts on RC compare */
+	timer_write(ioregs, 0, CCR, TIMER_BIT(CCR_CLKEN));
+	timer_write(ioregs, 0, IER, TIMER_BIT(IER_CPCS));
+	/* Set cycles to first interrupt */
+	timer_write(ioregs, 0,  RC, expirelo);
+
+	printk(KERN_INFO "timer: AT32AP system timer/counter at 0x%p irq %d\n",
+			ioregs, irq);
+
+	return 0;
+
+out_error_io:
+	iounmap(ioregs);
+out_error_clk:
+	clk_put(pclk);
+out_error:
+	return ret;
+}
+
+int avr32_hpt_start(void)
+{
+	timer_write(ioregs, 0, CCR, TIMER_BIT(CCR_SWTRG));
+	return 0;
+}
+
+irqreturn_t timer_interrupt(int irq, void *dev_id)
+{
+	unsigned int sr = timer_read(ioregs, 0, SR);
+
+	if (sr & TIMER_BIT(SR_CPCS)) {
+		/* ack timer interrupt and try to set next interrupt */
+		avr32_timer_ack();
+
+		/*
+		 * Call the generic timer interrupt handler
+		 */
+		write_seqlock(&xtime_lock);
+		do_timer(1);
+		write_sequnlock(&xtime_lock);
+
+		/*
+		 * In UP mode, we call local_timer_interrupt() to do profiling
+		 * and process accounting.
+		 *
+		 * SMP is not supported yet.
+		 */
+		local_timer_interrupt(irq, dev_id);
+
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_NONE;
+}
diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/Makefile avr32-git/arch/avr32/Makefile
--- linux-2.6.21.3/arch/avr32/Makefile	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/arch/avr32/Makefile	2007-06-06 11:33:46.000000000 +0200
@@ -16,7 +16,7 @@
 CFLAGS_MODULE	+= -mno-relax
 LDFLAGS_vmlinux	+= --relax
 
-cpuflags-$(CONFIG_CPU_AP7000)	+= -mcpu=ap7000
+cpuflags-$(CONFIG_CPU_AT32AP7000)	+= -mcpu=ap7000
 
 CFLAGS		+= $(cpuflags-y)
 AFLAGS		+= $(cpuflags-y)
@@ -27,9 +27,11 @@
 head-y					+= arch/avr32/kernel/head.o
 core-$(CONFIG_PLATFORM_AT32AP)		+= arch/avr32/mach-at32ap/
 core-$(CONFIG_BOARD_ATSTK1000)		+= arch/avr32/boards/atstk1000/
+core-$(CONFIG_BOARD_ATNGW100)		+= arch/avr32/boards/atngw100/
 core-$(CONFIG_LOADER_U_BOOT)		+= arch/avr32/boot/u-boot/
 core-y					+= arch/avr32/kernel/
 core-y					+= arch/avr32/mm/
+drivers-y				+= arch/avr32/drivers/
 libs-y					+= arch/avr32/lib/
 
 archincdir-$(CONFIG_PLATFORM_AT32AP)	:= arch-at32ap
diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/mm/dma-coherent.c avr32-git/arch/avr32/mm/dma-coherent.c
--- linux-2.6.21.3/arch/avr32/mm/dma-coherent.c	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/arch/avr32/mm/dma-coherent.c	2007-06-06 11:33:46.000000000 +0200
@@ -112,16 +112,21 @@
 }
 EXPORT_SYMBOL(dma_free_coherent);
 
-#if 0
 void *dma_alloc_writecombine(struct device *dev, size_t size,
 			     dma_addr_t *handle, gfp_t gfp)
 {
 	struct page *page;
+	dma_addr_t phys;
 
 	page = __dma_alloc(dev, size, handle, gfp);
+	if (!page)
+		return NULL;
+
+	phys = page_to_phys(page);
+	*handle = phys;
 
 	/* Now, map the page into P3 with write-combining turned on */
-	return __ioremap(page_to_phys(page), size, _PAGE_BUFFER);
+	return __ioremap(phys, size, _PAGE_BUFFER);
 }
 EXPORT_SYMBOL(dma_alloc_writecombine);
 
@@ -132,8 +137,7 @@
 
 	iounmap(cpu_addr);
 
-	page = bus_to_page(handle);
+	page = phys_to_page(handle);
 	__dma_free(dev, size, page, handle);
 }
 EXPORT_SYMBOL(dma_free_writecombine);
-#endif
diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/mm/fault.c avr32-git/arch/avr32/mm/fault.c
--- linux-2.6.21.3/arch/avr32/mm/fault.c	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/arch/avr32/mm/fault.c	2007-06-06 11:33:46.000000000 +0200
@@ -12,73 +12,46 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/pagemap.h>
+#include <linux/kprobes.h>
 
 #include <asm/kdebug.h>
 #include <asm/mmu_context.h>
 #include <asm/sysreg.h>
-#include <asm/uaccess.h>
 #include <asm/tlb.h>
-
-#ifdef DEBUG
-static void dump_code(unsigned long pc)
-{
-	char *p = (char *)pc;
-	char val;
-	int i;
-
-
-	printk(KERN_DEBUG "Code:");
-	for (i = 0; i < 16; i++) {
-		if (__get_user(val, p + i))
-			break;
-		printk(" %02x", val);
-	}
-	printk("\n");
-}
-#endif
+#include <asm/uaccess.h>
 
 #ifdef CONFIG_KPROBES
-ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
-
-/* Hook to register for page fault notifications */
-int register_page_fault_notifier(struct notifier_block *nb)
+static inline int notify_page_fault(struct pt_regs *regs, int trap)
 {
-	return atomic_notifier_chain_register(&notify_page_fault_chain, nb);
-}
+	int ret = 0;
 
-int unregister_page_fault_notifier(struct notifier_block *nb)
-{
-	return atomic_notifier_chain_unregister(&notify_page_fault_chain, nb);
-}
+	if (!user_mode(regs)) {
+		if (kprobe_running() && kprobe_fault_handler(regs, trap))
+			ret = 1;
+	}
 
-static inline int notify_page_fault(enum die_val val, struct pt_regs *regs,
-				    int trap, int sig)
-{
-	struct die_args args = {
-		.regs = regs,
-		.trapnr = trap,
-	};
-	return atomic_notifier_call_chain(&notify_page_fault_chain, val, &args);
+	return ret;
 }
 #else
-static inline int notify_page_fault(enum die_val val, struct pt_regs *regs,
-				    int trap, int sig)
+static inline int notify_page_fault(struct pt_regs *regs, int trap)
 {
-	return NOTIFY_DONE;
+	return 0;
 }
 #endif
 
+int exception_trace = 1;
+
 /*
  * This routine handles page faults. It determines the address and the
  * problem, and then passes it off to one of the appropriate routines.
  *
  * ecr is the Exception Cause Register. Possible values are:
- *   5:  Page not found (instruction access)
  *   6:  Protection fault (instruction access)
- *   12: Page not found (read access)
- *   13: Page not found (write access)
- *   14: Protection fault (read access)
- *   15: Protection fault (write access)
+ *   15: Protection fault (read access)
+ *   16: Protection fault (write access)
+ *   20: Page not found (instruction access)
+ *   24: Page not found (read access)
+ *   28: Page not found (write access)
  */
 asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs)
 {
@@ -88,10 +61,11 @@
 	const struct exception_table_entry *fixup;
 	unsigned long address;
 	unsigned long page;
-	int writeaccess = 0;
+	int writeaccess;
+	long signr;
+	int code;
 
-	if (notify_page_fault(DIE_PAGE_FAULT, regs,
-			      ecr, SIGSEGV) == NOTIFY_STOP)
+	if (notify_page_fault(regs, ecr))
 		return;
 
 	address = sysreg_read(TLBEAR);
@@ -99,6 +73,9 @@
 	tsk = current;
 	mm = tsk->mm;
 
+	signr = SIGSEGV;
+	code = SEGV_MAPERR;
+
 	/*
 	 * If we're in an interrupt or have no user context, we must
 	 * not take the fault...
@@ -125,7 +102,9 @@
 	 * can handle it...
 	 */
 good_area:
-	//pr_debug("good area: vm_flags = 0x%lx\n", vma->vm_flags);
+	code = SEGV_ACCERR;
+	writeaccess = 0;
+
 	switch (ecr) {
 	case ECR_PROTECTION_X:
 	case ECR_TLB_MISS_X:
@@ -176,46 +155,24 @@
 	 * map. Fix it, but check if it's kernel or user first...
 	 */
 bad_area:
-	pr_debug("Bad area [%s:%u]: addr %08lx, ecr %lu\n",
-		 tsk->comm, tsk->pid, address, ecr);
-
 	up_read(&mm->mmap_sem);
 
 	if (user_mode(regs)) {
-		/* Hmm...we have to pass address and ecr somehow... */
-		/* tsk->thread.address = address;
-		   tsk->thread.error_code = ecr; */
-#ifdef DEBUG
-		show_regs(regs);
-		dump_code(regs->pc);
-
-		page = sysreg_read(PTBR);
-		printk("ptbr = %08lx", page);
-		if (page) {
-			page = ((unsigned long *)page)[address >> 22];
-			printk(" pgd = %08lx", page);
-			if (page & _PAGE_PRESENT) {
-				page &= PAGE_MASK;
-				address &= 0x003ff000;
-				page = ((unsigned long *)__va(page))[address >> PAGE_SHIFT];
-				printk(" pte = %08lx\n", page);
-			}
-		}
-#endif
-		pr_debug("Sending SIGSEGV to PID %d...\n",
-			tsk->pid);
-		force_sig(SIGSEGV, tsk);
+		if (exception_trace && printk_ratelimit())
+			printk("%s%s[%d]: segfault at %08lx pc %08lx "
+			       "sp %08lx ecr %lu\n",
+			       is_init(tsk) ? KERN_EMERG : KERN_INFO,
+			       tsk->comm, tsk->pid, address, regs->pc,
+			       regs->sp, ecr);
+		_exception(SIGSEGV, regs, code, address);
 		return;
 	}
 
 no_context:
-	pr_debug("No context\n");
-
 	/* Are we prepared to handle this kernel fault? */
 	fixup = search_exception_tables(regs->pc);
 	if (fixup) {
 		regs->pc = fixup->fixup;
-		pr_debug("Found fixup at %08lx\n", fixup->fixup);
 		return;
 	}
 
@@ -230,7 +187,6 @@
 		printk(KERN_ALERT
 		       "Unable to handle kernel paging request");
 	printk(" at virtual address %08lx\n", address);
-	printk(KERN_ALERT "pc = %08lx\n", regs->pc);
 
 	page = sysreg_read(PTBR);
 	printk(KERN_ALERT "ptbr = %08lx", page);
@@ -241,20 +197,20 @@
 			page &= PAGE_MASK;
 			address &= 0x003ff000;
 			page = ((unsigned long *)__va(page))[address >> PAGE_SHIFT];
-			printk(" pte = %08lx\n", page);
+			printk(" pte = %08lx", page);
 		}
 	}
-	die("\nOops", regs, ecr);
-	do_exit(SIGKILL);
+	printk("\n");
+	die("Kernel access of bad area", regs, signr);
+	return;
 
 	/*
 	 * We ran out of memory, or some other thing happened to us
 	 * that made us unable to handle the page fault gracefully.
 	 */
 out_of_memory:
-	printk("Out of memory\n");
 	up_read(&mm->mmap_sem);
-	if (current->pid == 1) {
+	if (is_init(current)) {
 		yield();
 		down_read(&mm->mmap_sem);
 		goto survive;
@@ -267,21 +223,20 @@
 do_sigbus:
 	up_read(&mm->mmap_sem);
 
-	/*
-	 * Send a sigbus, regardless of whether we were in kernel or
-	 * user mode.
-	 */
-	/* address, error_code, trap_no, ... */
-#ifdef DEBUG
-	show_regs(regs);
-	dump_code(regs->pc);
-#endif
-	pr_debug("Sending SIGBUS to PID %d...\n", tsk->pid);
-	force_sig(SIGBUS, tsk);
-
 	/* Kernel mode? Handle exceptions or die */
+	signr = SIGBUS;
+	code = BUS_ADRERR;
 	if (!user_mode(regs))
 		goto no_context;
+
+	if (exception_trace)
+		printk("%s%s[%d]: bus error at %08lx pc %08lx "
+		       "sp %08lx ecr %lu\n",
+		       is_init(tsk) ? KERN_EMERG : KERN_INFO,
+		       tsk->comm, tsk->pid, address, regs->pc,
+		       regs->sp, ecr);
+
+	_exception(SIGBUS, regs, BUS_ADRERR, address);
 }
 
 asmlinkage void do_bus_error(unsigned long addr, int write_access,
@@ -292,8 +247,7 @@
 	       addr, write_access ? "write" : "read");
 	printk(KERN_INFO "DTLB dump:\n");
 	dump_dtlb();
-	die("Bus Error", regs, write_access);
-	do_exit(SIGKILL);
+	die("Bus Error", regs, SIGKILL);
 }
 
 /*
diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/mm/init.c avr32-git/arch/avr32/mm/init.c
--- linux-2.6.21.3/arch/avr32/mm/init.c	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/arch/avr32/mm/init.c	2007-06-06 11:33:46.000000000 +0200
@@ -10,11 +10,9 @@
 #include <linux/mm.h>
 #include <linux/swap.h>
 #include <linux/init.h>
-#include <linux/initrd.h>
 #include <linux/mmzone.h>
 #include <linux/bootmem.h>
 #include <linux/pagemap.h>
-#include <linux/pfn.h>
 #include <linux/nodemask.h>
 
 #include <asm/page.h>
@@ -78,242 +76,6 @@
 	printk ("%d pages swap cached\n", cached);
 }
 
-static void __init print_memory_map(const char *what,
-				    struct tag_mem_range *mem)
-{
-	printk ("%s:\n", what);
-	for (; mem; mem = mem->next) {
-		printk ("  %08lx - %08lx\n",
-			(unsigned long)mem->addr,
-			(unsigned long)(mem->addr + mem->size));
-	}
-}
-
-#define MAX_LOWMEM	HIGHMEM_START
-#define MAX_LOWMEM_PFN	PFN_DOWN(MAX_LOWMEM)
-
-/*
- * Sort a list of memory regions in-place by ascending address.
- *
- * We're using bubble sort because we only have singly linked lists
- * with few elements.
- */
-static void __init sort_mem_list(struct tag_mem_range **pmem)
-{
-	int done;
-	struct tag_mem_range **a, **b;
-
-	if (!*pmem)
-		return;
-
-	do {
-		done = 1;
-		a = pmem, b = &(*pmem)->next;
-		while (*b) {
-			if ((*a)->addr > (*b)->addr) {
-				struct tag_mem_range *tmp;
-				tmp = (*b)->next;
-				(*b)->next = *a;
-				*a = *b;
-				*b = tmp;
-				done = 0;
-			}
-			a = &(*a)->next;
-			b = &(*a)->next;
-		}
-	} while (!done);
-}
-
-/*
- * Find a free memory region large enough for storing the
- * bootmem bitmap.
- */
-static unsigned long __init
-find_bootmap_pfn(const struct tag_mem_range *mem)
-{
-	unsigned long bootmap_pages, bootmap_len;
-	unsigned long node_pages = PFN_UP(mem->size);
-	unsigned long bootmap_addr = mem->addr;
-	struct tag_mem_range *reserved = mem_reserved;
-	struct tag_mem_range *ramdisk = mem_ramdisk;
-	unsigned long kern_start = virt_to_phys(_stext);
-	unsigned long kern_end = virt_to_phys(_end);
-
-	bootmap_pages = bootmem_bootmap_pages(node_pages);
-	bootmap_len = bootmap_pages << PAGE_SHIFT;
-
-	/*
-	 * Find a large enough region without reserved pages for
-	 * storing the bootmem bitmap. We can take advantage of the
-	 * fact that all lists have been sorted.
-	 *
-	 * We have to check explicitly reserved regions as well as the
-	 * kernel image and any RAMDISK images...
-	 *
-	 * Oh, and we have to make sure we don't overwrite the taglist
-	 * since we're going to use it until the bootmem allocator is
-	 * fully up and running.
-	 */
-	while (1) {
-		if ((bootmap_addr < kern_end) &&
-		    ((bootmap_addr + bootmap_len) > kern_start))
-			bootmap_addr = kern_end;
-
-		while (reserved &&
-		       (bootmap_addr >= (reserved->addr + reserved->size)))
-			reserved = reserved->next;
-
-		if (reserved &&
-		    ((bootmap_addr + bootmap_len) >= reserved->addr)) {
-			bootmap_addr = reserved->addr + reserved->size;
-			continue;
-		}
-
-		while (ramdisk &&
-		       (bootmap_addr >= (ramdisk->addr + ramdisk->size)))
-			ramdisk = ramdisk->next;
-
-		if (!ramdisk ||
-		    ((bootmap_addr + bootmap_len) < ramdisk->addr))
-			break;
-
-		bootmap_addr = ramdisk->addr + ramdisk->size;
-	}
-
-	if ((PFN_UP(bootmap_addr) + bootmap_len) >= (mem->addr + mem->size))
-		return ~0UL;
-
-	return PFN_UP(bootmap_addr);
-}
-
-void __init setup_bootmem(void)
-{
-	unsigned bootmap_size;
-	unsigned long first_pfn, bootmap_pfn, pages;
-	unsigned long max_pfn, max_low_pfn;
-	unsigned long kern_start = virt_to_phys(_stext);
-	unsigned long kern_end = virt_to_phys(_end);
-	unsigned node = 0;
-	struct tag_mem_range *bank, *res;
-
-	sort_mem_list(&mem_phys);
-	sort_mem_list(&mem_reserved);
-
-	print_memory_map("Physical memory", mem_phys);
-	print_memory_map("Reserved memory", mem_reserved);
-
-	nodes_clear(node_online_map);
-
-	if (mem_ramdisk) {
-#ifdef CONFIG_BLK_DEV_INITRD
-		initrd_start = (unsigned long)__va(mem_ramdisk->addr);
-		initrd_end = initrd_start + mem_ramdisk->size;
-
-		print_memory_map("RAMDISK images", mem_ramdisk);
-		if (mem_ramdisk->next)
-			printk(KERN_WARNING
-			       "Warning: Only the first RAMDISK image "
-			       "will be used\n");
-		sort_mem_list(&mem_ramdisk);
-#else
-		printk(KERN_WARNING "RAM disk image present, but "
-		       "no initrd support in kernel!\n");
-#endif
-	}
-
-	if (mem_phys->next)
-		printk(KERN_WARNING "Only using first memory bank\n");
-
-	for (bank = mem_phys; bank; bank = NULL) {
-		first_pfn = PFN_UP(bank->addr);
-		max_low_pfn = max_pfn = PFN_DOWN(bank->addr + bank->size);
-		bootmap_pfn = find_bootmap_pfn(bank);
-		if (bootmap_pfn > max_pfn)
-			panic("No space for bootmem bitmap!\n");
-
-		if (max_low_pfn > MAX_LOWMEM_PFN) {
-			max_low_pfn = MAX_LOWMEM_PFN;
-#ifndef CONFIG_HIGHMEM
-			/*
-			 * Lowmem is memory that can be addressed
-			 * directly through P1/P2
-			 */
-			printk(KERN_WARNING
-			       "Node %u: Only %ld MiB of memory will be used.\n",
-			       node, MAX_LOWMEM >> 20);
-			printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n");
-#else
-#error HIGHMEM is not supported by AVR32 yet
-#endif
-		}
-
-		/* Initialize the boot-time allocator with low memory only. */
-		bootmap_size = init_bootmem_node(NODE_DATA(node), bootmap_pfn,
-						 first_pfn, max_low_pfn);
-
-		printk("Node %u: bdata = %p, bdata->node_bootmem_map = %p\n",
-		       node, NODE_DATA(node)->bdata,
-		       NODE_DATA(node)->bdata->node_bootmem_map);
-
-		/*
-		 * Register fully available RAM pages with the bootmem
-		 * allocator.
-		 */
-		pages = max_low_pfn - first_pfn;
-		free_bootmem_node (NODE_DATA(node), PFN_PHYS(first_pfn),
-				   PFN_PHYS(pages));
-
-		/*
-		 * Reserve space for the kernel image (if present in
-		 * this node)...
-		 */
-		if ((kern_start >= PFN_PHYS(first_pfn)) &&
-		    (kern_start < PFN_PHYS(max_pfn))) {
-			printk("Node %u: Kernel image %08lx - %08lx\n",
-			       node, kern_start, kern_end);
-			reserve_bootmem_node(NODE_DATA(node), kern_start,
-					     kern_end - kern_start);
-		}
-
-		/* ...the bootmem bitmap... */
-		reserve_bootmem_node(NODE_DATA(node),
-				     PFN_PHYS(bootmap_pfn),
-				     bootmap_size);
-
-		/* ...any RAMDISK images... */
-		for (res = mem_ramdisk; res; res = res->next) {
-			if (res->addr > PFN_PHYS(max_pfn))
-				break;
-
-			if (res->addr >= PFN_PHYS(first_pfn)) {
-				printk("Node %u: RAMDISK %08lx - %08lx\n",
-				       node,
-				       (unsigned long)res->addr,
-				       (unsigned long)(res->addr + res->size));
-				reserve_bootmem_node(NODE_DATA(node),
-						     res->addr, res->size);
-			}
-		}
-
-		/* ...and any other reserved regions. */
-		for (res = mem_reserved; res; res = res->next) {
-			if (res->addr > PFN_PHYS(max_pfn))
-				break;
-
-			if (res->addr >= PFN_PHYS(first_pfn)) {
-				printk("Node %u: Reserved %08lx - %08lx\n",
-				       node,
-				       (unsigned long)res->addr,
-				       (unsigned long)(res->addr + res->size));
-				reserve_bootmem_node(NODE_DATA(node),
-						     res->addr, res->size);
-			}
-		}
-
-		node_set_online(node);
-	}
-}
-
 /*
  * paging_init() sets up the page tables
  *
diff -Nur -x .gitignore -x .git linux-2.6.21.3/drivers/i2c/busses/atmeltwi.h avr32-git/drivers/i2c/busses/atmeltwi.h
--- linux-2.6.21.3/drivers/i2c/busses/atmeltwi.h	1970-01-01 01:00:00.000000000 +0100
+++ avr32-git/drivers/i2c/busses/atmeltwi.h	2007-06-06 11:33:51.000000000 +0200
@@ -0,0 +1,117 @@
+/*
+ * Register definitions for the Atmel Two-Wire Interface
+ */
+
+#ifndef __ASM_AVR32_TWI_H__
+#define __ASM_AVR32_TWI_H__
+
+/* TWI register offsets */
+#define TWI_CR					0x0000
+#define TWI_MMR					0x0004
+#define TWI_SMR					0x0008
+#define TWI_IADR				0x000c
+#define TWI_CWGR				0x0010
+#define TWI_SR					0x0020
+#define TWI_IER					0x0024
+#define TWI_IDR					0x0028
+#define TWI_IMR					0x002c
+#define TWI_RHR					0x0030
+#define TWI_THR					0x0034
+
+/* Bitfields in CR */
+#define TWI_START_OFFSET			0
+#define TWI_START_SIZE				1
+#define TWI_STOP_OFFSET				1
+#define TWI_STOP_SIZE				1
+#define TWI_MSEN_OFFSET				2
+#define TWI_MSEN_SIZE				1
+#define TWI_MSDIS_OFFSET			3
+#define TWI_MSDIS_SIZE				1
+#define TWI_SVEN_OFFSET				4
+#define TWI_SVEN_SIZE				1
+#define TWI_SVDIS_OFFSET			5
+#define TWI_SVDIS_SIZE				1
+#define TWI_SWRST_OFFSET			7
+#define TWI_SWRST_SIZE				1
+
+/* Bitfields in MMR */
+#define TWI_IADRSZ_OFFSET			8
+#define TWI_IADRSZ_SIZE				2
+#define TWI_MREAD_OFFSET			12
+#define TWI_MREAD_SIZE				1
+#define TWI_DADR_OFFSET				16
+#define TWI_DADR_SIZE				7
+
+/* Bitfields in SMR */
+#define TWI_SADR_OFFSET				16
+#define TWI_SADR_SIZE				7
+
+/* Bitfields in IADR */
+#define TWI_IADR_OFFSET				0
+#define TWI_IADR_SIZE				24
+
+/* Bitfields in CWGR */
+#define TWI_CLDIV_OFFSET			0
+#define TWI_CLDIV_SIZE				8
+#define TWI_CHDIV_OFFSET			8
+#define TWI_CHDIV_SIZE				8
+#define TWI_CKDIV_OFFSET			16
+#define TWI_CKDIV_SIZE				3
+
+/* Bitfields in SR */
+#define TWI_TXCOMP_OFFSET			0
+#define TWI_TXCOMP_SIZE				1
+#define TWI_RXRDY_OFFSET			1
+#define TWI_RXRDY_SIZE				1
+#define TWI_TXRDY_OFFSET			2
+#define TWI_TXRDY_SIZE				1
+#define TWI_SVDIR_OFFSET			3
+#define TWI_SVDIR_SIZE				1
+#define TWI_SVACC_OFFSET			4
+#define TWI_SVACC_SIZE				1
+#define TWI_GCACC_OFFSET			5
+#define TWI_GCACC_SIZE				1
+#define TWI_OVRE_OFFSET				6
+#define TWI_OVRE_SIZE				1
+#define TWI_UNRE_OFFSET				7
+#define TWI_UNRE_SIZE				1
+#define TWI_NACK_OFFSET				8
+#define TWI_NACK_SIZE				1
+#define TWI_ARBLST_OFFSET			9
+#define TWI_ARBLST_SIZE				1
+
+/* Bitfields in RHR */
+#define TWI_RXDATA_OFFSET			0
+#define TWI_RXDATA_SIZE				8
+
+/* Bitfields in THR */
+#define TWI_TXDATA_OFFSET			0
+#define TWI_TXDATA_SIZE				8
+
+/* Constants for IADRSZ */
+#define TWI_IADRSZ_NO_ADDR			0
+#define TWI_IADRSZ_ONE_BYTE			1
+#define TWI_IADRSZ_TWO_BYTES			2
+#define TWI_IADRSZ_THREE_BYTES			3
+
+/* Bit manipulation macros */
+#define TWI_BIT(name)					\
+	(1 << TWI_##name##_OFFSET)
+#define TWI_BF(name,value)				\
+	(((value) & ((1 << TWI_##name##_SIZE) - 1))	\
+	 << TWI_##name##_OFFSET)
+#define TWI_BFEXT(name,value)				\
+	(((value) >> TWI_##name##_OFFSET)		\
+	 & ((1 << TWI_##name##_SIZE) - 1))
+#define TWI_BFINS(name,value,old)			\
+	(((old) & ~(((1 << TWI_##name##_SIZE) - 1)	\
+		    << TWI_##name##_OFFSET))		\
+	 | TWI_BF(name,value))
+
+/* Register access macros */
+#define twi_readl(port,reg)				\
+	__raw_readl((port)->regs + TWI_##reg)
+#define twi_writel(port,reg,value)			\
+	__raw_writel((value), (port)->regs + TWI_##reg)
+
+#endif /* __ASM_AVR32_TWI_H__ */
diff -Nur -x .gitignore -x .git linux-2.6.21.3/drivers/i2c/busses/i2c-atmeltwi.c avr32-git/drivers/i2c/busses/i2c-atmeltwi.c
--- linux-2.6.21.3/drivers/i2c/busses/i2c-atmeltwi.c	1970-01-01 01:00:00.000000000 +0100
+++ avr32-git/drivers/i2c/busses/i2c-atmeltwi.c	2007-06-06 11:33:51.000000000 +0200
@@ -0,0 +1,348 @@
+/*
+ * i2c Support for Atmel's Two-Wire Interface (TWI)
+ *
+ * Based on the work of Copyright (C) 2004 Rick Bronson
+ * Converted to 2.6 by Andrew Victor <andrew at sanpeople.com>
+ * Ported to AVR32 and heavily modified by Espen Krangnes <ekrangnes at atmel.com>
+ *
+ * Copyright (C) 2006 Atmel Corporation
+ *
+ * Borrowed heavily from the original work by:
+ * Copyright (C) 2000 Philip Edelbrock <phil at stimpy.netroedge.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/completion.h>
+#include <asm/io.h>
+#include <linux/time.h>
+#include "atmeltwi.h"
+
+static unsigned int baudrate = CONFIG_I2C_ATMELTWI_BAUDRATE;
+module_param(baudrate, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+MODULE_PARM_DESC(baudrate, "The TWI baudrate");
+
+
+struct atmel_twi {
+	void __iomem *regs;
+	struct i2c_adapter adapter;
+	struct clk *pclk;
+	spinlock_t lock;
+	struct completion comp;
+	u32 intmask;
+	u8 *buf;
+	u8 len;
+	u8 acks_left;
+	unsigned int irq;
+
+};
+#define to_atmel_twi(adap) container_of(adap, struct atmel_twi, adapter)
+
+/*
+ * Initialize the TWI hardware registers.
+ */
+static int __devinit twi_hwinit(struct atmel_twi *twi)
+{
+	unsigned long cdiv, ckdiv=0;
+
+	twi_writel(twi, IDR, ~0UL);
+	twi_writel(twi, CR, TWI_BIT(SWRST));	/*Reset peripheral*/
+	twi_readl(twi, SR);
+
+	cdiv = (clk_get_rate(twi->pclk) / (2 * baudrate)) - 4;
+
+	while (cdiv > 255) {
+		ckdiv++;
+		cdiv = cdiv >> 1;
+	}
+
+	if (ckdiv > 7)
+		return -EINVAL;
+	else
+		twi_writel(twi, CWGR, (TWI_BF(CKDIV, ckdiv)
+			       | TWI_BF(CHDIV, cdiv)
+			       | TWI_BF(CLDIV, cdiv)));
+	return 0;
+}
+
+/*
+ * Waits for the i2c status register to set the specified bitmask
+ * Returns 0 if timed out (~100ms).
+ */
+static short twi_wait_for_completion(struct atmel_twi *twi,
+		u32 mask)
+{
+	int timeout = msecs_to_jiffies(100);
+
+	twi->intmask = mask;
+	init_completion(&twi->comp);
+
+	twi_writel(twi, IER, mask);
+
+	if(!wait_for_completion_timeout(&twi->comp, timeout))
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+/*
+ * Generic i2c master transfer entrypoint.
+ */
+static int twi_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
+{
+	struct atmel_twi *twi = to_atmel_twi(adap);
+	struct i2c_msg *pmsg;
+	int i;
+
+	/* get first message */
+	pmsg = msgs;
+
+	dev_dbg(&adap->dev, "twi_xfer: processing %d messages:\n", num);
+
+	for (i = 0; i < num; i++, pmsg++) {
+
+		twi->len = pmsg->len;
+		twi->buf = pmsg->buf;
+		twi->acks_left = pmsg->len;
+		twi_writel(twi, MMR, TWI_BF(DADR, pmsg->addr) |
+			(pmsg->flags & I2C_M_RD ? TWI_BIT(MREAD) : 0));
+		twi_writel(twi, IADR, TWI_BF(IADR, pmsg->addr));
+
+		dev_dbg(&adap->dev,"#%d: internal addr %d %s byte%s %s 0x%02x\n",
+			i,pmsg->len, pmsg->flags & I2C_M_RD ? "reading" : "writing",
+			pmsg->len > 1 ? "s" : "",
+			pmsg->flags & I2C_M_RD ? "from" : "to", pmsg->addr);
+
+		/* enable */
+		twi_writel(twi, CR, TWI_BIT(MSEN));
+
+		if (pmsg->flags & I2C_M_RD) {
+			twi_writel(twi, CR, TWI_BIT(START));
+			if ( twi_wait_for_completion(twi,TWI_BIT(RXRDY))==-ETIMEDOUT ) {
+				dev_dbg(&adap->dev, "RXRDY timeout. Stopped with %d bytes left\n",
+					twi->acks_left);
+				return -ETIMEDOUT;
+			}
+
+			/* Send Stop, and Wait until transfer is finished */
+			if ( twi_wait_for_completion(twi,TWI_BIT(TXCOMP))==-ETIMEDOUT ) {
+				dev_dbg(&adap->dev, "TXCOMP timeout\n");
+				return -ETIMEDOUT;
+			}
+
+		} else {
+			twi_writel(twi, THR, twi->buf[0]);
+			if ( twi_wait_for_completion(twi,TWI_BIT(TXRDY))==-ETIMEDOUT ) {
+				dev_dbg(&adap->dev, "TXRDY timeout. Stopped with %d bytes left\n",
+				twi->acks_left);
+				return -ETIMEDOUT;
+			}
+		}
+
+		/* Disable TWI interface */
+		twi_writel(twi, CR, TWI_BIT(MSDIS));
+
+	} /* end cur msg */
+
+	return i;
+}
+
+
+static irqreturn_t twi_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct atmel_twi *twi = dev_id;
+	int status = twi_readl(twi, SR);
+
+	if (twi->intmask & status){
+		if (twi->intmask & TWI_BIT(NACK)) {
+			goto nack;
+		} else if (twi->intmask & TWI_BIT(RXRDY)){
+			twi->buf[twi->len - twi->acks_left] = twi_readl(twi,RHR);
+			if(--twi->acks_left==1)
+				twi_writel(twi, CR, TWI_BIT(STOP));
+			if (twi->acks_left==0)
+				goto complete;
+		} else if (twi->intmask & TWI_BIT(TXRDY)) {
+			twi->acks_left--;
+			if (twi->acks_left==0) {
+				twi->intmask = TWI_BIT(TXCOMP);
+				twi_writel(twi, IER, TWI_BIT(TXCOMP));
+			} else
+				twi_writel(twi, THR, twi->buf[twi->len - twi->acks_left]);
+		} else if (twi->intmask & TWI_BIT(TXCOMP)) {
+			goto complete;
+		}
+	}
+
+	return IRQ_HANDLED;
+
+nack:
+	printk(KERN_INFO "NACK received!\n");
+
+complete:
+	twi_writel(twi, IDR, ~0UL);
+	complete(&twi->comp);
+
+	return IRQ_HANDLED;
+
+}
+
+
+/*
+ * Return list of supported functionality.
+ */
+static u32 twi_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+/* For now, we only handle combined mode (smbus) */
+static struct i2c_algorithm twi_algorithm = {
+	.master_xfer	= twi_xfer,
+	.functionality	= twi_func,
+};
+
+/*
+ * Main initialization routine.
+ */
+static int __devinit twi_probe(struct platform_device *pdev)
+{
+	struct atmel_twi *twi;
+	struct resource *regs;
+	struct clk *pclk;
+	struct i2c_adapter *adapter;
+	int rc, irq;
+
+	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!regs)
+		return -ENXIO;
+
+	pclk = clk_get(&pdev->dev, "pclk");
+	if (IS_ERR(pclk))
+		return PTR_ERR(pclk);
+	clk_enable(pclk);
+
+	rc = -ENOMEM;
+	twi = kzalloc(sizeof(struct atmel_twi), GFP_KERNEL);
+	if (!twi) {
+		dev_err(&pdev->dev, "can't allocate interface!\n");
+		goto err_alloc_twi;
+	}
+
+	twi->pclk = pclk;
+	twi->regs = ioremap(regs->start, regs->end - regs->start + 1);
+	if (!twi->regs)
+		goto err_ioremap;
+
+	irq = platform_get_irq(pdev,0);
+	rc = request_irq(irq, twi_interrupt, 0, "twi", twi);
+	if (rc) {
+		dev_err(&pdev->dev, "can't bind irq!\n");
+		goto err_irq;
+	}
+	twi->irq = irq;
+
+	rc = twi_hwinit(twi);
+	if (rc) {
+		dev_err(&pdev->dev, "Unable to set baudrate\n");
+		goto err_hw_init;
+	}
+
+	adapter = &twi->adapter;
+	sprintf(adapter->name, "TWI");
+	adapter->algo = &twi_algorithm;
+	adapter->class = I2C_CLASS_HWMON;
+	adapter->dev.parent = &pdev->dev;
+
+	platform_set_drvdata(pdev, twi);
+
+	rc = i2c_add_adapter(adapter);
+	if (rc) {
+		dev_err(&pdev->dev, "Adapter %s registration failed\n",
+			adapter->name);
+		goto err_register;
+	}
+
+	dev_info(&pdev->dev, "Atmel TWI i2c bus device (baudrate %dk) at 0x%08lx.\n",
+		 baudrate/1000, (unsigned long)regs->start);
+
+	return 0;
+
+
+err_register:
+	platform_set_drvdata(pdev, NULL);
+
+err_hw_init:
+	free_irq(irq, twi);
+
+err_irq:
+	iounmap(twi->regs);
+
+err_ioremap:
+	kfree(twi);
+
+err_alloc_twi:
+	clk_disable(pclk);
+	clk_put(pclk);
+
+	return rc;
+}
+
+static int __devexit twi_remove(struct platform_device *pdev)
+{
+	struct atmel_twi *twi = platform_get_drvdata(pdev);
+	int res;
+
+	platform_set_drvdata(pdev, NULL);
+	res = i2c_del_adapter(&twi->adapter);
+	twi_writel(twi, CR, TWI_BIT(MSDIS));
+	iounmap(twi->regs);
+	clk_disable(twi->pclk);
+	clk_put(twi->pclk);
+	free_irq(twi->irq, twi);
+	kfree(twi);
+
+	return res;
+}
+
+static struct platform_driver twi_driver = {
+	.probe		= twi_probe,
+	.remove		= __devexit_p(twi_remove),
+	.driver		= {
+		.name	= "atmel_twi",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init atmel_twi_init(void)
+{
+	return platform_driver_register(&twi_driver);
+}
+
+static void __exit atmel_twi_exit(void)
+{
+	platform_driver_unregister(&twi_driver);
+}
+
+module_init(atmel_twi_init);
+module_exit(atmel_twi_exit);
+
+MODULE_AUTHOR("Espen Krangnes");
+MODULE_DESCRIPTION("I2C driver for Atmel TWI");
+MODULE_LICENSE("GPL");
diff -Nur -x .gitignore -x .git linux-2.6.21.3/drivers/i2c/busses/i2c-gpio.c avr32-git/drivers/i2c/busses/i2c-gpio.c
--- linux-2.6.21.3/drivers/i2c/busses/i2c-gpio.c	1970-01-01 01:00:00.000000000 +0100
+++ avr32-git/drivers/i2c/busses/i2c-gpio.c	2007-06-06 11:33:51.000000000 +0200
@@ -0,0 +1,215 @@
+/*
+ * Bitbanging I2C bus driver using the GPIO API
+ *
+ * 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.
+ */
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/i2c-gpio.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/gpio.h>
+
+/* Toggle SDA by changing the direction of the pin */
+static void i2c_gpio_setsda_dir(void *data, int state)
+{
+	struct i2c_gpio_platform_data *pdata = data;
+
+	if (state)
+		gpio_direction_input(pdata->sda_pin);
+	else
+		gpio_direction_output(pdata->sda_pin, 0);
+}
+
+/*
+ * Toggle SDA by changing the output value of the pin. This is only
+ * valid for pins configured as open drain (i.e. setting the value
+ * high effectively turns off the output driver.)
+ */
+static void i2c_gpio_setsda_val(void *data, int state)
+{
+	struct i2c_gpio_platform_data *pdata = data;
+
+	gpio_set_value(pdata->sda_pin, state);
+}
+
+/* Toggle SCL by changing the direction of the pin. */
+static void i2c_gpio_setscl_dir(void *data, int state)
+{
+	struct i2c_gpio_platform_data *pdata = data;
+
+	if (state)
+		gpio_direction_input(pdata->scl_pin);
+	else
+		gpio_direction_output(pdata->scl_pin, 0);
+}
+
+/*
+ * Toggle SCL by changing the output value of the pin. This is used
+ * for pins that are configured as open drain and for output-only
+ * pins. The latter case will break the i2c protocol, but it will
+ * often work in practice.
+ */
+static void i2c_gpio_setscl_val(void *data, int state)
+{
+	struct i2c_gpio_platform_data *pdata = data;
+
+	gpio_set_value(pdata->scl_pin, state);
+}
+
+int i2c_gpio_getsda(void *data)
+{
+	struct i2c_gpio_platform_data *pdata = data;
+
+	return gpio_get_value(pdata->sda_pin);
+}
+
+int i2c_gpio_getscl(void *data)
+{
+	struct i2c_gpio_platform_data *pdata = data;
+
+	return gpio_get_value(pdata->scl_pin);
+}
+
+static int __init i2c_gpio_probe(struct platform_device *pdev)
+{
+	struct i2c_gpio_platform_data *pdata;
+	struct i2c_algo_bit_data *bit_data;
+	struct i2c_adapter *adap;
+	int ret;
+
+	pdata = pdev->dev.platform_data;
+	if (!pdata)
+		return -ENXIO;
+
+	ret = -ENOMEM;
+	adap = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
+	if (!adap)
+		goto err_alloc_adap;
+	bit_data = kzalloc(sizeof(struct i2c_algo_bit_data), GFP_KERNEL);
+	if (!bit_data)
+		goto err_alloc_bit_data;
+
+	ret = gpio_request(pdata->sda_pin, "sda");
+	if (ret)
+		goto err_request_sda;
+	ret = gpio_request(pdata->scl_pin, "scl");
+	if (ret)
+		goto err_request_scl;
+
+	if (pdata->sda_is_open_drain) {
+		gpio_direction_output(pdata->sda_pin, 1);
+		bit_data->setsda = i2c_gpio_setsda_val;
+	} else {
+		gpio_direction_input(pdata->sda_pin);
+		bit_data->setsda = i2c_gpio_setsda_dir;
+	}
+
+	if (pdata->scl_is_open_drain || pdata->scl_is_output_only) {
+		gpio_direction_output(pdata->scl_pin, 1);
+		bit_data->setscl = i2c_gpio_setscl_val;
+	} else {
+		gpio_direction_input(pdata->scl_pin);
+		bit_data->setscl = i2c_gpio_setscl_dir;
+	}
+
+	if (!pdata->scl_is_output_only)
+		bit_data->getscl = i2c_gpio_getscl;
+	bit_data->getsda = i2c_gpio_getsda;
+
+	if (pdata->udelay)
+		bit_data->udelay = pdata->udelay;
+	else if (pdata->scl_is_output_only)
+		bit_data->udelay = 50;			/* 10 kHz */
+	else
+		bit_data->udelay = 5;			/* 100 kHz */
+
+	if (pdata->timeout)
+		bit_data->timeout = pdata->timeout;
+	else
+		bit_data->timeout = HZ / 10;		/* 100 ms */
+
+	bit_data->data = pdata;
+
+	adap->owner = THIS_MODULE;
+	snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id);
+	adap->algo_data = bit_data;
+	adap->dev.parent = &pdev->dev;
+
+	ret = i2c_bit_add_bus(adap);
+	if (ret)
+		goto err_add_bus;
+
+	platform_set_drvdata(pdev, adap);
+
+	dev_info(&pdev->dev, "using pins %u (SDA) and %u (SCL%s)\n",
+		 pdata->sda_pin, pdata->scl_pin,
+		 pdata->scl_is_output_only
+		 ? ", no clock stretching" : "");
+
+	return 0;
+
+err_add_bus:
+	gpio_free(pdata->scl_pin);
+err_request_scl:
+	gpio_free(pdata->sda_pin);
+err_request_sda:
+	kfree(bit_data);
+err_alloc_bit_data:
+	kfree(adap);
+err_alloc_adap:
+	return ret;
+}
+
+static int __exit i2c_gpio_remove(struct platform_device *pdev)
+{
+	struct i2c_gpio_platform_data *pdata;
+	struct i2c_adapter *adap;
+
+	adap = platform_get_drvdata(pdev);
+	pdata = pdev->dev.platform_data;
+
+	i2c_del_adapter(adap);
+	gpio_free(pdata->scl_pin);
+	gpio_free(pdata->sda_pin);
+	kfree(adap->algo_data);
+	kfree(adap);
+
+	return 0;
+}
+
+static struct platform_driver i2c_gpio_driver = {
+	.driver		= {
+		.name	= "i2c-gpio",
+		.owner	= THIS_MODULE,
+	},
+	.remove		= __exit_p(i2c_gpio_remove),
+};
+
+static int __init i2c_gpio_init(void)
+{
+	int ret;
+
+	ret = platform_driver_probe(&i2c_gpio_driver, i2c_gpio_probe);
+	if (ret)
+		printk(KERN_ERR "i2c-gpio: probe failed: %d\n", ret);
+
+	return ret;
+}
+module_init(i2c_gpio_init);
+
+static void __exit i2c_gpio_exit(void)
+{
+	platform_driver_unregister(&i2c_gpio_driver);
+}
+module_exit(i2c_gpio_exit);
+
+MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>");
+MODULE_DESCRIPTION("Platform-independent bitbanging I2C driver");
+MODULE_LICENSE("GPL");
diff -Nur -x .gitignore -x .git linux-2.6.21.3/drivers/i2c/busses/Kconfig avr32-git/drivers/i2c/busses/Kconfig
--- linux-2.6.21.3/drivers/i2c/busses/Kconfig	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/drivers/i2c/busses/Kconfig	2007-06-06 11:33:51.000000000 +0200
@@ -5,6 +5,26 @@
 menu "I2C Hardware Bus support"
 	depends on I2C
 
+config I2C_ATMELTWI
+	tristate "Atmel TWI/I2C"
+	depends on I2C
+	help
+	  Atmel on-chip TWI controller. Say Y if you have an AT32 or
+	  AT91-based device and want to use its built-in TWI
+	  functionality. Atmel's TWI is compatible with Philips' I2C
+	  protocol. If in doubt, say NO
+
+config I2C_ATMELTWI_BAUDRATE
+	prompt "Atmel TWI baudrate"
+	depends on I2C_ATMELTWI
+	int
+	default 100000
+	help
+	  Set the TWI/I2C baudrate. This will alter the default value. A
+	  different baudrate can be set by using a module parameter as well. If
+	  no parameter is provided when loading, this is the value that will be
+	  used.
+
 config I2C_ALI1535
 	tristate "ALI 1535"
 	depends on I2C && PCI
@@ -102,6 +122,14 @@
 	  This support is also available as a module.  If so, the module 
 	  will be called i2c-elektor.
 
+config I2C_GPIO
+	tristate "GPIO-based bitbanging I2C"
+	depends on GENERIC_GPIO
+	select I2C_ALGOBIT
+	help
+	  This is a very simple bitbanging I2C driver utilizing the
+	  arch-neutral GPIO API to control the SCL and SDA lines.
+
 config I2C_HYDRA
 	tristate "CHRP Apple Hydra Mac I/O I2C interface"
 	depends on I2C && PCI && PPC_CHRP && EXPERIMENTAL
diff -Nur -x .gitignore -x .git linux-2.6.21.3/drivers/i2c/busses/Makefile avr32-git/drivers/i2c/busses/Makefile
--- linux-2.6.21.3/drivers/i2c/busses/Makefile	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/drivers/i2c/busses/Makefile	2007-06-06 11:33:51.000000000 +0200
@@ -11,6 +11,7 @@
 obj-$(CONFIG_I2C_AT91)		+= i2c-at91.o
 obj-$(CONFIG_I2C_AU1550)	+= i2c-au1550.o
 obj-$(CONFIG_I2C_ELEKTOR)	+= i2c-elektor.o
+obj-$(CONFIG_I2C_GPIO)		+= i2c-gpio.o
 obj-$(CONFIG_I2C_HYDRA)		+= i2c-hydra.o
 obj-$(CONFIG_I2C_I801)		+= i2c-i801.o
 obj-$(CONFIG_I2C_I810)		+= i2c-i810.o
@@ -48,6 +49,7 @@
 obj-$(CONFIG_I2C_VOODOO3)	+= i2c-voodoo3.o
 obj-$(CONFIG_SCx200_ACB)	+= scx200_acb.o
 obj-$(CONFIG_SCx200_I2C)	+= scx200_i2c.o
+obj-$(CONFIG_I2C_ATMELTWI)	+= i2c-atmeltwi.o
 
 ifeq ($(CONFIG_I2C_DEBUG_BUS),y)
 EXTRA_CFLAGS += -DDEBUG
diff -Nur -x .gitignore -x .git linux-2.6.21.3/drivers/mmc/atmel-mci.c avr32-git/drivers/mmc/atmel-mci.c
--- linux-2.6.21.3/drivers/mmc/atmel-mci.c	1970-01-01 01:00:00.000000000 +0100
+++ avr32-git/drivers/mmc/atmel-mci.c	2007-06-06 11:33:56.000000000 +0200
@@ -0,0 +1,1218 @@
+/*
+ * Atmel MultiMedia Card Interface driver
+ *
+ * Copyright (C) 2004-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/blkdev.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <linux/mmc/host.h>
+#include <linux/mmc/protocol.h>
+
+#include <asm/dma-controller.h>
+#include <asm/io.h>
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+#include "atmel-mci.h"
+
+#define DRIVER_NAME "atmel_mci"
+
+#define MCI_CMD_ERROR_FLAGS	(MCI_BIT(RINDE)	| MCI_BIT(RDIRE) |	\
+				 MCI_BIT(RCRCE) | MCI_BIT(RENDE) |	\
+				 MCI_BIT(RTOE))
+#define MCI_DATA_ERROR_FLAGS	(MCI_BIT(DCRCE) | MCI_BIT(DTOE) |	\
+				 MCI_BIT(OVRE) | MCI_BIT(UNRE))
+
+enum {
+	EVENT_CMD_COMPLETE = 0,
+	EVENT_CMD_ERROR,
+	EVENT_DATA_COMPLETE,
+	EVENT_DATA_ERROR,
+	EVENT_STOP_SENT,
+	EVENT_STOP_COMPLETE,
+	EVENT_STOP_ERROR,
+	EVENT_DMA_ERROR,
+	EVENT_CARD_DETECT,
+};
+
+struct atmel_mci_dma {
+	struct dma_request_sg	req;
+	unsigned short		rx_periph_id;
+	unsigned short		tx_periph_id;
+};
+
+struct atmel_mci {
+	struct mmc_host		*mmc;
+	void __iomem		*regs;
+	struct atmel_mci_dma	dma;
+
+	struct mmc_request	*mrq;
+	struct mmc_command	*cmd;
+	struct mmc_data		*data;
+
+	u32			stop_cmdr;
+	u32			stop_iflags;
+
+	struct tasklet_struct	tasklet;
+	unsigned long		pending_events;
+	unsigned long		completed_events;
+	u32			error_status;
+
+	int			present;
+	int			detect_pin;
+	int			wp_pin;
+
+	unsigned long		bus_hz;
+	unsigned long		mapbase;
+	struct clk		*mck;
+	struct platform_device	*pdev;
+
+#ifdef CONFIG_DEBUG_FS
+	struct dentry		*debugfs_root;
+	struct dentry		*debugfs_regs;
+	struct dentry		*debugfs_req;
+	struct dentry		*debugfs_pending_events;
+	struct dentry		*debugfs_completed_events;
+#endif
+};
+
+/* Those printks take an awful lot of time... */
+#ifndef DEBUG
+static unsigned int fmax = 15000000U;
+#else
+static unsigned int fmax = 1000000U;
+#endif
+module_param(fmax, uint, 0444);
+MODULE_PARM_DESC(fmax, "Max frequency in Hz of the MMC bus clock");
+
+/* Test bit macros for completed events */
+#define mci_cmd_is_complete(host)			\
+	test_bit(EVENT_CMD_COMPLETE, &host->completed_events)
+#define mci_cmd_error_is_complete(host)			\
+	test_bit(EVENT_CMD_ERROR, &host->completed_events)
+#define mci_data_is_complete(host)			\
+	test_bit(EVENT_DATA_COMPLETE, &host->completed_events)
+#define mci_data_error_is_complete(host)		\
+	test_bit(EVENT_DATA_ERROR, &host->completed_events)
+#define mci_stop_sent_is_complete(host)			\
+	test_bit(EVENT_STOP_SENT, &host->completed_events)
+#define mci_stop_is_complete(host)			\
+	test_bit(EVENT_STOP_COMPLETE, &host->completed_events)
+#define mci_stop_error_is_complete(host)		\
+	test_bit(EVENT_STOP_ERROR, &host->completed_events)
+#define mci_dma_error_is_complete(host)			\
+	test_bit(EVENT_DMA_ERROR, &host->completed_events)
+#define mci_card_detect_is_complete(host)			\
+	test_bit(EVENT_CARD_DETECT, &host->completed_events)
+
+/* Test and clear bit macros for pending events */
+#define mci_clear_cmd_is_pending(host)			\
+	test_and_clear_bit(EVENT_CMD_COMPLETE, &host->pending_events)
+#define mci_clear_cmd_error_is_pending(host)		\
+	test_and_clear_bit(EVENT_CMD_ERROR, &host->pending_events)
+#define mci_clear_data_is_pending(host)			\
+	test_and_clear_bit(EVENT_DATA_COMPLETE, &host->pending_events)
+#define mci_clear_data_error_is_pending(host)		\
+	test_and_clear_bit(EVENT_DATA_ERROR, &host->pending_events)
+#define mci_clear_stop_sent_is_pending(host)		\
+	test_and_clear_bit(EVENT_STOP_SENT, &host->pending_events)
+#define mci_clear_stop_is_pending(host)			\
+	test_and_clear_bit(EVENT_STOP_COMPLETE, &host->pending_events)
+#define mci_clear_stop_error_is_pending(host)		\
+	test_and_clear_bit(EVENT_STOP_ERROR, &host->pending_events)
+#define mci_clear_dma_error_is_pending(host)		\
+	test_and_clear_bit(EVENT_DMA_ERROR, &host->pending_events)
+#define mci_clear_card_detect_is_pending(host)		\
+	test_and_clear_bit(EVENT_CARD_DETECT, &host->pending_events)
+
+/* Test and set bit macros for completed events */
+#define mci_set_cmd_is_completed(host)			\
+	test_and_set_bit(EVENT_CMD_COMPLETE, &host->completed_events)
+#define mci_set_cmd_error_is_completed(host)		\
+	test_and_set_bit(EVENT_CMD_ERROR, &host->completed_events)
+#define mci_set_data_is_completed(host)			\
+	test_and_set_bit(EVENT_DATA_COMPLETE, &host->completed_events)
+#define mci_set_data_error_is_completed(host)		\
+	test_and_set_bit(EVENT_DATA_ERROR, &host->completed_events)
+#define mci_set_stop_sent_is_completed(host)		\
+	test_and_set_bit(EVENT_STOP_SENT, &host->completed_events)
+#define mci_set_stop_is_completed(host)			\
+	test_and_set_bit(EVENT_STOP_COMPLETE, &host->completed_events)
+#define mci_set_stop_error_is_completed(host)		\
+	test_and_set_bit(EVENT_STOP_ERROR, &host->completed_events)
+#define mci_set_dma_error_is_completed(host)		\
+	test_and_set_bit(EVENT_DMA_ERROR, &host->completed_events)
+#define mci_set_card_detect_is_completed(host)		\
+	test_and_set_bit(EVENT_CARD_DETECT, &host->completed_events)
+
+/* Set bit macros for completed events */
+#define mci_set_cmd_complete(host)			\
+	set_bit(EVENT_CMD_COMPLETE, &host->completed_events)
+#define mci_set_cmd_error_complete(host)		\
+	set_bit(EVENT_CMD_ERROR, &host->completed_events)
+#define mci_set_data_complete(host)			\
+	set_bit(EVENT_DATA_COMPLETE, &host->completed_events)
+#define mci_set_data_error_complete(host)		\
+	set_bit(EVENT_DATA_ERROR, &host->completed_events)
+#define mci_set_stop_sent_complete(host)		\
+	set_bit(EVENT_STOP_SENT, &host->completed_events)
+#define mci_set_stop_complete(host)			\
+	set_bit(EVENT_STOP_COMPLETE, &host->completed_events)
+#define mci_set_stop_error_complete(host)		\
+	set_bit(EVENT_STOP_ERROR, &host->completed_events)
+#define mci_set_dma_error_complete(host)		\
+	set_bit(EVENT_DMA_ERROR, &host->completed_events)
+#define mci_set_card_detect_complete(host)		\
+	set_bit(EVENT_CARD_DETECT, &host->completed_events)
+
+/* Set bit macros for pending events */
+#define mci_set_cmd_pending(host)			\
+	set_bit(EVENT_CMD_COMPLETE, &host->pending_events)
+#define mci_set_cmd_error_pending(host)			\
+	set_bit(EVENT_CMD_ERROR, &host->pending_events)
+#define mci_set_data_pending(host)			\
+	set_bit(EVENT_DATA_COMPLETE, &host->pending_events)
+#define mci_set_data_error_pending(host)		\
+	set_bit(EVENT_DATA_ERROR, &host->pending_events)
+#define mci_set_stop_sent_pending(host)			\
+	set_bit(EVENT_STOP_SENT, &host->pending_events)
+#define mci_set_stop_pending(host)			\
+	set_bit(EVENT_STOP_COMPLETE, &host->pending_events)
+#define mci_set_stop_error_pending(host)		\
+	set_bit(EVENT_STOP_ERROR, &host->pending_events)
+#define mci_set_dma_error_pending(host)			\
+	set_bit(EVENT_DMA_ERROR, &host->pending_events)
+#define mci_set_card_detect_pending(host)		\
+	set_bit(EVENT_CARD_DETECT, &host->pending_events)
+
+/* Clear bit macros for pending events */
+#define mci_clear_cmd_pending(host)			\
+	clear_bit(EVENT_CMD_COMPLETE, &host->pending_events)
+#define mci_clear_cmd_error_pending(host)		\
+	clear_bit(EVENT_CMD_ERROR, &host->pending_events)
+#define mci_clear_data_pending(host)			\
+	clear_bit(EVENT_DATA_COMPLETE, &host->pending_events)
+#define mci_clear_data_error_pending(host)		\
+	clear_bit(EVENT_DATA_ERROR, &host->pending_events)
+#define mci_clear_stop_sent_pending(host)		\
+	clear_bit(EVENT_STOP_SENT, &host->pending_events)
+#define mci_clear_stop_pending(host)			\
+	clear_bit(EVENT_STOP_COMPLETE, &host->pending_events)
+#define mci_clear_stop_error_pending(host)		\
+	clear_bit(EVENT_STOP_ERROR, &host->pending_events)
+#define mci_clear_dma_error_pending(host)		\
+	clear_bit(EVENT_DMA_ERROR, &host->pending_events)
+#define mci_clear_card_detect_pending(host)		\
+	clear_bit(EVENT_CARD_DETECT, &host->pending_events)
+
+
+#ifdef CONFIG_DEBUG_FS
+#include <linux/debugfs.h>
+
+#define DBG_REQ_BUF_SIZE	(4096 - sizeof(unsigned int))
+
+struct req_dbg_data {
+	unsigned int nbytes;
+	char str[DBG_REQ_BUF_SIZE];
+};
+
+static int req_dbg_open(struct inode *inode, struct file *file)
+{
+	struct atmel_mci *host;
+	struct mmc_request *mrq;
+	struct mmc_command *cmd, *stop;
+	struct mmc_data *data;
+	struct req_dbg_data *priv;
+	char *str;
+	unsigned long n = 0;
+
+	priv = kzalloc(DBG_REQ_BUF_SIZE, GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+	str = priv->str;
+
+	mutex_lock(&inode->i_mutex);
+	host = inode->i_private;
+
+	spin_lock_irq(&host->mmc->lock);
+	mrq = host->mrq;
+	if (mrq) {
+		cmd = mrq->cmd;
+		data = mrq->data;
+		stop = mrq->stop;
+		n = snprintf(str, DBG_REQ_BUF_SIZE,
+			     "CMD%u(0x%x) %x %x %x %x %x (err %u)\n",
+			     cmd->opcode, cmd->arg, cmd->flags,
+			     cmd->resp[0], cmd->resp[1], cmd->resp[2],
+			     cmd->resp[3], cmd->error);
+		if (n < DBG_REQ_BUF_SIZE && data)
+			n += snprintf(str + n, DBG_REQ_BUF_SIZE - n,
+				      "DATA %u * %u (%u) %x (err %u)\n",
+				      data->blocks, data->blksz,
+				      data->bytes_xfered, data->flags,
+				      data->error);
+		if (n < DBG_REQ_BUF_SIZE && stop)
+			n += snprintf(str + n, DBG_REQ_BUF_SIZE - n,
+				      "CMD%u(0x%x) %x %x %x %x %x (err %u)\n",
+				      stop->opcode, stop->arg, stop->flags,
+				      stop->resp[0], stop->resp[1],
+				      stop->resp[2], stop->resp[3],
+				      stop->error);
+	}
+	spin_unlock_irq(&host->mmc->lock);
+	mutex_unlock(&inode->i_mutex);
+
+	priv->nbytes = min(n, DBG_REQ_BUF_SIZE);
+	file->private_data = priv;
+
+	return 0;
+}
+
+static ssize_t req_dbg_read(struct file *file, char __user *buf,
+			    size_t nbytes, loff_t *ppos)
+{
+	struct req_dbg_data *priv = file->private_data;
+
+	return simple_read_from_buffer(buf, nbytes, ppos,
+				       priv->str, priv->nbytes);
+}
+
+static int req_dbg_release(struct inode *inode, struct file *file)
+{
+	kfree(file->private_data);
+	return 0;
+}
+
+static const struct file_operations req_dbg_fops = {
+	.owner		= THIS_MODULE,
+	.open		= req_dbg_open,
+	.llseek		= no_llseek,
+	.read		= req_dbg_read,
+	.release	= req_dbg_release,
+};
+
+static int regs_dbg_open(struct inode *inode, struct file *file)
+{
+	struct atmel_mci *host;
+	unsigned int i;
+	u32 *data;
+	int ret = -ENOMEM;
+
+	mutex_lock(&inode->i_mutex);
+	host = inode->i_private;
+	data = kmalloc(inode->i_size, GFP_KERNEL);
+	if (!data)
+		goto out;
+
+	spin_lock_irq(&host->mmc->lock);
+	for (i = 0; i < inode->i_size / 4; i++)
+		data[i] = __raw_readl(host->regs + i * 4);
+	spin_unlock_irq(&host->mmc->lock);
+
+	file->private_data = data;
+	ret = 0;
+
+out:
+	mutex_unlock(&inode->i_mutex);
+
+	return ret;
+}
+
+static ssize_t regs_dbg_read(struct file *file, char __user *buf,
+			     size_t nbytes, loff_t *ppos)
+{
+	struct inode *inode = file->f_dentry->d_inode;
+	int ret;
+
+	mutex_lock(&inode->i_mutex);
+	ret = simple_read_from_buffer(buf, nbytes, ppos,
+				      file->private_data,
+				      file->f_dentry->d_inode->i_size);
+	mutex_unlock(&inode->i_mutex);
+
+	return ret;
+}
+
+static int regs_dbg_release(struct inode *inode, struct file *file)
+{
+	kfree(file->private_data);
+	return 0;
+}
+
+static const struct file_operations regs_dbg_fops = {
+	.owner		= THIS_MODULE,
+	.open		= regs_dbg_open,
+	.llseek		= generic_file_llseek,
+	.read		= regs_dbg_read,
+	.release	= regs_dbg_release,
+};
+
+static void atmci_init_debugfs(struct atmel_mci *host)
+{
+	struct mmc_host *mmc;
+	struct dentry *root, *regs;
+	struct resource *res;
+
+	mmc = host->mmc;
+	root = debugfs_create_dir(mmc_hostname(mmc), NULL);
+	if (IS_ERR(root) || !root)
+		goto err_root;
+	host->debugfs_root = root;
+
+	regs = debugfs_create_file("regs", 0400, root, host, &regs_dbg_fops);
+	if (!regs)
+		goto err_regs;
+
+	res = platform_get_resource(host->pdev, IORESOURCE_MEM, 0);
+	regs->d_inode->i_size = res->end - res->start + 1;
+	host->debugfs_regs = regs;
+
+	host->debugfs_req = debugfs_create_file("req", 0400, root,
+						host, &req_dbg_fops);
+	if (!host->debugfs_req)
+		goto err_req;
+
+	host->debugfs_pending_events
+		= debugfs_create_u32("pending_events", 0400, root,
+				     (u32 *)&host->pending_events);
+	if (!host->debugfs_pending_events)
+		goto err_pending_events;
+
+	host->debugfs_completed_events
+		= debugfs_create_u32("completed_events", 0400, root,
+				     (u32 *)&host->completed_events);
+	if (!host->debugfs_completed_events)
+		goto err_completed_events;
+
+	return;
+
+err_completed_events:
+	debugfs_remove(host->debugfs_pending_events);
+err_pending_events:
+	debugfs_remove(host->debugfs_req);
+err_req:
+	debugfs_remove(host->debugfs_regs);
+err_regs:
+	debugfs_remove(host->debugfs_root);
+err_root:
+	host->debugfs_root = NULL;
+	dev_err(&host->pdev->dev,
+		"failed to initialize debugfs for %s\n",
+		mmc_hostname(mmc));
+}
+
+static void atmci_cleanup_debugfs(struct atmel_mci *host)
+{
+	if (host->debugfs_root) {
+		debugfs_remove(host->debugfs_completed_events);
+		debugfs_remove(host->debugfs_pending_events);
+		debugfs_remove(host->debugfs_req);
+		debugfs_remove(host->debugfs_regs);
+		debugfs_remove(host->debugfs_root);
+		host->debugfs_root = NULL;
+	}
+}
+#else
+static inline void atmci_init_debugfs(struct atmel_mci *host)
+{
+
+}
+
+static inline void atmci_cleanup_debugfs(struct atmel_mci *host)
+{
+
+}
+#endif /* CONFIG_DEBUG_FS */
+
+static inline unsigned int ns_to_clocks(struct atmel_mci *host,
+					unsigned int ns)
+{
+	return (ns * (host->bus_hz / 1000000) + 999) / 1000;
+}
+
+static void atmci_set_timeout(struct atmel_mci *host,
+			      struct mmc_data *data)
+{
+	static unsigned dtomul_to_shift[] = {
+		0, 4, 7, 8, 10, 12, 16, 20
+	};
+	unsigned timeout;
+	unsigned dtocyc, dtomul;
+
+	timeout = ns_to_clocks(host, data->timeout_ns) + data->timeout_clks;
+
+	for (dtomul = 0; dtomul < 8; dtomul++) {
+		unsigned shift = dtomul_to_shift[dtomul];
+		dtocyc = (timeout + (1 << shift) - 1) >> shift;
+		if (dtocyc < 15)
+			break;
+	}
+
+	if (dtomul >= 8) {
+		dtomul = 7;
+		dtocyc = 15;
+	}
+
+	pr_debug("%s: setting timeout to %u cycles\n",
+		 mmc_hostname(host->mmc),
+		 dtocyc << dtomul_to_shift[dtomul]);
+	mci_writel(host, DTOR, (MCI_BF(DTOMUL, dtomul)
+				| MCI_BF(DTOCYC, dtocyc)));
+}
+
+/*
+ * Return mask with interrupt flags to be handled for this command.
+ */
+static u32 atmci_prepare_command(struct mmc_host *mmc,
+				 struct mmc_command *cmd,
+				 u32 *cmd_flags)
+{
+	u32 cmdr;
+	u32 iflags;
+
+	cmd->error = MMC_ERR_NONE;
+
+	cmdr = 0;
+	BUG_ON(MCI_BFEXT(CMDNB, cmdr) != 0);
+	cmdr = MCI_BFINS(CMDNB, cmd->opcode, cmdr);
+
+	if (cmd->flags & MMC_RSP_PRESENT) {
+		if (cmd->flags & MMC_RSP_136)
+			cmdr |= MCI_BF(RSPTYP, MCI_RSPTYP_136_BIT);
+		else
+			cmdr |= MCI_BF(RSPTYP, MCI_RSPTYP_48_BIT);
+	}
+
+	/*
+	 * This should really be MAXLAT_5 for CMD2 and ACMD41, but
+	 * it's too difficult to determine whether this is an ACMD or
+	 * not. Better make it 64.
+	 */
+	cmdr |= MCI_BIT(MAXLAT);
+
+	if (mmc->ios.bus_mode == MMC_BUSMODE_OPENDRAIN)
+		cmdr |= MCI_BIT(OPDCMD);
+
+	iflags = MCI_BIT(CMDRDY) | MCI_CMD_ERROR_FLAGS;
+	if (!(cmd->flags & MMC_RSP_CRC))
+		iflags &= ~MCI_BIT(RCRCE);
+
+	pr_debug("%s: cmd: op %02x arg %08x flags %08x, cmdflags %08lx\n",
+		 mmc_hostname(mmc), cmd->opcode, cmd->arg, cmd->flags,
+		 (unsigned long)cmdr);
+
+	*cmd_flags = cmdr;
+	return iflags;
+}
+
+static void atmci_start_command(struct atmel_mci *host,
+				struct mmc_command *cmd,
+				u32 cmd_flags)
+{
+	WARN_ON(host->cmd);
+	host->cmd = cmd;
+
+	mci_writel(host, ARGR, cmd->arg);
+	mci_writel(host, CMDR, cmd_flags);
+
+	if (cmd->data)
+		dma_start_request(host->dma.req.req.dmac,
+				  host->dma.req.req.channel);
+}
+
+/*
+ * Returns a mask of flags to be set in the command register when the
+ * command to start the transfer is to be sent.
+ */
+static u32 atmci_prepare_data(struct mmc_host *mmc, struct mmc_data *data)
+{
+	struct atmel_mci *host = mmc_priv(mmc);
+	u32 cmd_flags;
+
+	WARN_ON(host->data);
+	host->data = data;
+
+	atmci_set_timeout(host, data);
+	mci_writel(host, BLKR, (MCI_BF(BCNT, data->blocks)
+				| MCI_BF(BLKLEN, data->blksz)));
+	host->dma.req.block_size = data->blksz;
+	host->dma.req.nr_blocks = data->blocks;
+
+	cmd_flags = MCI_BF(TRCMD, MCI_TRCMD_START_TRANS);
+	if (data->flags & MMC_DATA_STREAM)
+		cmd_flags |= MCI_BF(TRTYP, MCI_TRTYP_STREAM);
+	else if (data->blocks > 1)
+		cmd_flags |= MCI_BF(TRTYP, MCI_TRTYP_MULTI_BLOCK);
+	else
+		cmd_flags |= MCI_BF(TRTYP, MCI_TRTYP_BLOCK);
+
+	if (data->flags & MMC_DATA_READ) {
+		cmd_flags |= MCI_BIT(TRDIR);
+		host->dma.req.nr_sg
+			= dma_map_sg(&host->pdev->dev, data->sg,
+				     data->sg_len, DMA_FROM_DEVICE);
+		host->dma.req.periph_id = host->dma.rx_periph_id;
+		host->dma.req.direction = DMA_DIR_PERIPH_TO_MEM;
+		host->dma.req.data_reg = host->mapbase + MCI_RDR;
+	} else {
+		host->dma.req.nr_sg
+			= dma_map_sg(&host->pdev->dev, data->sg,
+				     data->sg_len, DMA_TO_DEVICE);
+		host->dma.req.periph_id = host->dma.tx_periph_id;
+		host->dma.req.direction = DMA_DIR_MEM_TO_PERIPH;
+		host->dma.req.data_reg = host->mapbase + MCI_TDR;
+	}
+	host->dma.req.sg = data->sg;
+
+	dma_prepare_request_sg(host->dma.req.req.dmac, &host->dma.req);
+
+	return cmd_flags;
+}
+
+static void atmci_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+	struct atmel_mci *host = mmc_priv(mmc);
+	struct mmc_data *data = mrq->data;
+	u32 iflags;
+	u32 cmdflags = 0;
+
+	iflags = mci_readl(host, IMR);
+	if (iflags)
+		printk("WARNING: IMR=0x%08x\n", mci_readl(host, IMR));
+
+	WARN_ON(host->mrq != NULL);
+	host->mrq = mrq;
+	host->pending_events = 0;
+	host->completed_events = 0;
+
+	iflags = atmci_prepare_command(mmc, mrq->cmd, &cmdflags);
+
+	if (mrq->stop) {
+		BUG_ON(!data);
+
+		host->stop_iflags = atmci_prepare_command(mmc, mrq->stop,
+							  &host->stop_cmdr);
+		host->stop_cmdr |= MCI_BF(TRCMD, MCI_TRCMD_STOP_TRANS);
+		if (!(data->flags & MMC_DATA_WRITE))
+			host->stop_cmdr |= MCI_BIT(TRDIR);
+		if (data->flags & MMC_DATA_STREAM)
+			host->stop_cmdr |= MCI_BF(TRTYP, MCI_TRTYP_STREAM);
+		else
+			host->stop_cmdr |= MCI_BF(TRTYP, MCI_TRTYP_MULTI_BLOCK);
+	}
+	if (data) {
+		cmdflags |= atmci_prepare_data(mmc, data);
+		iflags |= MCI_DATA_ERROR_FLAGS;
+	}
+
+	atmci_start_command(host, mrq->cmd, cmdflags);
+	mci_writel(host, IER, iflags);
+}
+
+static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+	struct atmel_mci *host = mmc_priv(mmc);
+
+	if (ios->clock) {
+		u32 clkdiv;
+
+		clkdiv = host->bus_hz / (2 * ios->clock) - 1;
+		if (clkdiv > 255)
+			clkdiv = 255;
+		mci_writel(host, MR, (clkdiv
+				      | MCI_BIT(WRPROOF)
+				      | MCI_BIT(RDPROOF)));
+	}
+
+	switch (ios->bus_width) {
+	case MMC_BUS_WIDTH_1:
+		mci_writel(host, SDCR, 0);
+		break;
+	case MMC_BUS_WIDTH_4:
+		mci_writel(host, SDCR, MCI_BIT(SDCBUS));
+		break;
+	}
+
+	switch (ios->power_mode) {
+	case MMC_POWER_OFF:
+		mci_writel(host, CR, MCI_BIT(MCIDIS));
+		break;
+	case MMC_POWER_UP:
+		mci_writel(host, CR, MCI_BIT(SWRST));
+		break;
+	case MMC_POWER_ON:
+		mci_writel(host, CR, MCI_BIT(MCIEN));
+		break;
+	}
+}
+
+static int atmci_get_ro(struct mmc_host *mmc)
+{
+	int read_only = 0;
+	struct atmel_mci *host = mmc_priv(mmc);
+
+	if (host->wp_pin >= 0) {
+		read_only = gpio_get_value(host->wp_pin);
+		pr_debug("%s: card is %s\n", mmc_hostname(mmc),
+			 read_only ? "read-only" : "read-write");
+	} else {
+		pr_debug("%s: no pin for checking read-only switch."
+			 " Assuming write-enable.\n", mmc_hostname(mmc));
+	}
+
+	return read_only;
+}
+
+static struct mmc_host_ops atmci_ops = {
+	.request	= atmci_request,
+	.set_ios	= atmci_set_ios,
+	.get_ro		= atmci_get_ro,
+};
+
+static void atmci_request_end(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+	struct atmel_mci *host = mmc_priv(mmc);
+
+	WARN_ON(host->cmd || host->data);
+	host->mrq = NULL;
+
+	mmc_request_done(mmc, mrq);
+}
+
+static void send_stop_cmd(struct mmc_host *mmc, struct mmc_data *data,
+			  u32 flags)
+{
+	struct atmel_mci *host = mmc_priv(mmc);
+
+	atmci_start_command(host, data->stop, host->stop_cmdr | flags);
+	mci_writel(host, IER, host->stop_iflags);
+}
+
+static void atmci_data_complete(struct atmel_mci *host, struct mmc_data *data)
+{
+	host->data = NULL;
+	dma_unmap_sg(&host->pdev->dev, data->sg, host->dma.req.nr_sg,
+		     ((data->flags & MMC_DATA_WRITE)
+		      ? DMA_TO_DEVICE : DMA_FROM_DEVICE));
+
+	/*
+	 * Data might complete before command for very short transfers
+	 * (like READ_SCR)
+	 */
+	if (mci_cmd_is_complete(host)
+	    && (!data->stop || mci_stop_is_complete(host)))
+		atmci_request_end(host->mmc, data->mrq);
+}
+
+static void atmci_command_error(struct mmc_host *mmc,
+				struct mmc_command *cmd,
+				u32 status)
+{
+	pr_debug("%s: command error: status=0x%08x\n",
+		 mmc_hostname(mmc), status);
+
+	if (status & MCI_BIT(RTOE))
+		cmd->error = MMC_ERR_TIMEOUT;
+	else if (status & MCI_BIT(RCRCE))
+		cmd->error = MMC_ERR_BADCRC;
+	else
+		cmd->error = MMC_ERR_FAILED;
+}
+
+static void atmci_tasklet_func(unsigned long priv)
+{
+	struct mmc_host *mmc = (struct mmc_host *)priv;
+	struct atmel_mci *host = mmc_priv(mmc);
+	struct mmc_request *mrq = host->mrq;
+	struct mmc_data *data = host->data;
+
+	pr_debug("atmci_tasklet: pending/completed/mask %lx/%lx/%x\n",
+		 host->pending_events, host->completed_events,
+		 mci_readl(host, IMR));
+
+	if (mci_clear_cmd_error_is_pending(host)) {
+		struct mmc_command *cmd;
+
+		mci_set_cmd_error_complete(host);
+		mci_clear_cmd_pending(host);
+		cmd = host->mrq->cmd;
+
+		if (cmd->data) {
+			dma_stop_request(host->dma.req.req.dmac,
+					 host->dma.req.req.channel);
+			host->data = NULL;
+		}
+
+		atmci_command_error(mmc, cmd, host->error_status);
+		atmci_request_end(mmc, cmd->mrq);
+	}
+	if (mci_clear_stop_error_is_pending(host)) {
+		mci_set_stop_error_complete(host);
+		mci_clear_stop_pending(host);
+		atmci_command_error(mmc, host->mrq->stop,
+				    host->error_status);
+		if (!host->data)
+			atmci_request_end(mmc, host->mrq);
+	}
+	if (mci_clear_cmd_is_pending(host)) {
+		mci_set_cmd_complete(host);
+		if (!mrq->data || mci_data_is_complete(host)
+		    || mci_data_error_is_complete(host))
+			atmci_request_end(mmc, mrq);
+	}
+	if (mci_clear_stop_is_pending(host)) {
+		mci_set_stop_complete(host);
+		if (mci_data_is_complete(host)
+		    || mci_data_error_is_complete(host))
+			atmci_request_end(mmc, mrq);
+	}
+	if (mci_clear_dma_error_is_pending(host)) {
+		mci_set_dma_error_complete(host);
+		mci_clear_data_pending(host);
+
+		/* DMA controller got bus error => invalid address */
+		data->error = MMC_ERR_INVALID;
+
+		printk(KERN_DEBUG "%s: dma error after %u bytes xfered\n",
+		       mmc_hostname(mmc), host->data->bytes_xfered);
+
+		if (data->stop
+		    && !mci_set_stop_sent_is_completed(host))
+			/* TODO: Check if card is still present */
+			send_stop_cmd(host->mmc, data, 0);
+
+		atmci_data_complete(host, data);
+	}
+	if (mci_clear_data_error_is_pending(host)) {
+		u32 status = host->error_status;
+
+		mci_set_data_error_complete(host);
+		mci_clear_data_pending(host);
+
+		dma_stop_request(host->dma.req.req.dmac,
+				 host->dma.req.req.channel);
+
+		printk(KERN_DEBUG "%s: data error: status=0x%08x\n",
+		       mmc_hostname(host->mmc), status);
+
+		if (status & MCI_BIT(DCRCE)) {
+			printk(KERN_DEBUG "%s: Data CRC error\n",
+			       mmc_hostname(host->mmc));
+			data->error = MMC_ERR_BADCRC;
+		} else if (status & MCI_BIT(DTOE)) {
+			printk(KERN_DEBUG "%s: Data Timeout error\n",
+			       mmc_hostname(host->mmc));
+			data->error = MMC_ERR_TIMEOUT;
+		} else {
+			printk(KERN_DEBUG "%s: Data FIFO error\n",
+			       mmc_hostname(host->mmc));
+			data->error = MMC_ERR_FIFO;
+		}
+		printk(KERN_DEBUG "%s: Bytes xfered: %u\n",
+		       mmc_hostname(host->mmc), data->bytes_xfered);
+
+		if (data->stop
+		    && !mci_set_stop_sent_is_completed(host))
+			/* TODO: Check if card is still present */
+			send_stop_cmd(host->mmc, data, 0);
+
+		atmci_data_complete(host, data);
+	}
+	if (mci_clear_data_is_pending(host)) {
+		mci_set_data_complete(host);
+		data->bytes_xfered = data->blocks * data->blksz;
+		atmci_data_complete(host, data);
+	}
+	if (mci_clear_card_detect_is_pending(host)) {
+		/* Reset controller if card is gone */
+		if (!host->present) {
+			mci_writel(host, CR, MCI_BIT(SWRST));
+			mci_writel(host, IDR, ~0UL);
+			mci_writel(host, CR, MCI_BIT(MCIEN));
+		}
+
+		/* Clean up queue if present */
+		if (mrq) {
+			if (!mci_cmd_is_complete(host)
+			    && !mci_cmd_error_is_complete(host)) {
+				mrq->cmd->error = MMC_ERR_TIMEOUT;
+			}
+			if (mrq->data && !mci_data_is_complete(host)
+			    && !mci_data_error_is_complete(host)) {
+				dma_stop_request(host->dma.req.req.dmac,
+						host->dma.req.req.channel);
+				host->data->error = MMC_ERR_TIMEOUT;
+				atmci_data_complete(host, data);
+			}
+			if (mrq->stop && !mci_stop_is_complete(host)
+			    && !mci_stop_error_is_complete(host)) {
+				mrq->stop->error = MMC_ERR_TIMEOUT;
+			}
+
+			host->cmd = NULL;
+			atmci_request_end(mmc, mrq);
+		}
+		mmc_detect_change(host->mmc, msecs_to_jiffies(100));
+	}
+}
+
+static void atmci_cmd_interrupt(struct mmc_host *mmc, u32 status)
+{
+	struct atmel_mci *host = mmc_priv(mmc);
+	struct mmc_command *cmd = host->cmd;
+
+	/*
+	 * Read the response now so that we're free to send a new
+	 * command immediately.
+	 */
+	cmd->resp[0] = mci_readl(host, RSPR);
+	cmd->resp[1] = mci_readl(host, RSPR);
+	cmd->resp[2] = mci_readl(host, RSPR);
+	cmd->resp[3] = mci_readl(host, RSPR);
+
+	mci_writel(host, IDR, MCI_BIT(CMDRDY) | MCI_CMD_ERROR_FLAGS);
+	host->cmd = NULL;
+
+	if (mci_stop_sent_is_complete(host))
+		mci_set_stop_pending(host);
+	else
+		mci_set_cmd_pending(host);
+
+	tasklet_schedule(&host->tasklet);
+}
+
+static void atmci_xfer_complete(struct dma_request *_req)
+{
+	struct dma_request_sg *req = to_dma_request_sg(_req);
+	struct atmel_mci_dma *dma;
+	struct atmel_mci *host;
+	struct mmc_data *data;
+
+	dma = container_of(req, struct atmel_mci_dma, req);
+	host = container_of(dma, struct atmel_mci, dma);
+	data = host->data;
+
+	if (data->stop && !mci_set_stop_sent_is_completed(host))
+		send_stop_cmd(host->mmc, data, 0);
+
+	if (data->flags & MMC_DATA_READ) {
+		mci_writel(host, IDR, MCI_DATA_ERROR_FLAGS);
+		mci_set_data_pending(host);
+		tasklet_schedule(&host->tasklet);
+	} else {
+		/*
+		 * For the WRITE case, wait for NOTBUSY. This function
+		 * is called when everything has been written to the
+		 * controller, not when the card is done programming.
+		 */
+		mci_writel(host, IER, MCI_BIT(NOTBUSY));
+	}
+}
+
+static void atmci_dma_error(struct dma_request *_req)
+{
+	struct dma_request_sg *req = to_dma_request_sg(_req);
+	struct atmel_mci_dma *dma;
+	struct atmel_mci *host;
+
+	dma = container_of(req, struct atmel_mci_dma, req);
+	host = container_of(dma, struct atmel_mci, dma);
+
+	mci_writel(host, IDR, (MCI_BIT(NOTBUSY)
+			       | MCI_DATA_ERROR_FLAGS));
+
+	mci_set_dma_error_pending(host);
+	tasklet_schedule(&host->tasklet);
+}
+
+static irqreturn_t atmci_interrupt(int irq, void *dev_id)
+{
+	struct mmc_host *mmc = dev_id;
+	struct atmel_mci *host = mmc_priv(mmc);
+	u32 status, mask, pending;
+
+	spin_lock(&mmc->lock);
+
+	status = mci_readl(host, SR);
+	mask = mci_readl(host, IMR);
+	pending = status & mask;
+
+	do {
+		if (pending & MCI_CMD_ERROR_FLAGS) {
+			mci_writel(host, IDR, (MCI_BIT(CMDRDY)
+					       | MCI_BIT(NOTBUSY)
+					       | MCI_CMD_ERROR_FLAGS
+					       | MCI_DATA_ERROR_FLAGS));
+			host->error_status = status;
+			host->cmd = NULL;
+			if (mci_stop_sent_is_complete(host))
+				mci_set_stop_error_pending(host);
+			else
+				mci_set_cmd_error_pending(host);
+			tasklet_schedule(&host->tasklet);
+			break;
+		}
+		if (pending & MCI_DATA_ERROR_FLAGS) {
+			mci_writel(host, IDR, (MCI_BIT(NOTBUSY)
+					       | MCI_DATA_ERROR_FLAGS));
+			host->error_status = status;
+			mci_set_data_error_pending(host);
+			tasklet_schedule(&host->tasklet);
+			break;
+		}
+		if (pending & MCI_BIT(CMDRDY))
+			atmci_cmd_interrupt(mmc, status);
+		if (pending & MCI_BIT(NOTBUSY)) {
+			mci_writel(host, IDR, (MCI_BIT(NOTBUSY)
+					       | MCI_DATA_ERROR_FLAGS));
+			mci_set_data_pending(host);
+			tasklet_schedule(&host->tasklet);
+		}
+
+		status = mci_readl(host, SR);
+		mask = mci_readl(host, IMR);
+		pending = status & mask;
+	} while (pending);
+
+	spin_unlock(&mmc->lock);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t atmci_detect_change(int irq, void *dev_id)
+{
+	struct mmc_host *mmc = dev_id;
+	struct atmel_mci *host = mmc_priv(mmc);
+
+	int present = !gpio_get_value(irq_to_gpio(irq));
+
+	if (present != host->present) {
+		pr_debug("%s: card %s\n", mmc_hostname(host->mmc),
+			 present ? "inserted" : "removed");
+		host->present = present;
+		mci_set_card_detect_pending(host);
+		tasklet_schedule(&host->tasklet);
+	}
+	return IRQ_HANDLED;
+}
+
+static int __devinit atmci_probe(struct platform_device *pdev)
+{
+	struct mci_platform_data *board;
+	struct atmel_mci *host;
+	struct mmc_host *mmc;
+	struct resource *regs;
+	int irq;
+	int ret;
+
+	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!regs)
+		return -ENXIO;
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
+	board = pdev->dev.platform_data;
+
+	mmc = mmc_alloc_host(sizeof(struct atmel_mci), &pdev->dev);
+	if (!mmc)
+		return -ENOMEM;
+
+	host = mmc_priv(mmc);
+	host->pdev = pdev;
+	host->mmc = mmc;
+	if (board) {
+		host->detect_pin = board->detect_pin;
+		host->wp_pin = board->wp_pin;
+	} else {
+		host->detect_pin = -1;
+		host->detect_pin = -1;
+	}
+
+	host->mck = clk_get(&pdev->dev, "mci_clk");
+	if (IS_ERR(host->mck)) {
+		ret = PTR_ERR(host->mck);
+		goto out_free_host;
+	}
+	clk_enable(host->mck);
+
+	ret = -ENOMEM;
+	host->regs = ioremap(regs->start, regs->end - regs->start + 1);
+	if (!host->regs)
+		goto out_disable_clk;
+
+	host->bus_hz = clk_get_rate(host->mck);
+	host->mapbase = regs->start;
+
+	mmc->ops = &atmci_ops;
+	mmc->f_min = (host->bus_hz + 511) / 512;
+	mmc->f_max = min((unsigned int)(host->bus_hz / 2), fmax);
+	mmc->ocr_avail	= 0x00100000;
+	mmc->caps |= MMC_CAP_4_BIT_DATA;
+
+	tasklet_init(&host->tasklet, atmci_tasklet_func, (unsigned long)mmc);
+
+	ret = request_irq(irq, atmci_interrupt, 0, "mmci", mmc);
+	if (ret)
+		goto out_unmap;
+
+	/* Assume card is present if we don't have a detect pin */
+	host->present = 1;
+	if (host->detect_pin >= 0) {
+		if (gpio_request(host->detect_pin, "mmc_detect")) {
+			printk(KERN_WARNING "%s: no detect pin available\n",
+			       mmc_hostname(host->mmc));
+			host->detect_pin = -1;
+		} else {
+			host->present = !gpio_get_value(host->detect_pin);
+		}
+	}
+	if (host->wp_pin >= 0) {
+		if (gpio_request(host->wp_pin, "mmc_wp")) {
+			printk(KERN_WARNING "%s: no WP pin available\n",
+			       mmc_hostname(host->mmc));
+			host->wp_pin = -1;
+		}
+	}
+
+	/* TODO: Get this information from platform data */
+	ret = -ENOMEM;
+	host->dma.req.req.dmac = find_dma_controller(0);
+	if (!host->dma.req.req.dmac) {
+		printk(KERN_ERR
+		       "mmci: No DMA controller available, aborting\n");
+		goto out_free_irq;
+	}
+	ret = dma_alloc_channel(host->dma.req.req.dmac);
+	if (ret < 0) {
+		printk(KERN_ERR
+		       "mmci: Unable to allocate DMA channel, aborting\n");
+		goto out_free_irq;
+	}
+	host->dma.req.req.channel = ret;
+	host->dma.req.width = DMA_WIDTH_32BIT;
+	host->dma.req.req.xfer_complete = atmci_xfer_complete;
+	host->dma.req.req.block_complete = NULL; // atmci_block_complete;
+	host->dma.req.req.error = atmci_dma_error;
+	host->dma.rx_periph_id = 0;
+	host->dma.tx_periph_id = 1;
+
+	mci_writel(host, CR, MCI_BIT(SWRST));
+	mci_writel(host, IDR, ~0UL);
+	mci_writel(host, CR, MCI_BIT(MCIEN));
+
+	platform_set_drvdata(pdev, host);
+
+	mmc_add_host(mmc);
+
+	if (host->detect_pin >= 0) {
+		ret = request_irq(gpio_to_irq(host->detect_pin),
+				  atmci_detect_change,
+				  IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+				  DRIVER_NAME, mmc);
+		if (ret) {
+			printk(KERN_ERR
+			       "%s: could not request IRQ %d for detect pin\n",
+			       mmc_hostname(mmc),
+			       gpio_to_irq(host->detect_pin));
+			gpio_free(host->detect_pin);
+			host->detect_pin = -1;
+		}
+	}
+
+	printk(KERN_INFO "%s: Atmel MCI controller at 0x%08lx irq %d\n",
+	       mmc_hostname(mmc), host->mapbase, irq);
+
+	atmci_init_debugfs(host);
+
+	return 0;
+
+out_free_irq:
+	if (host->detect_pin >= 0)
+		gpio_free(host->detect_pin);
+	if (host->wp_pin >= 0)
+		gpio_free(host->wp_pin);
+	free_irq(irq, mmc);
+out_unmap:
+	iounmap(host->regs);
+out_disable_clk:
+	clk_disable(host->mck);
+	clk_put(host->mck);
+out_free_host:
+	mmc_free_host(mmc);
+	return ret;
+}
+
+static int __devexit atmci_remove(struct platform_device *pdev)
+{
+	struct atmel_mci *host = platform_get_drvdata(pdev);
+
+	platform_set_drvdata(pdev, NULL);
+
+	if (host) {
+		atmci_cleanup_debugfs(host);
+
+		if (host->detect_pin >= 0) {
+			free_irq(gpio_to_irq(host->detect_pin), host->mmc);
+			cancel_delayed_work(&host->mmc->detect);
+			gpio_free(host->detect_pin);
+		}
+
+		mmc_remove_host(host->mmc);
+
+		mci_writel(host, IDR, ~0UL);
+		mci_writel(host, CR, MCI_BIT(MCIDIS));
+		mci_readl(host, SR);
+
+		dma_release_channel(host->dma.req.req.dmac,
+				    host->dma.req.req.channel);
+
+		if (host->wp_pin >= 0)
+			gpio_free(host->wp_pin);
+
+		free_irq(platform_get_irq(pdev, 0), host->mmc);
+		iounmap(host->regs);
+
+		clk_disable(host->mck);
+		clk_put(host->mck);
+
+		mmc_free_host(host->mmc);
+	}
+	return 0;
+}
+
+static struct platform_driver atmci_driver = {
+	.probe		= atmci_probe,
+	.remove		= __devexit_p(atmci_remove),
+	.driver		= {
+		.name		= DRIVER_NAME,
+	},
+};
+
+static int __init atmci_init(void)
+{
+	return platform_driver_register(&atmci_driver);
+}
+
+static void __exit atmci_exit(void)
+{
+	platform_driver_unregister(&atmci_driver);
+}
+
+module_init(atmci_init);
+module_exit(atmci_exit);
+
+MODULE_DESCRIPTION("Atmel Multimedia Card Interface driver");
+MODULE_LICENSE("GPL");
diff -Nur -x .gitignore -x .git linux-2.6.21.3/drivers/mmc/atmel-mci.h avr32-git/drivers/mmc/atmel-mci.h
--- linux-2.6.21.3/drivers/mmc/atmel-mci.h	1970-01-01 01:00:00.000000000 +0100
+++ avr32-git/drivers/mmc/atmel-mci.h	2007-06-06 11:33:56.000000000 +0200
@@ -0,0 +1,192 @@
+/*
+ * Atmel MultiMedia Card Interface driver
+ *
+ * Copyright (C) 2004-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.
+ */
+#ifndef __DRIVERS_MMC_ATMEL_MCI_H__
+#define __DRIVERS_MMC_ATMEL_MCI_H__
+
+/* MCI register offsets */
+#define MCI_CR					0x0000
+#define MCI_MR					0x0004
+#define MCI_DTOR				0x0008
+#define MCI_SDCR				0x000c
+#define MCI_ARGR				0x0010
+#define MCI_CMDR				0x0014
+#define MCI_BLKR				0x0018
+#define MCI_RSPR				0x0020
+#define MCI_RSPR1				0x0024
+#define MCI_RSPR2				0x0028
+#define MCI_RSPR3				0x002c
+#define MCI_RDR					0x0030
+#define MCI_TDR					0x0034
+#define MCI_SR					0x0040
+#define MCI_IER					0x0044
+#define MCI_IDR					0x0048
+#define MCI_IMR					0x004c
+
+/* Bitfields in CR */
+#define MCI_MCIEN_OFFSET			0
+#define MCI_MCIEN_SIZE				1
+#define MCI_MCIDIS_OFFSET			1
+#define MCI_MCIDIS_SIZE				1
+#define MCI_PWSEN_OFFSET			2
+#define MCI_PWSEN_SIZE				1
+#define MCI_PWSDIS_OFFSET			3
+#define MCI_PWSDIS_SIZE				1
+#define MCI_SWRST_OFFSET			7
+#define MCI_SWRST_SIZE				1
+
+/* Bitfields in MR */
+#define MCI_CLKDIV_OFFSET			0
+#define MCI_CLKDIV_SIZE				8
+#define MCI_PWSDIV_OFFSET			8
+#define MCI_PWSDIV_SIZE				3
+#define MCI_RDPROOF_OFFSET			11
+#define MCI_RDPROOF_SIZE			1
+#define MCI_WRPROOF_OFFSET			12
+#define MCI_WRPROOF_SIZE			1
+#define MCI_DMAPADV_OFFSET			14
+#define MCI_DMAPADV_SIZE			1
+#define MCI_BLKLEN_OFFSET			16
+#define MCI_BLKLEN_SIZE				16
+
+/* Bitfields in DTOR */
+#define MCI_DTOCYC_OFFSET			0
+#define MCI_DTOCYC_SIZE				4
+#define MCI_DTOMUL_OFFSET			4
+#define MCI_DTOMUL_SIZE				3
+
+/* Bitfields in SDCR */
+#define MCI_SDCSEL_OFFSET			0
+#define MCI_SDCSEL_SIZE				4
+#define MCI_SDCBUS_OFFSET			7
+#define MCI_SDCBUS_SIZE				1
+
+/* Bitfields in ARGR */
+#define MCI_ARG_OFFSET				0
+#define MCI_ARG_SIZE				32
+
+/* Bitfields in CMDR */
+#define MCI_CMDNB_OFFSET			0
+#define MCI_CMDNB_SIZE				6
+#define MCI_RSPTYP_OFFSET			6
+#define MCI_RSPTYP_SIZE				2
+#define MCI_SPCMD_OFFSET			8
+#define MCI_SPCMD_SIZE				3
+#define MCI_OPDCMD_OFFSET			11
+#define MCI_OPDCMD_SIZE				1
+#define MCI_MAXLAT_OFFSET			12
+#define MCI_MAXLAT_SIZE				1
+#define MCI_TRCMD_OFFSET			16
+#define MCI_TRCMD_SIZE				2
+#define MCI_TRDIR_OFFSET			18
+#define MCI_TRDIR_SIZE				1
+#define MCI_TRTYP_OFFSET			19
+#define MCI_TRTYP_SIZE				2
+
+/* Bitfields in BLKR */
+#define MCI_BCNT_OFFSET				0
+#define MCI_BCNT_SIZE				16
+
+/* Bitfields in RSPRn */
+#define MCI_RSP_OFFSET				0
+#define MCI_RSP_SIZE				32
+
+/* Bitfields in SR/IER/IDR/IMR */
+#define MCI_CMDRDY_OFFSET			0
+#define MCI_CMDRDY_SIZE				1
+#define MCI_RXRDY_OFFSET			1
+#define MCI_RXRDY_SIZE				1
+#define MCI_TXRDY_OFFSET			2
+#define MCI_TXRDY_SIZE				1
+#define MCI_BLKE_OFFSET				3
+#define MCI_BLKE_SIZE				1
+#define MCI_DTIP_OFFSET				4
+#define MCI_DTIP_SIZE				1
+#define MCI_NOTBUSY_OFFSET			5
+#define MCI_NOTBUSY_SIZE			1
+#define MCI_ENDRX_OFFSET			6
+#define MCI_ENDRX_SIZE				1
+#define MCI_ENDTX_OFFSET			7
+#define MCI_ENDTX_SIZE				1
+#define MCI_RXBUFF_OFFSET			14
+#define MCI_RXBUFF_SIZE				1
+#define MCI_TXBUFE_OFFSET			15
+#define MCI_TXBUFE_SIZE				1
+#define MCI_RINDE_OFFSET			16
+#define MCI_RINDE_SIZE				1
+#define MCI_RDIRE_OFFSET			17
+#define MCI_RDIRE_SIZE				1
+#define MCI_RCRCE_OFFSET			18
+#define MCI_RCRCE_SIZE				1
+#define MCI_RENDE_OFFSET			19
+#define MCI_RENDE_SIZE				1
+#define MCI_RTOE_OFFSET				20
+#define MCI_RTOE_SIZE				1
+#define MCI_DCRCE_OFFSET			21
+#define MCI_DCRCE_SIZE				1
+#define MCI_DTOE_OFFSET				22
+#define MCI_DTOE_SIZE				1
+#define MCI_OVRE_OFFSET				30
+#define MCI_OVRE_SIZE				1
+#define MCI_UNRE_OFFSET				31
+#define MCI_UNRE_SIZE				1
+
+/* Constants for DTOMUL */
+#define MCI_DTOMUL_1_CYCLE			0
+#define MCI_DTOMUL_16_CYCLES			1
+#define MCI_DTOMUL_128_CYCLES			2
+#define MCI_DTOMUL_256_CYCLES			3
+#define MCI_DTOMUL_1024_CYCLES			4
+#define MCI_DTOMUL_4096_CYCLES			5
+#define MCI_DTOMUL_65536_CYCLES			6
+#define MCI_DTOMUL_1048576_CYCLES		7
+
+/* Constants for RSPTYP */
+#define MCI_RSPTYP_NO_RESP			0
+#define MCI_RSPTYP_48_BIT			1
+#define MCI_RSPTYP_136_BIT			2
+
+/* Constants for SPCMD */
+#define MCI_SPCMD_NO_SPEC_CMD			0
+#define MCI_SPCMD_INIT_CMD			1
+#define MCI_SPCMD_SYNC_CMD			2
+#define MCI_SPCMD_INT_CMD			4
+#define MCI_SPCMD_INT_RESP			5
+
+/* Constants for TRCMD */
+#define MCI_TRCMD_NO_TRANS			0
+#define MCI_TRCMD_START_TRANS			1
+#define MCI_TRCMD_STOP_TRANS			2
+
+/* Constants for TRTYP */
+#define MCI_TRTYP_BLOCK				0
+#define MCI_TRTYP_MULTI_BLOCK			1
+#define MCI_TRTYP_STREAM			2
+
+/* Bit manipulation macros */
+#define MCI_BIT(name)					\
+	(1 << MCI_##name##_OFFSET)
+#define MCI_BF(name,value)				\
+	(((value) & ((1 << MCI_##name##_SIZE) - 1))	\
+	 << MCI_##name##_OFFSET)
+#define MCI_BFEXT(name,value)				\
+	(((value) >> MCI_##name##_OFFSET)		\
+	 & ((1 << MCI_##name##_SIZE) - 1))
+#define MCI_BFINS(name,value,old)			\
+	(((old) & ~(((1 << MCI_##name##_SIZE) - 1)	\
+		    << MCI_##name##_OFFSET))		\
+	 | MCI_BF(name,value))
+
+/* Register access macros */
+#define mci_readl(port,reg)				\
+	__raw_readl((port)->regs + MCI_##reg)
+#define mci_writel(port,reg,value)			\
+	__raw_writel((value), (port)->regs + MCI_##reg)
+
+#endif /* __DRIVERS_MMC_ATMEL_MCI_H__ */
diff -Nur -x .gitignore -x .git linux-2.6.21.3/drivers/mmc/Kconfig avr32-git/drivers/mmc/Kconfig
--- linux-2.6.21.3/drivers/mmc/Kconfig	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/drivers/mmc/Kconfig	2007-06-06 11:33:56.000000000 +0200
@@ -71,6 +71,16 @@
 
 	  If unsure, say N.
 
+config MMC_ATMELMCI
+	tristate "Atmel Multimedia Card Interface support"
+	depends on AVR32 && MMC
+	help
+	  This selects the Atmel Multimedia Card Interface. If you have
+	  a AT91 (ARM) or AT32 (AVR32) platform with a Multimedia Card
+	  slot, say Y or M here.
+
+	  If unsure, say N.
+
 config MMC_WBSD
 	tristate "Winbond W83L51xD SD/MMC Card Interface support"
 	depends on MMC && ISA_DMA_API
diff -Nur -x .gitignore -x .git linux-2.6.21.3/drivers/mmc/Makefile avr32-git/drivers/mmc/Makefile
--- linux-2.6.21.3/drivers/mmc/Makefile	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/drivers/mmc/Makefile	2007-06-06 11:33:56.000000000 +0200
@@ -23,6 +23,7 @@
 obj-$(CONFIG_MMC_AU1X)		+= au1xmmc.o
 obj-$(CONFIG_MMC_OMAP)		+= omap.o
 obj-$(CONFIG_MMC_AT91)		+= at91_mci.o
+obj-$(CONFIG_MMC_ATMELMCI)	+= atmel-mci.o
 obj-$(CONFIG_MMC_TIFM_SD)	+= tifm_sd.o
 
 mmc_core-y := mmc.o mmc_sysfs.o
diff -Nur -x .gitignore -x .git linux-2.6.21.3/drivers/mtd/chips/cfi_cmdset_0001.c avr32-git/drivers/mtd/chips/cfi_cmdset_0001.c
--- linux-2.6.21.3/drivers/mtd/chips/cfi_cmdset_0001.c	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/drivers/mtd/chips/cfi_cmdset_0001.c	2007-06-06 11:33:56.000000000 +0200
@@ -47,6 +47,7 @@
 #define I82802AC	0x00ac
 #define MANUFACTURER_ST         0x0020
 #define M50LPW080       0x002F
+#define AT49BV640D	0x02de
 
 static int cfi_intelext_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
 static int cfi_intelext_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
@@ -153,6 +154,47 @@
 }
 #endif
 
+/* Atmel chips don't use the same PRI format as Intel chips */
+static void fixup_convert_atmel_pri(struct mtd_info *mtd, void *param)
+{
+	struct map_info *map = mtd->priv;
+	struct cfi_private *cfi = map->fldrv_priv;
+	struct cfi_pri_intelext *extp = cfi->cmdset_priv;
+	struct cfi_pri_atmel atmel_pri;
+	uint32_t features = 0;
+
+	/* Reverse byteswapping */
+	extp->FeatureSupport = cpu_to_le32(extp->FeatureSupport);
+	extp->BlkStatusRegMask = cpu_to_le16(extp->BlkStatusRegMask);
+	extp->ProtRegAddr = cpu_to_le16(extp->ProtRegAddr);
+
+	memcpy(&atmel_pri, extp, sizeof(atmel_pri));
+	memset((char *)extp + 5, 0, sizeof(*extp) - 5);
+
+	printk(KERN_ERR "atmel Features: %02x\n", atmel_pri.Features);
+
+	if (atmel_pri.Features & 0x01) /* chip erase supported */
+		features |= (1<<0);
+	if (atmel_pri.Features & 0x02) /* erase suspend supported */
+		features |= (1<<1);
+	if (atmel_pri.Features & 0x04) /* program suspend supported */
+		features |= (1<<2);
+	if (atmel_pri.Features & 0x08) /* simultaneous operations supported */
+		features |= (1<<9);
+	if (atmel_pri.Features & 0x20) /* page mode read supported */
+		features |= (1<<7);
+	if (atmel_pri.Features & 0x40) /* queued erase supported */
+		features |= (1<<4);
+	if (atmel_pri.Features & 0x80) /* Protection bits supported */
+		features |= (1<<6);
+
+	extp->FeatureSupport = features;
+
+	/* burst write mode not supported */
+	cfi->cfiq->BufWriteTimeoutTyp = 0;
+	cfi->cfiq->BufWriteTimeoutMax = 0;
+}
+
 #ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE
 /* Some Intel Strata Flash prior to FPO revision C has bugs in this area */
 static void fixup_intel_strataflash(struct mtd_info *mtd, void* param)
@@ -221,6 +263,7 @@
 }
 
 static struct cfi_fixup cfi_fixup_table[] = {
+	{ CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri, NULL },
 #ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE
 	{ CFI_MFR_ANY, CFI_ID_ANY, fixup_intel_strataflash, NULL },
 #endif
diff -Nur -x .gitignore -x .git linux-2.6.21.3/drivers/mtd/chips/cfi_cmdset_0002.c avr32-git/drivers/mtd/chips/cfi_cmdset_0002.c
--- linux-2.6.21.3/drivers/mtd/chips/cfi_cmdset_0002.c	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/drivers/mtd/chips/cfi_cmdset_0002.c	2007-06-06 11:33:56.000000000 +0200
@@ -185,6 +185,10 @@
 		extp->TopBottom = 2;
 	else
 		extp->TopBottom = 3;
+
+	/* burst write mode not supported */
+	cfi->cfiq->BufWriteTimeoutTyp = 0;
+	cfi->cfiq->BufWriteTimeoutMax = 0;
 }
 
 static void fixup_use_secsi(struct mtd_info *mtd, void *param)
@@ -217,6 +221,7 @@
 }
 
 static struct cfi_fixup cfi_fixup_table[] = {
+	{ CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri, NULL },
 #ifdef AMD_BOOTLOC_BUG
 	{ CFI_MFR_AMD, CFI_ID_ANY, fixup_amd_bootblock, NULL },
 #endif
@@ -229,7 +234,6 @@
 #if !FORCE_WORD_WRITE
 	{ CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL, },
 #endif
-	{ CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri, NULL },
 	{ 0, 0, NULL, NULL }
 };
 static struct cfi_fixup jedec_fixup_table[] = {
diff -Nur -x .gitignore -x .git linux-2.6.21.3/drivers/serial/atmel_serial.c avr32-git/drivers/serial/atmel_serial.c
--- linux-2.6.21.3/drivers/serial/atmel_serial.c	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/drivers/serial/atmel_serial.c	2007-06-06 11:33:59.000000000 +0200
@@ -114,6 +114,7 @@
 	struct uart_port	uart;		/* uart */
 	struct clk		*clk;		/* uart clock */
 	unsigned short		suspended;	/* is port suspended? */
+	int			break_active;	/* break being received */
 };
 
 static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART];
@@ -252,6 +253,7 @@
  */
 static void atmel_rx_chars(struct uart_port *port)
 {
+	struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port;
 	struct tty_struct *tty = port->info->tty;
 	unsigned int status, ch, flg;
 
@@ -267,13 +269,29 @@
 		 * note that the error handling code is
 		 * out of the main execution path
 		 */
-		if (unlikely(status & (ATMEL_US_PARE | ATMEL_US_FRAME | ATMEL_US_OVRE | ATMEL_US_RXBRK))) {
+		if (unlikely(status & (ATMEL_US_PARE | ATMEL_US_FRAME
+				       | ATMEL_US_OVRE | ATMEL_US_RXBRK)
+			     || atmel_port->break_active)) {
 			UART_PUT_CR(port, ATMEL_US_RSTSTA);	/* clear error */
-			if (status & ATMEL_US_RXBRK) {
+			if (status & ATMEL_US_RXBRK
+			    && !atmel_port->break_active) {
 				status &= ~(ATMEL_US_PARE | ATMEL_US_FRAME);	/* ignore side-effect */
 				port->icount.brk++;
+				atmel_port->break_active = 1;
+				UART_PUT_IER(port, ATMEL_US_RXBRK);
 				if (uart_handle_break(port))
 					goto ignore_char;
+			} else {
+				/*
+				 * This is either the end-of-break
+				 * condition or we've received at
+				 * least one character without RXBRK
+				 * being set. In both cases, the next
+				 * RXBRK will indicate start-of-break.
+				 */
+				UART_PUT_IDR(port, ATMEL_US_RXBRK);
+				status &= ~ATMEL_US_RXBRK;
+				atmel_port->break_active = 0;
 			}
 			if (status & ATMEL_US_PARE)
 				port->icount.parity++;
@@ -352,6 +370,16 @@
 		/* Interrupt receive */
 		if (pending & ATMEL_US_RXRDY)
 			atmel_rx_chars(port);
+		else if (pending & ATMEL_US_RXBRK) {
+			/*
+			 * End of break detected. If it came along
+			 * with a character, atmel_rx_chars will
+			 * handle it.
+			 */
+			UART_PUT_CR(port, ATMEL_US_RSTSTA);
+			UART_PUT_IDR(port, ATMEL_US_RXBRK);
+			atmel_port->break_active = 0;
+		}
 
 		// TODO: All reads to CSR will clear these interrupts!
 		if (pending & ATMEL_US_RIIC) port->icount.rng++;
@@ -484,11 +512,16 @@
 	unsigned long flags;
 	unsigned int mode, imr, quot, baud;
 
+	/* Get current mode register */
+	mode = UART_GET_MR(port) & ~(ATMEL_US_USCLKS | ATMEL_US_CHRL | ATMEL_US_NBSTOP | ATMEL_US_PAR);
+
 	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
 	quot = uart_get_divisor(port, baud);
 
-	/* Get current mode register */
-	mode = UART_GET_MR(port) & ~(ATMEL_US_CHRL | ATMEL_US_NBSTOP | ATMEL_US_PAR);
+	if (quot > 65535) {		/* BRGR is 16-bit, so switch to slower clock */
+		quot /= 8;
+		mode |= ATMEL_US_USCLKS_MCK_DIV8;
+	}
 
 	/* byte size */
 	switch (termios->c_cflag & CSIZE) {
diff -Nur -x .gitignore -x .git linux-2.6.21.3/drivers/serial/atmel_serial.h avr32-git/drivers/serial/atmel_serial.h
--- linux-2.6.21.3/drivers/serial/atmel_serial.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/drivers/serial/atmel_serial.h	2007-06-06 11:33:59.000000000 +0200
@@ -46,6 +46,9 @@
 #define			ATMEL_US_USMODE_ISO7816_T1	6
 #define			ATMEL_US_USMODE_IRDA		8
 #define		ATMEL_US_USCLKS		(3   <<  4)		/* Clock Selection */
+#define			ATMEL_US_USCLKS_MCK		(0 <<  4)
+#define			ATMEL_US_USCLKS_MCK_DIV8	(1 <<  4)
+#define			ATMEL_US_USCLKS_SCK		(3 <<  4)
 #define		ATMEL_US_CHRL		(3   <<  6)		/* Character Length */
 #define			ATMEL_US_CHRL_5			(0 <<  6)
 #define			ATMEL_US_CHRL_6			(1 <<  6)
diff -Nur -x .gitignore -x .git linux-2.6.21.3/drivers/spi/atmel_spi.c avr32-git/drivers/spi/atmel_spi.c
--- linux-2.6.21.3/drivers/spi/atmel_spi.c	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/drivers/spi/atmel_spi.c	2007-06-06 11:33:59.000000000 +0200
@@ -22,10 +22,7 @@
 #include <asm/io.h>
 #include <asm/arch/board.h>
 #include <asm/arch/gpio.h>
-
-#ifdef CONFIG_ARCH_AT91
 #include <asm/arch/cpu.h>
-#endif
 
 #include "atmel_spi.h"
 
@@ -116,16 +113,16 @@
 
 	len = as->remaining_bytes;
 
-	tx_dma = xfer->tx_dma;
-	rx_dma = xfer->rx_dma;
+	tx_dma = xfer->tx_dma + xfer->len - len;
+	rx_dma = xfer->rx_dma + xfer->len - len;
 
 	/* use scratch buffer only when rx or tx data is unspecified */
-	if (rx_dma == INVALID_DMA_ADDRESS) {
+	if (!xfer->rx_buf) {
 		rx_dma = as->buffer_dma;
 		if (len > BUFFER_SIZE)
 			len = BUFFER_SIZE;
 	}
-	if (tx_dma == INVALID_DMA_ADDRESS) {
+	if (!xfer->tx_buf) {
 		tx_dma = as->buffer_dma;
 		if (len > BUFFER_SIZE)
 			len = BUFFER_SIZE;
@@ -415,8 +412,8 @@
 		csr |= SPI_BIT(NCPHA);
 
 	/* TODO: DLYBS and DLYBCT */
-	csr |= SPI_BF(DLYBS, 10);
-	csr |= SPI_BF(DLYBCT, 10);
+	csr |= SPI_BF(DLYBS, 0);
+	csr |= SPI_BF(DLYBCT, 0);
 
 	/* chipselect must have been muxed as GPIO (e.g. in board setup) */
 	npcs_pin = (unsigned int)spi->controller_data;
@@ -552,10 +549,8 @@
 		goto out_free_buffer;
 	as->irq = irq;
 	as->clk = clk;
-#ifdef CONFIG_ARCH_AT91
 	if (!cpu_is_at91rm9200())
 		as->new_1 = 1;
-#endif
 
 	ret = request_irq(irq, atmel_spi_interrupt, 0,
 			pdev->dev.bus_id, master);
diff -Nur -x .gitignore -x .git linux-2.6.21.3/drivers/video/atmel_lcdfb.c avr32-git/drivers/video/atmel_lcdfb.c
--- linux-2.6.21.3/drivers/video/atmel_lcdfb.c	1970-01-01 01:00:00.000000000 +0100
+++ avr32-git/drivers/video/atmel_lcdfb.c	2007-06-06 11:34:00.000000000 +0200
@@ -0,0 +1,752 @@
+/*
+ *  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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/gpio.h>
+
+#include <video/atmel_lcdc.h>
+
+#define lcdc_readl(sinfo, reg)		__raw_readl((sinfo)->mmio+(reg))
+#define lcdc_writel(sinfo, reg, val)	__raw_writel((val), (sinfo)->mmio+(reg))
+
+/* configurable parameters */
+#define ATMEL_LCDC_CVAL_DEFAULT		0xc8
+#define ATMEL_LCDC_DMA_BURST_LEN	8
+
+#if defined(CONFIG_ARCH_AT91SAM9263)
+#define ATMEL_LCDC_FIFO_SIZE		2048
+#else
+#define ATMEL_LCDC_FIFO_SIZE		512
+#endif
+
+#if defined(CONFIG_ARCH_AT91)
+#define	ATMEL_LCDFB_FBINFO_DEFAULT	FBINFO_DEFAULT
+
+static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
+					struct fb_var_screeninfo *var)
+{
+
+}
+#elif defined(CONFIG_AVR32)
+#define	ATMEL_LCDFB_FBINFO_DEFAULT	(FBINFO_DEFAULT \
+					| FBINFO_PARTIAL_PAN_OK \
+					| FBINFO_HWACCEL_XPAN \
+					| FBINFO_HWACCEL_YPAN)
+
+static void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
+				     struct fb_var_screeninfo *var)
+{
+	u32 dma2dcfg;
+	u32 pixeloff;
+
+	pixeloff = (var->xoffset * var->bits_per_pixel) & 0x1f;
+
+	dma2dcfg = ((var->xres_virtual - var->xres) * var->bits_per_pixel) / 8;
+	dma2dcfg |= pixeloff << ATMEL_LCDC_PIXELOFF_OFFSET;
+	lcdc_writel(sinfo, ATMEL_LCDC_DMA2DCFG, dma2dcfg);
+
+	/* Update configuration */
+	lcdc_writel(sinfo, ATMEL_LCDC_DMACON,
+		    lcdc_readl(sinfo, ATMEL_LCDC_DMACON)
+		    | ATMEL_LCDC_DMAUPDT);
+}
+#endif
+
+
+static struct fb_fix_screeninfo atmel_lcdfb_fix __initdata = {
+	.type		= FB_TYPE_PACKED_PIXELS,
+	.visual		= FB_VISUAL_TRUECOLOR,
+	.xpanstep	= 0,
+	.ypanstep	= 0,
+	.ywrapstep	= 0,
+	.accel		= FB_ACCEL_NONE,
+};
+
+
+static void atmel_lcdfb_update_dma(struct fb_info *info,
+			       struct fb_var_screeninfo *var)
+{
+	struct atmel_lcdfb_info *sinfo = info->par;
+	struct fb_fix_screeninfo *fix = &info->fix;
+	unsigned long dma_addr;
+
+	dma_addr = (fix->smem_start + var->yoffset * fix->line_length
+		    + var->xoffset * var->bits_per_pixel / 8);
+
+	dma_addr &= ~3UL;
+
+	/* Set framebuffer DMA base address and pixel offset */
+	lcdc_writel(sinfo, ATMEL_LCDC_DMABADDR1, dma_addr);
+
+	atmel_lcdfb_update_dma2d(sinfo, var);
+}
+
+static inline void atmel_lcdfb_free_video_memory(struct atmel_lcdfb_info *sinfo)
+{
+	struct fb_info *info = sinfo->info;
+
+	dma_free_writecombine(info->device, info->fix.smem_len,
+				info->screen_base, info->fix.smem_start);
+}
+
+/**
+ *	atmel_lcdfb_alloc_video_memory - Allocate framebuffer memory
+ *	@sinfo: the frame buffer to allocate memory for
+ */
+static int atmel_lcdfb_alloc_video_memory(struct atmel_lcdfb_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 = 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_lcdfb_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_lcdfb_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_lcdfb_check_var(struct fb_var_screeninfo *var,
+			     struct fb_info *info)
+{
+	struct device *dev = info->device;
+	struct atmel_lcdfb_info *sinfo = info->par;
+	unsigned long clk_value_khz;
+
+	clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000;
+
+	dev_dbg(dev, "%s:\n", __func__);
+	dev_dbg(dev, "  resolution: %ux%u\n", var->xres, var->yres);
+	dev_dbg(dev, "  pixclk:     %lu KHz\n", PICOS2KHZ(var->pixclock));
+	dev_dbg(dev, "  bpp:        %u\n", var->bits_per_pixel);
+	dev_dbg(dev, "  clk:        %lu KHz\n", clk_value_khz);
+
+	if ((PICOS2KHZ(var->pixclock) * var->bits_per_pixel / 8) > clk_value_khz) {
+		dev_err(dev, "%lu KHz pixel clock is too fast\n", PICOS2KHZ(var->pixclock));
+		return -EINVAL;
+	}
+
+	/* Force same alignment for each line */
+	var->xres = (var->xres + 3) & ~3UL;
+	var->xres_virtual = (var->xres_virtual + 3) & ~3UL;
+
+	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;
+	var->xoffset = var->yoffset = 0;
+
+	switch (var->bits_per_pixel) {
+	case 2:
+	case 4:
+	case 8:
+		var->red.offset = var->green.offset = var->blue.offset = 0;
+		var->red.length = var->green.length = var->blue.length
+			= var->bits_per_pixel;
+		break;
+	case 15:
+	case 16:
+		var->red.offset = 0;
+		var->green.offset = 5;
+		var->blue.offset = 10;
+		var->red.length = var->green.length = var->blue.length = 5;
+		break;
+	case 24:
+	case 32:
+		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;
+}
+
+/**
+ *      atmel_lcdfb_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_lcdfb_set_par(struct fb_info *info)
+{
+	struct atmel_lcdfb_info *sinfo = info->par;
+	unsigned long value;
+	unsigned long clk_value_khz;
+
+	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);
+
+	/* Turn off the LCD controller and the DMA controller */
+	lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET);
+
+	lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0);
+
+	if (info->var.bits_per_pixel <= 8)
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+	else
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+
+	info->fix.line_length = info->var.xres_virtual * (info->var.bits_per_pixel / 8);
+
+	/* Re-initialize the DMA engine... */
+	dev_dbg(info->device, "  * update DMA engine\n");
+	atmel_lcdfb_update_dma(info, &info->var);
+
+	/* ...set frame size and burst length = 8 words (?) */
+	value = (info->var.yres * info->var.xres * info->var.bits_per_pixel) / 32;
+	value |= ((ATMEL_LCDC_DMA_BURST_LEN - 1) << ATMEL_LCDC_BLENGTH_OFFSET);
+	lcdc_writel(sinfo, ATMEL_LCDC_DMAFRMCFG, value);
+
+	/* Now, the LCDC core... */
+
+	/* Set pixel clock */
+	clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000;
+
+	value = clk_value_khz / PICOS2KHZ(info->var.pixclock);
+
+	if (clk_value_khz % PICOS2KHZ(info->var.pixclock))
+		value++;
+
+	value = (value / 2) - 1;
+
+	if (value <= 0) {
+		dev_notice(info->device, "Bypassing pixel clock divider\n");
+		lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1, ATMEL_LCDC_BYPASS);
+	} else
+		lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1, value << ATMEL_LCDC_CLKVAL_OFFSET);
+
+	/* Initialize control register 2 */
+	value = sinfo->default_lcdcon2;
+
+	if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
+		value |= ATMEL_LCDC_INVLINE_INVERTED;
+	if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
+		value |= ATMEL_LCDC_INVFRAME_INVERTED;
+
+	switch (info->var.bits_per_pixel) {
+		case 1:	value |= ATMEL_LCDC_PIXELSIZE_1; break;
+		case 2: value |= ATMEL_LCDC_PIXELSIZE_2; break;
+		case 4: value |= ATMEL_LCDC_PIXELSIZE_4; break;
+		case 8: value |= ATMEL_LCDC_PIXELSIZE_8; break;
+		case 15: /* fall through */
+		case 16: value |= ATMEL_LCDC_PIXELSIZE_16; break;
+		case 24: value |= ATMEL_LCDC_PIXELSIZE_24; break;
+		case 32: value |= ATMEL_LCDC_PIXELSIZE_32; break;
+		default: BUG(); break;
+	}
+	dev_dbg(info->device, "  * LCDCON2 = %08lx\n", value);
+	lcdc_writel(sinfo, ATMEL_LCDC_LCDCON2, value);
+
+	/* Vertical timing */
+	value = (info->var.vsync_len - 1) << ATMEL_LCDC_VPW_OFFSET;
+	value |= info->var.upper_margin << ATMEL_LCDC_VBP_OFFSET;
+	value |= info->var.lower_margin;
+	dev_dbg(info->device, "  * LCDTIM1 = %08lx\n", value);
+	lcdc_writel(sinfo, ATMEL_LCDC_TIM1, value);
+
+	/* Horizontal timing */
+	value = (info->var.right_margin - 1) << ATMEL_LCDC_HFP_OFFSET;
+	value |= (info->var.hsync_len - 1) << ATMEL_LCDC_HPW_OFFSET;
+	value |= (info->var.left_margin - 1);
+	dev_dbg(info->device, "  * LCDTIM2 = %08lx\n", value);
+	lcdc_writel(sinfo, ATMEL_LCDC_TIM2, value);
+
+	/* Display size */
+	value = (info->var.xres - 1) << ATMEL_LCDC_HOZVAL_OFFSET;
+	value |= info->var.yres - 1;
+	lcdc_writel(sinfo, ATMEL_LCDC_LCDFRMCFG, value);
+
+	/* FIFO Threshold: Use formula from data sheet */
+	value = ATMEL_LCDC_FIFO_SIZE - (2 * ATMEL_LCDC_DMA_BURST_LEN + 3);
+	lcdc_writel(sinfo, ATMEL_LCDC_FIFO, value);
+
+	/* Toggle LCD_MODE every frame */
+	lcdc_writel(sinfo, ATMEL_LCDC_MVAL, 0);
+
+	/* Disable all interrupts */
+	lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL);
+
+	/* Set contrast */
+	value = ATMEL_LCDC_PS_DIV8 | ATMEL_LCDC_POL_POSITIVE | ATMEL_LCDC_ENA_PWMENABLE;
+	lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, value);
+	lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, ATMEL_LCDC_CVAL_DEFAULT);
+	/* ...wait for DMA engine to become idle... */
+	while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY)
+		msleep(10);
+
+	dev_dbg(info->device, "  * re-enable DMA engine\n");
+	/* ...and enable it with updated configuration */
+	lcdc_writel(sinfo, ATMEL_LCDC_DMACON, sinfo->default_dmacon);
+
+	dev_dbg(info->device, "  * re-enable LCDC core\n");
+	lcdc_writel(sinfo, ATMEL_LCDC_PWRCON,
+		(sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET) | ATMEL_LCDC_PWR);
+
+	dev_dbg(info->device, "  * DONE\n");
+
+	return 0;
+}
+
+static inline unsigned int chan_to_field(unsigned int chan, const struct fb_bitfield *bf)
+{
+	chan &= 0xffff;
+	chan >>= 16 - bf->length;
+	return chan << bf->offset;
+}
+
+/**
+ *  	atmel_lcdfb_setcolreg - Optional function. Sets a color register.
+ *      @regno: Which register in the CLUT we are programming
+ *      @red: The red value which can be up to 16 bits wide
+ *	@green: The green value which can be up to 16 bits wide
+ *	@blue:  The blue value which can be up to 16 bits wide.
+ *	@transp: If supported the alpha value which can be up to 16 bits wide.
+ *      @info: frame buffer info structure
+ *
+ *  	Set a single color register. The values supplied have a 16 bit
+ *  	magnitude which needs to be scaled in this function for the hardware.
+ *	Things to take into consideration are how many color registers, if
+ *	any, are supported with the current color visual. With truecolor mode
+ *	no color palettes are supported. Here a psuedo palette is created
+ *	which we store the value in pseudo_palette in struct fb_info. For
+ *	pseudocolor mode we have a limited color palette. To deal with this
+ *	we can program what color is displayed for a particular pixel value.
+ *	DirectColor is similar in that we can program each color field. If
+ *	we have a static colormap we don't need to implement this function.
+ *
+ *	Returns negative errno on error, or zero on success. In an
+ *	ideal world, this would have been the case, but as it turns
+ *	out, the other drivers return 1 on failure, so that's what
+ *	we're going to do.
+ */
+static int atmel_lcdfb_setcolreg(unsigned int regno, unsigned int red,
+			     unsigned int green, unsigned int blue,
+			     unsigned int transp, struct fb_info *info)
+{
+	struct atmel_lcdfb_info *sinfo = info->par;
+	unsigned int val;
+	u32 *pal;
+	int ret = 1;
+
+	if (info->var.grayscale)
+		red = green = blue = (19595 * red + 38470 * green
+				      + 7471 * blue) >> 16;
+
+	switch (info->fix.visual) {
+	case FB_VISUAL_TRUECOLOR:
+		if (regno < 16) {
+			pal = info->pseudo_palette;
+
+			val  = chan_to_field(red, &info->var.red);
+			val |= chan_to_field(green, &info->var.green);
+			val |= chan_to_field(blue, &info->var.blue);
+
+			pal[regno] = val;
+			ret = 0;
+		}
+		break;
+
+	case FB_VISUAL_PSEUDOCOLOR:
+		if (regno < 256) {
+			val  = ((red   >> 11) & 0x001f);
+			val |= ((green >>  6) & 0x03e0);
+			val |= ((blue  >>  1) & 0x7c00);
+
+			/*
+			 * TODO: intensity bit. Maybe something like
+			 *   ~(red[10] ^ green[10] ^ blue[10]) & 1
+			 */
+
+			lcdc_writel(sinfo, ATMEL_LCDC_LUT(regno), val);
+			ret = 0;
+		}
+		break;
+	}
+
+	return ret;
+}
+
+static int atmel_lcdfb_pan_display(struct fb_var_screeninfo *var,
+			       struct fb_info *info)
+{
+	dev_dbg(info->device, "%s\n", __func__);
+
+	atmel_lcdfb_update_dma(info, var);
+
+	return 0;
+}
+
+static struct fb_ops atmel_lcdfb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= atmel_lcdfb_check_var,
+	.fb_set_par	= atmel_lcdfb_set_par,
+	.fb_setcolreg	= atmel_lcdfb_setcolreg,
+	.fb_pan_display	= atmel_lcdfb_pan_display,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+static irqreturn_t atmel_lcdfb_interrupt(int irq, void *dev_id)
+{
+	struct fb_info *info = dev_id;
+	struct atmel_lcdfb_info *sinfo = info->par;
+	u32 status;
+
+	status = lcdc_readl(sinfo, ATMEL_LCDC_ISR);
+	lcdc_writel(sinfo, ATMEL_LCDC_IDR, status);
+	return IRQ_HANDLED;
+}
+
+static int __init atmel_lcdfb_init_fbinfo(struct atmel_lcdfb_info *sinfo)
+{
+	struct fb_info *info = sinfo->info;
+	int ret = 0;
+
+	memset_io(info->screen_base, 0, info->fix.smem_len);
+	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);
+
+	/* Allocate colormap */
+	ret = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (ret < 0)
+		dev_err(info->device, "Alloc color map failed\n");
+
+	return ret;
+}
+
+static void atmel_lcdfb_start_clock(struct atmel_lcdfb_info *sinfo)
+{
+	if (sinfo->bus_clk)
+		clk_enable(sinfo->bus_clk);
+	clk_enable(sinfo->lcdc_clk);
+}
+
+static void atmel_lcdfb_stop_clock(struct atmel_lcdfb_info *sinfo)
+{
+	if (sinfo->bus_clk)
+		clk_disable(sinfo->bus_clk);
+	clk_disable(sinfo->lcdc_clk);
+}
+
+
+static int __init atmel_lcdfb_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct fb_info *info;
+	struct atmel_lcdfb_info *sinfo;
+	struct atmel_lcdfb_info *pdata_sinfo;
+	struct resource *regs = NULL;
+	struct resource *map = NULL;
+	int ret;
+
+	dev_dbg(dev, "%s BEGIN\n", __func__);
+
+	ret = -ENOMEM;
+	info = framebuffer_alloc(sizeof(struct atmel_lcdfb_info), dev);
+	if (!info) {
+		dev_err(dev, "cannot allocate memory\n");
+		goto out;
+	}
+
+	sinfo = info->par;
+
+	if (dev->platform_data) {
+		pdata_sinfo = (struct atmel_lcdfb_info *)dev->platform_data;
+		sinfo->default_bpp = pdata_sinfo->default_bpp;
+		sinfo->default_dmacon = pdata_sinfo->default_dmacon;
+		sinfo->default_lcdcon2 = pdata_sinfo->default_lcdcon2;
+		sinfo->default_monspecs = pdata_sinfo->default_monspecs;
+		sinfo->atmel_lcdfb_power_control = pdata_sinfo->atmel_lcdfb_power_control;
+		sinfo->guard_time = pdata_sinfo->guard_time;
+	} else {
+		dev_err(dev, "cannot get default configuration\n");
+		goto free_info;
+	}
+	sinfo->info = info;
+	sinfo->pdev = pdev;
+
+	strcpy(info->fix.id, sinfo->pdev->name);
+	info->flags = ATMEL_LCDFB_FBINFO_DEFAULT;
+	info->pseudo_palette = sinfo->pseudo_palette;
+	info->fbops = &atmel_lcdfb_ops;
+
+	memcpy(&info->monspecs, sinfo->default_monspecs, sizeof(info->monspecs));
+	info->fix = atmel_lcdfb_fix;
+
+	/* Enable LCDC Clocks */
+	if (cpu_is_at91sam9261() || cpu_is_at32ap7000()) {
+		sinfo->bus_clk = clk_get(dev, "hck1");
+		if (IS_ERR(sinfo->bus_clk)) {
+			ret = PTR_ERR(sinfo->bus_clk);
+			goto free_info;
+		}
+	}
+	sinfo->lcdc_clk = clk_get(dev, "lcdc_clk");
+	if (IS_ERR(sinfo->lcdc_clk)) {
+		ret = PTR_ERR(sinfo->lcdc_clk);
+		goto put_bus_clk;
+	}
+	atmel_lcdfb_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;
+	}
+
+	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, 1);
+	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;
+		}
+
+		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_lcdfb_alloc_video_memory(sinfo);
+		if (ret < 0) {
+			dev_err(dev, "cannot allocate framebuffer: %d\n", ret);
+			goto stop_clk;
+		}
+	}
+
+	/* LCDC 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 LCDC registers\n");
+		goto release_mem;
+	}
+
+	/* interrupt */
+	ret = request_irq(sinfo->irq_base, atmel_lcdfb_interrupt, 0, pdev->name, info);
+	if (ret) {
+		dev_err(dev, "request_irq failed: %d\n", ret);
+		goto unmap_mmio;
+	}
+
+	ret = atmel_lcdfb_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_lcdfb_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;
+	}
+
+	/* Power up the LCDC screen */
+	if (sinfo->atmel_lcdfb_power_control)
+		sinfo->atmel_lcdfb_power_control(1);
+
+	dev_info(dev, "fb%d: Atmel LCDC 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);
+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_lcdfb_free_video_memory(sinfo);
+
+release_intmem:
+	if (map)
+		release_mem_region(info->fix.smem_start, info->fix.smem_len);
+stop_clk:
+	atmel_lcdfb_stop_clock(sinfo);
+	clk_put(sinfo->lcdc_clk);
+put_bus_clk:
+	if (sinfo->bus_clk)
+		clk_put(sinfo->bus_clk);
+free_info:
+	framebuffer_release(info);
+out:
+	dev_dbg(dev, "%s FAILED\n", __func__);
+	return ret;
+}
+
+static int __exit atmel_lcdfb_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct atmel_lcdfb_info *sinfo = info->par;
+
+	if (!sinfo)
+		return 0;
+
+	if (sinfo->atmel_lcdfb_power_control)
+		sinfo->atmel_lcdfb_power_control(0);
+	unregister_framebuffer(info);
+	atmel_lcdfb_stop_clock(sinfo);
+	clk_put(sinfo->lcdc_clk);
+	if (sinfo->bus_clk)
+		clk_put(sinfo->bus_clk);
+	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_lcdfb_free_video_memory(sinfo);
+	}
+
+	dev_set_drvdata(dev, NULL);
+	framebuffer_release(info);
+
+	return 0;
+}
+
+static struct platform_driver atmel_lcdfb_driver = {
+	.remove		= __exit_p(atmel_lcdfb_remove),
+	.driver		= {
+		.name	= "atmel_lcdfb",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init atmel_lcdfb_init(void)
+{
+	return platform_driver_probe(&atmel_lcdfb_driver, atmel_lcdfb_probe);
+}
+
+static void __exit atmel_lcdfb_exit(void)
+{
+	platform_driver_unregister(&atmel_lcdfb_driver);
+}
+
+module_init(atmel_lcdfb_init);
+module_exit(atmel_lcdfb_exit);
+
+MODULE_DESCRIPTION("AT91/AT32 LCD Controller framebuffer driver");
+MODULE_AUTHOR("Nicolas Ferre <nicolas.ferre@rfo.atmel.com>");
+MODULE_LICENSE("GPL");
diff -Nur -x .gitignore -x .git linux-2.6.21.3/drivers/video/backlight/Kconfig avr32-git/drivers/video/backlight/Kconfig
--- linux-2.6.21.3/drivers/video/backlight/Kconfig	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/drivers/video/backlight/Kconfig	2007-06-06 11:34:00.000000000 +0200
@@ -8,26 +8,44 @@
 	  Enable this to be able to choose the drivers for controlling the
 	  backlight and the LCD panel on some platforms, for example on PDAs.
 
-config BACKLIGHT_CLASS_DEVICE
-        tristate "Lowlevel Backlight controls"
+#
+# LCD
+#
+config LCD_CLASS_DEVICE
+        tristate "Lowlevel LCD controls"
 	depends on BACKLIGHT_LCD_SUPPORT
 	default m
 	help
-	  This framework adds support for low-level control of the LCD
-          backlight. This includes support for brightness and power.
+	  This framework adds support for low-level control of LCD.
+	  Some framebuffer devices connect to platform-specific LCD modules
+	  in order to have a platform-specific way to control the flat panel
+	  (contrast and applying power to the LCD (not to the backlight!)).
 
 	  To have support for your specific LCD panel you will have to
 	  select the proper drivers which depend on this option.
 
-config LCD_CLASS_DEVICE
-        tristate "Lowlevel LCD controls"
+config LCD_LTV350QV
+	tristate "Samsung LTV350QV LCD Panel"
+	depends on LCD_CLASS_DEVICE && SPI_MASTER
+	default n
+	help
+	  If you have a Samsung LTV350QV LCD panel, say y to include a
+	  power control driver for it.  The panel starts up in power
+	  off state, so you need this driver in order to see any
+	  output.
+
+	  The LTV350QV panel is present on all ATSTK1000 boards.
+
+#
+# Backlight
+#
+config BACKLIGHT_CLASS_DEVICE
+        tristate "Lowlevel Backlight controls"
 	depends on BACKLIGHT_LCD_SUPPORT
 	default m
 	help
-	  This framework adds support for low-level control of LCD.
-	  Some framebuffer devices connect to platform-specific LCD modules
-	  in order to have a platform-specific way to control the flat panel
-	  (contrast and applying power to the LCD (not to the backlight!)).
+	  This framework adds support for low-level control of the LCD
+          backlight. This includes support for brightness and power.
 
 	  To have support for your specific LCD panel you will have to
 	  select the proper drivers which depend on this option.
diff -Nur -x .gitignore -x .git linux-2.6.21.3/drivers/video/backlight/ltv350qv.c avr32-git/drivers/video/backlight/ltv350qv.c
--- linux-2.6.21.3/drivers/video/backlight/ltv350qv.c	1970-01-01 01:00:00.000000000 +0100
+++ avr32-git/drivers/video/backlight/ltv350qv.c	2007-06-06 11:34:00.000000000 +0200
@@ -0,0 +1,340 @@
+/*
+ * Power control for Samsung LTV350QV Quarter VGA LCD Panel
+ *
+ * Copyright (C) 2006, 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.
+ */
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/lcd.h>
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+
+#include "ltv350qv.h"
+
+#define POWER_IS_ON(pwr)	((pwr) <= FB_BLANK_NORMAL)
+
+struct ltv350qv {
+	struct spi_device	*spi;
+	u8			*buffer;
+	int			power;
+	struct lcd_device	*ld;
+};
+
+/*
+ * The power-on and power-off sequences are taken from the
+ * LTV350QV-F04 data sheet from Samsung. The register definitions are
+ * taken from the S6F2002 command list also from Samsung. Both
+ * documents are distributed with the AVR32 Linux BSP CD from Atmel.
+ *
+ * There's still some voodoo going on here, but it's a lot better than
+ * in the first incarnation of the driver where all we had was the raw
+ * numbers from the initialization sequence.
+ */
+static int ltv350qv_write_reg(struct ltv350qv *lcd, u8 reg, u16 val)
+{
+	struct spi_message msg;
+	struct spi_transfer index_xfer = {
+		.len		= 3,
+		.cs_change	= 1,
+	};
+	struct spi_transfer value_xfer = {
+		.len		= 3,
+		.cs_change	= 1,
+	};
+
+	spi_message_init(&msg);
+
+	/* register index */
+	lcd->buffer[0] = LTV_OPC_INDEX;
+	lcd->buffer[1] = 0x00;
+	lcd->buffer[2] = reg & 0x7f;
+	index_xfer.tx_buf = lcd->buffer;
+	spi_message_add_tail(&index_xfer, &msg);
+
+	/* register value */
+	lcd->buffer[4] = LTV_OPC_DATA;
+	lcd->buffer[5] = val >> 8;
+	lcd->buffer[6] = val;
+	value_xfer.tx_buf = lcd->buffer + 4;
+	spi_message_add_tail(&value_xfer, &msg);
+
+	return spi_sync(lcd->spi, &msg);
+}
+
+/* The comments are taken straight from the data sheet */
+static int ltv350qv_power_on(struct ltv350qv *lcd)
+{
+	int ret;
+
+	/* Power On Reset Display off State */
+	if (ltv350qv_write_reg(lcd, LTV_PWRCTL1, 0x0000))
+		goto err;
+	msleep(15);
+
+	/* Power Setting Function 1 */
+	if (ltv350qv_write_reg(lcd, LTV_PWRCTL1, LTV_VCOM_DISABLE))
+		goto err;
+	if (ltv350qv_write_reg(lcd, LTV_PWRCTL2, LTV_VCOML_ENABLE))
+		goto err_power1;
+
+	/* Power Setting Function 2 */
+	if (ltv350qv_write_reg(lcd, LTV_PWRCTL1,
+			       LTV_VCOM_DISABLE | LTV_DRIVE_CURRENT(5)
+			       | LTV_SUPPLY_CURRENT(5)))
+		goto err_power2;
+
+	msleep(55);
+
+	/* Instruction Setting */
+	ret = ltv350qv_write_reg(lcd, LTV_IFCTL,
+				 LTV_NMD | LTV_REV | LTV_NL(0x1d));
+	ret |= ltv350qv_write_reg(lcd, LTV_DATACTL,
+				  LTV_DS_SAME | LTV_CHS_480
+				  | LTV_DF_RGB | LTV_RGB_BGR);
+	ret |= ltv350qv_write_reg(lcd, LTV_ENTRY_MODE,
+				  LTV_VSPL_ACTIVE_LOW
+				  | LTV_HSPL_ACTIVE_LOW
+				  | LTV_DPL_SAMPLE_RISING
+				  | LTV_EPL_ACTIVE_LOW
+				  | LTV_SS_RIGHT_TO_LEFT);
+	ret |= ltv350qv_write_reg(lcd, LTV_GATECTL1, LTV_CLW(3));
+	ret |= ltv350qv_write_reg(lcd, LTV_GATECTL2,
+				  LTV_NW_INV_1LINE | LTV_FWI(3));
+	ret |= ltv350qv_write_reg(lcd, LTV_VBP, 0x000a);
+	ret |= ltv350qv_write_reg(lcd, LTV_HBP, 0x0021);
+	ret |= ltv350qv_write_reg(lcd, LTV_SOTCTL, LTV_SDT(3) | LTV_EQ(0));
+	ret |= ltv350qv_write_reg(lcd, LTV_GAMMA(0), 0x0103);
+	ret |= ltv350qv_write_reg(lcd, LTV_GAMMA(1), 0x0301);
+	ret |= ltv350qv_write_reg(lcd, LTV_GAMMA(2), 0x1f0f);
+	ret |= ltv350qv_write_reg(lcd, LTV_GAMMA(3), 0x1f0f);
+	ret |= ltv350qv_write_reg(lcd, LTV_GAMMA(4), 0x0707);
+	ret |= ltv350qv_write_reg(lcd, LTV_GAMMA(5), 0x0307);
+	ret |= ltv350qv_write_reg(lcd, LTV_GAMMA(6), 0x0707);
+	ret |= ltv350qv_write_reg(lcd, LTV_GAMMA(7), 0x0000);
+	ret |= ltv350qv_write_reg(lcd, LTV_GAMMA(8), 0x0004);
+	ret |= ltv350qv_write_reg(lcd, LTV_GAMMA(9), 0x0000);
+	if (ret)
+		goto err_settings;
+
+	/* Wait more than 2 frames */
+	msleep(20);
+
+	/* Display On Sequence */
+	ret = ltv350qv_write_reg(lcd, LTV_PWRCTL1,
+				 LTV_VCOM_DISABLE | LTV_VCOMOUT_ENABLE
+				 | LTV_POWER_ON | LTV_DRIVE_CURRENT(5)
+				 | LTV_SUPPLY_CURRENT(5));
+	ret |= ltv350qv_write_reg(lcd, LTV_GATECTL2,
+				  LTV_NW_INV_1LINE | LTV_DSC | LTV_FWI(3));
+	if (ret)
+		goto err_disp_on;
+
+	/* Display should now be ON. Phew. */
+	return 0;
+
+err_disp_on:
+	/*
+	 * Try to recover. Error handling probably isn't very useful
+	 * at this point, just make a best effort to switch the panel
+	 * off.
+	 */
+	ltv350qv_write_reg(lcd, LTV_PWRCTL1,
+			   LTV_VCOM_DISABLE | LTV_DRIVE_CURRENT(5)
+			   | LTV_SUPPLY_CURRENT(5));
+	ltv350qv_write_reg(lcd, LTV_GATECTL2,
+			   LTV_NW_INV_1LINE | LTV_FWI(3));
+err_settings:
+err_power2:
+err_power1:
+	ltv350qv_write_reg(lcd, LTV_PWRCTL2, 0x0000);
+	msleep(1);
+err:
+	ltv350qv_write_reg(lcd, LTV_PWRCTL1, LTV_VCOM_DISABLE);
+	return -EIO;
+}
+
+static int ltv350qv_power_off(struct ltv350qv *lcd)
+{
+	int ret;
+
+	/* Display Off Sequence */
+	ret = ltv350qv_write_reg(lcd, LTV_PWRCTL1,
+				 LTV_VCOM_DISABLE
+				 | LTV_DRIVE_CURRENT(5)
+				 | LTV_SUPPLY_CURRENT(5));
+	ret |= ltv350qv_write_reg(lcd, LTV_GATECTL2,
+				  LTV_NW_INV_1LINE | LTV_FWI(3));
+
+	/* Power down setting 1 */
+	ret |= ltv350qv_write_reg(lcd, LTV_PWRCTL2, 0x0000);
+
+	/* Wait at least 1 ms */
+	msleep(1);
+
+	/* Power down setting 2 */
+	ret |= ltv350qv_write_reg(lcd, LTV_PWRCTL1, LTV_VCOM_DISABLE);
+
+	/*
+	 * No point in trying to recover here. If we can't switch the
+	 * panel off, what are we supposed to do other than inform the
+	 * user about the failure?
+	 */
+	if (ret)
+		return -EIO;
+
+	/* Display power should now be OFF */
+	return 0;
+}
+
+static int ltv350qv_power(struct ltv350qv *lcd, int power)
+{
+	int ret = 0;
+
+	if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->power))
+		ret = ltv350qv_power_on(lcd);
+	else if (!POWER_IS_ON(power) && POWER_IS_ON(lcd->power))
+		ret = ltv350qv_power_off(lcd);
+
+	if (!ret)
+		lcd->power = power;
+
+	return ret;
+}
+
+static int ltv350qv_set_power(struct lcd_device *ld, int power)
+{
+	struct ltv350qv *lcd;
+
+	lcd = class_get_devdata(&ld->class_dev);
+	return ltv350qv_power(lcd, power);
+}
+
+static int ltv350qv_get_power(struct lcd_device *ld)
+{
+	struct ltv350qv *lcd;
+
+	lcd = class_get_devdata(&ld->class_dev);
+	return lcd->power;
+}
+
+static struct lcd_ops ltv_ops = {
+	.get_power	= ltv350qv_get_power,
+	.set_power	= ltv350qv_set_power,
+};
+
+static int __devinit ltv350qv_probe(struct spi_device *spi)
+{
+	struct ltv350qv *lcd;
+	struct lcd_device *ld;
+	int ret;
+
+	lcd = kzalloc(sizeof(struct ltv350qv), GFP_KERNEL);
+	if (!lcd)
+		return -ENOMEM;
+
+	lcd->spi = spi;
+	lcd->power = FB_BLANK_POWERDOWN;
+	lcd->buffer = kzalloc(8, GFP_KERNEL);
+
+	ld = lcd_device_register("ltv350qv", lcd, &ltv_ops);
+	if (IS_ERR(ld)) {
+		ret = PTR_ERR(ld);
+		goto out_free_lcd;
+	}
+	lcd->ld = ld;
+
+	ret = ltv350qv_power(lcd, FB_BLANK_UNBLANK);
+	if (ret)
+		goto out_unregister;
+
+	dev_set_drvdata(&spi->dev, lcd);
+
+	return 0;
+
+out_unregister:
+	lcd_device_unregister(ld);
+out_free_lcd:
+	kfree(lcd);
+	return ret;
+}
+
+static int __devexit ltv350qv_remove(struct spi_device *spi)
+{
+	struct ltv350qv *lcd = dev_get_drvdata(&spi->dev);
+
+	ltv350qv_power(lcd, FB_BLANK_POWERDOWN);
+	lcd_device_unregister(lcd->ld);
+	kfree(lcd);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int ltv350qv_suspend(struct spi_device *spi,
+			    pm_message_t state, u32 level)
+{
+	struct ltv350qv *lcd = dev_get_drvdata(&spi->dev);
+
+	if (level == SUSPEND_POWER_DOWN)
+		return ltv350qv_power(lcd, FB_BLANK_POWERDOWN);
+
+	return 0;
+}
+
+static int ltv350qv_resume(struct spi_device *spi, u32 level)
+{
+	struct ltv350qv *lcd = dev_get_drvdata(&spi->dev);
+
+	if (level == RESUME_POWER_ON)
+		return ltv350qv_power(lcd, FB_BLANK_UNBLANK);
+
+	return 0;
+}
+#else
+#define ltv350qv_suspend	NULL
+#define ltv350qv_resume		NULL
+#endif
+
+/* Power down all displays on reboot, poweroff or halt */
+static void ltv350qv_shutdown(struct spi_device *spi)
+{
+	struct ltv350qv *lcd = dev_get_drvdata(&spi->dev);
+
+	ltv350qv_power(lcd, FB_BLANK_POWERDOWN);
+}
+
+static struct spi_driver ltv350qv_driver = {
+	.driver = {
+		.name		= "ltv350qv",
+		.bus		= &spi_bus_type,
+		.owner		= THIS_MODULE,
+	},
+
+	.probe		= ltv350qv_probe,
+	.remove		= __devexit_p(ltv350qv_remove),
+	.shutdown	= ltv350qv_shutdown,
+	.suspend	= ltv350qv_suspend,
+	.resume		= ltv350qv_resume,
+};
+
+static int __init ltv350qv_init(void)
+{
+	return spi_register_driver(&ltv350qv_driver);
+}
+
+static void __exit ltv350qv_exit(void)
+{
+	spi_unregister_driver(&ltv350qv_driver);
+}
+module_init(ltv350qv_init);
+module_exit(ltv350qv_exit);
+
+MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>");
+MODULE_DESCRIPTION("Samsung LTV350QV LCD Driver");
+MODULE_LICENSE("GPL");
diff -Nur -x .gitignore -x .git linux-2.6.21.3/drivers/video/backlight/ltv350qv.h avr32-git/drivers/video/backlight/ltv350qv.h
--- linux-2.6.21.3/drivers/video/backlight/ltv350qv.h	1970-01-01 01:00:00.000000000 +0100
+++ avr32-git/drivers/video/backlight/ltv350qv.h	2007-06-06 11:34:00.000000000 +0200
@@ -0,0 +1,95 @@
+/*
+ * Register definitions for Samsung LTV350QV Quarter VGA LCD Panel
+ *
+ * Copyright (C) 2006, 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 __LTV350QV_H
+#define __LTV350QV_H
+
+#define LTV_OPC_INDEX	0x74
+#define LTV_OPC_DATA	0x76
+
+#define LTV_ID		0x00		/* ID Read */
+#define LTV_IFCTL	0x01		/* Display Interface Control */
+#define LTV_DATACTL	0x02		/* Display Data Control */
+#define LTV_ENTRY_MODE	0x03		/* Entry Mode */
+#define LTV_GATECTL1	0x04		/* Gate Control 1 */
+#define LTV_GATECTL2	0x05		/* Gate Control 2 */
+#define LTV_VBP		0x06		/* Vertical Back Porch */
+#define LTV_HBP		0x07		/* Horizontal Back Porch */
+#define LTV_SOTCTL	0x08		/* Source Output Timing Control */
+#define LTV_PWRCTL1	0x09		/* Power Control 1 */
+#define LTV_PWRCTL2	0x0a		/* Power Control 2 */
+#define LTV_GAMMA(x)	(0x10 + (x))	/* Gamma control */
+
+/* Bit definitions for LTV_IFCTL */
+#define LTV_IM			(1 << 15)
+#define LTV_NMD			(1 << 14)
+#define LTV_SSMD		(1 << 13)
+#define LTV_REV			(1 <<  7)
+#define LTV_NL(x)		(((x) & 0x001f) << 0)
+
+/* Bit definitions for LTV_DATACTL */
+#define LTV_DS_SAME		(0 << 12)
+#define LTV_DS_D_TO_S		(1 << 12)
+#define LTV_DS_S_TO_D		(2 << 12)
+#define LTV_CHS_384		(0 <<  9)
+#define LTV_CHS_480		(1 <<  9)
+#define LTV_CHS_492		(2 <<  9)
+#define LTV_DF_RGB		(0 <<  6)
+#define LTV_DF_RGBX		(1 <<  6)
+#define LTV_DF_XRGB		(2 <<  6)
+#define LTV_RGB_RGB		(0 <<  2)
+#define LTV_RGB_BGR		(1 <<  2)
+#define LTV_RGB_GRB		(2 <<  2)
+#define LTV_RGB_RBG		(3 <<  2)
+
+/* Bit definitions for LTV_ENTRY_MODE */
+#define LTV_VSPL_ACTIVE_LOW	(0 << 15)
+#define LTV_VSPL_ACTIVE_HIGH	(1 << 15)
+#define LTV_HSPL_ACTIVE_LOW	(0 << 14)
+#define LTV_HSPL_ACTIVE_HIGH	(1 << 14)
+#define LTV_DPL_SAMPLE_RISING	(0 << 13)
+#define LTV_DPL_SAMPLE_FALLING	(1 << 13)
+#define LTV_EPL_ACTIVE_LOW	(0 << 12)
+#define LTV_EPL_ACTIVE_HIGH	(1 << 12)
+#define LTV_SS_LEFT_TO_RIGHT	(0 <<  8)
+#define LTV_SS_RIGHT_TO_LEFT	(1 <<  8)
+#define LTV_STB			(1 <<  1)
+
+/* Bit definitions for LTV_GATECTL1 */
+#define LTV_CLW(x)		(((x) & 0x0007) << 12)
+#define LTV_GAON		(1 <<  5)
+#define LTV_SDR			(1 <<  3)
+
+/* Bit definitions for LTV_GATECTL2 */
+#define LTV_NW_INV_FRAME	(0 << 14)
+#define LTV_NW_INV_1LINE	(1 << 14)
+#define LTV_NW_INV_2LINE	(2 << 14)
+#define LTV_DSC			(1 << 12)
+#define LTV_GIF			(1 <<  8)
+#define LTV_FHN			(1 <<  7)
+#define LTV_FTI(x)		(((x) & 0x0003) << 4)
+#define LTV_FWI(x)		(((x) & 0x0003) << 0)
+
+/* Bit definitions for LTV_SOTCTL */
+#define LTV_SDT(x)		(((x) & 0x0007) << 10)
+#define LTV_EQ(x)		(((x) & 0x0007) <<  2)
+
+/* Bit definitions for LTV_PWRCTL1 */
+#define LTV_VCOM_DISABLE	(1 << 14)
+#define LTV_VCOMOUT_ENABLE	(1 << 11)
+#define LTV_POWER_ON		(1 <<  9)
+#define LTV_DRIVE_CURRENT(x)	(((x) & 0x0007) << 4)	/* 0=off, 5=max */
+#define LTV_SUPPLY_CURRENT(x)	(((x) & 0x0007) << 0)	/* 0=off, 5=max */
+
+/* Bit definitions for LTV_PWRCTL2 */
+#define LTV_VCOML_ENABLE	(1 << 13)
+#define LTV_VCOML_VOLTAGE(x)	(((x) & 0x001f) << 8)	/* 0=1V, 31=-1V */
+#define LTV_VCOMH_VOLTAGE(x)	(((x) & 0x001f) << 0)	/* 0=3V, 31=4.5V */
+
+#endif /* __LTV350QV_H */
diff -Nur -x .gitignore -x .git linux-2.6.21.3/drivers/video/backlight/Makefile avr32-git/drivers/video/backlight/Makefile
--- linux-2.6.21.3/drivers/video/backlight/Makefile	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/drivers/video/backlight/Makefile	2007-06-06 11:34:00.000000000 +0200
@@ -1,6 +1,8 @@
 # Backlight & LCD drivers
 
 obj-$(CONFIG_LCD_CLASS_DEVICE)     += lcd.o
+obj-$(CONFIG_LCD_LTV350QV)	+= ltv350qv.o
+
 obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
 obj-$(CONFIG_BACKLIGHT_CORGI)	+= corgi_bl.o
 obj-$(CONFIG_BACKLIGHT_HP680)	+= hp680_bl.o
diff -Nur -x .gitignore -x .git linux-2.6.21.3/drivers/video/fbmem.c avr32-git/drivers/video/fbmem.c
--- linux-2.6.21.3/drivers/video/fbmem.c	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/drivers/video/fbmem.c	2007-06-06 11:34:00.000000000 +0200
@@ -1198,6 +1198,10 @@
 	pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
 #elif defined(__arm__) || defined(__sh__) || defined(__m32r__)
 	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+#elif defined(__avr32__)
+	vma->vm_page_prot = __pgprot((pgprot_val(vma->vm_page_prot)
+				      & ~_PAGE_CACHABLE)
+				     | (_PAGE_BUFFER | _PAGE_DIRTY));
 #elif defined(__ia64__)
 	if (efi_range_is_wc(vma->vm_start, vma->vm_end - vma->vm_start))
 		vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
diff -Nur -x .gitignore -x .git linux-2.6.21.3/drivers/video/Kconfig avr32-git/drivers/video/Kconfig
--- linux-2.6.21.3/drivers/video/Kconfig	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/drivers/video/Kconfig	2007-06-06 11:34:00.000000000 +0200
@@ -674,6 +674,22 @@
 	  working with S1D13806). Product specs at
 	  <http://www.erd.epson.com/vdc/html/legacy_13xxx.htm>
 
+config FB_ATMEL
+	tristate "AT91/AT32 LCD Controller support"
+	depends on FB && (ARCH_AT91SAM9261 || ARCH_AT91SAM9263 || AVR32)
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This enables support for the AT91/AT32 LCD Controller.
+
+config FB_INTSRAM
+	bool "Frame Buffer in internal SRAM"
+	depends on FB_ATMEL && ARCH_AT91SAM9261
+	help
+	  Say Y if you want to map Frame Buffer in internal SRAM. Say N if you want
+	  to let frame buffer in external SDRAM.
+
 config FB_NVIDIA
 	tristate "nVidia Framebuffer Support"
 	depends on FB && PCI
diff -Nur -x .gitignore -x .git linux-2.6.21.3/drivers/video/Makefile avr32-git/drivers/video/Makefile
--- linux-2.6.21.3/drivers/video/Makefile	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/drivers/video/Makefile	2007-06-06 11:34:00.000000000 +0200
@@ -75,6 +75,7 @@
 obj-$(CONFIG_FB_SA1100)           += sa1100fb.o
 obj-$(CONFIG_FB_HIT)              += hitfb.o
 obj-$(CONFIG_FB_EPSON1355)	  += epson1355fb.o
+obj-$(CONFIG_FB_ATMEL)		  += atmel_lcdfb.o
 obj-$(CONFIG_FB_PVR2)             += pvr2fb.o
 obj-$(CONFIG_FB_VOODOO1)          += sstfb.o
 obj-$(CONFIG_FB_ARMCLCD)	  += amba-clcd.o
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-alpha/pgtable.h avr32-git/include/asm-alpha/pgtable.h
--- linux-2.6.21.3/include/asm-alpha/pgtable.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-alpha/pgtable.h	2007-06-06 11:34:07.000000000 +0200
@@ -345,10 +345,6 @@
 #define io_remap_pfn_range(vma, start, pfn, size, prot)	\
 		remap_pfn_range(vma, start, pfn, size, prot)
 
-#define MK_IOSPACE_PFN(space, pfn)	(pfn)
-#define GET_IOSPACE(pfn)		0
-#define GET_PFN(pfn)			(pfn)
-
 #define pte_ERROR(e) \
 	printk("%s:%d: bad pte %016lx.\n", __FILE__, __LINE__, pte_val(e))
 #define pmd_ERROR(e) \
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-alpha/scatterlist.h avr32-git/include/asm-alpha/scatterlist.h
--- linux-2.6.21.3/include/asm-alpha/scatterlist.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-alpha/scatterlist.h	2007-06-06 11:34:07.000000000 +0200
@@ -2,6 +2,7 @@
 #define _ALPHA_SCATTERLIST_H
 
 #include <asm/page.h>
+#include <asm/types.h>
   
 struct scatterlist {
 	struct page *page;
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-arm/arch-at91/cpu.h avr32-git/include/asm-arm/arch-at91/cpu.h
--- linux-2.6.21.3/include/asm-arm/arch-at91/cpu.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-arm/arch-at91/cpu.h	2007-06-06 11:34:07.000000000 +0200
@@ -68,4 +68,10 @@
 #define cpu_is_at91sam9263()	(0)
 #endif
 
+/*
+ * Since this is ARM, we will never run on any AVR32 CPU. But these
+ * definitions may reduce clutter in common drivers.
+ */
+#define cpu_is_at32ap7000()	(0)
+
 #endif
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-arm/pgtable.h avr32-git/include/asm-arm/pgtable.h
--- linux-2.6.21.3/include/asm-arm/pgtable.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-arm/pgtable.h	2007-06-06 11:34:10.000000000 +0200
@@ -395,10 +395,6 @@
 #define io_remap_pfn_range(vma,from,pfn,size,prot) \
 		remap_pfn_range(vma, from, pfn, size, prot)
 
-#define MK_IOSPACE_PFN(space, pfn)	(pfn)
-#define GET_IOSPACE(pfn)		0
-#define GET_PFN(pfn)			(pfn)
-
 #define pgtable_cache_init() do { } while (0)
 
 #endif /* !__ASSEMBLY__ */
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-arm/pgtable-nommu.h avr32-git/include/asm-arm/pgtable-nommu.h
--- linux-2.6.21.3/include/asm-arm/pgtable-nommu.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-arm/pgtable-nommu.h	2007-06-06 11:34:10.000000000 +0200
@@ -83,10 +83,6 @@
 #define io_remap_page_range	remap_page_range
 #define io_remap_pfn_range	remap_pfn_range
 
-#define MK_IOSPACE_PFN(space, pfn)	(pfn)
-#define GET_IOSPACE(pfn)		0
-#define GET_PFN(pfn)			(pfn)
-
 
 /*
  * All 32bit addresses are effectively valid for vmalloc...
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-arm26/pgtable.h avr32-git/include/asm-arm26/pgtable.h
--- linux-2.6.21.3/include/asm-arm26/pgtable.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-arm26/pgtable.h	2007-06-06 11:34:10.000000000 +0200
@@ -297,10 +297,6 @@
 #define io_remap_pfn_range(vma,from,pfn,size,prot) \
 		remap_pfn_range(vma, from, pfn, size, prot)
 
-#define MK_IOSPACE_PFN(space, pfn)	(pfn)
-#define GET_IOSPACE(pfn)		0
-#define GET_PFN(pfn)			(pfn)
-
 #endif /* !__ASSEMBLY__ */
 
 #endif /* _ASMARM_PGTABLE_H */
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-avr32/arch-at32ap/board.h avr32-git/include/asm-avr32/arch-at32ap/board.h
--- linux-2.6.21.3/include/asm-avr32/arch-at32ap/board.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-avr32/arch-at32ap/board.h	2007-06-06 11:34:10.000000000 +0200
@@ -6,6 +6,8 @@
 
 #include <linux/types.h>
 
+#define GPIO_PIN_NONE	(-1)
+
 /* Add basic devices: system manager, interrupt controller, portmuxes, etc. */
 void at32_add_system_devices(void);
 
@@ -30,11 +32,22 @@
 struct platform_device *
 at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n);
 
-struct lcdc_platform_data {
-	unsigned long fbmem_start;
-	unsigned long fbmem_size;
+struct platform_device *at32_add_device_twi(unsigned int id);
+
+struct mci_platform_data {
+	int detect_pin;
+	int wp_pin;
 };
 struct platform_device *
-at32_add_device_lcdc(unsigned int id, struct lcdc_platform_data *data);
+at32_add_device_mci(unsigned int id, struct mci_platform_data *data);
+struct platform_device *at32_add_device_usba(unsigned int id);
+
+struct atmel_lcdfb_info;
+struct platform_device *
+at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data,
+		     unsigned long fbmem_start, unsigned long fbmem_len);
+
+struct platform_device *at32_add_device_ac97c(unsigned int id);
+struct platform_device *at32_add_device_abdac(unsigned int id);
 
 #endif /* __ASM_ARCH_BOARD_H */
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-avr32/arch-at32ap/cpu.h avr32-git/include/asm-avr32/arch-at32ap/cpu.h
--- linux-2.6.21.3/include/asm-avr32/arch-at32ap/cpu.h	1970-01-01 01:00:00.000000000 +0100
+++ avr32-git/include/asm-avr32/arch-at32ap/cpu.h	2007-06-06 11:34:10.000000000 +0200
@@ -0,0 +1,33 @@
+/*
+ * AVR32 and (fake) AT91 CPU identification
+ *
+ * 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_CPU_H
+#define __ASM_ARCH_CPU_H
+
+/*
+ * Only AT32AP7000 is defined for now. We can identify the specific
+ * chip at runtime, but I'm not sure if it's really worth it.
+ */
+#ifdef CONFIG_CPU_AT32AP7000
+# define cpu_is_at32ap7000()	(1)
+#else
+# define cpu_is_at32ap7000()	(0)
+#endif
+
+/*
+ * Since this is AVR32, we will never run on any AT91 CPU. But these
+ * definitions may reduce clutter in common drivers.
+ */
+#define cpu_is_at91rm9200()	(0)
+#define cpu_is_at91sam9xe()	(0)
+#define cpu_is_at91sam9260()	(0)
+#define cpu_is_at91sam9261()	(0)
+#define cpu_is_at91sam9263()	(0)
+
+#endif /* __ASM_ARCH_CPU_H */
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-avr32/arch-at32ap/gpio.h avr32-git/include/asm-avr32/arch-at32ap/gpio.h
--- linux-2.6.21.3/include/asm-avr32/arch-at32ap/gpio.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-avr32/arch-at32ap/gpio.h	2007-06-06 11:34:11.000000000 +0200
@@ -14,6 +14,8 @@
 int gpio_get_value(unsigned int gpio);
 void gpio_set_value(unsigned int gpio, int value);
 
+#include <asm-generic/gpio.h>		/* cansleep wrappers */
+
 static inline int gpio_to_irq(unsigned int gpio)
 {
 	return gpio + GPIO_IRQ_BASE;
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-avr32/arch-at32ap/io.h avr32-git/include/asm-avr32/arch-at32ap/io.h
--- linux-2.6.21.3/include/asm-avr32/arch-at32ap/io.h	1970-01-01 01:00:00.000000000 +0100
+++ avr32-git/include/asm-avr32/arch-at32ap/io.h	2007-06-06 11:34:11.000000000 +0200
@@ -0,0 +1,39 @@
+#ifndef __ASM_AVR32_ARCH_AT32AP_IO_H
+#define __ASM_AVR32_ARCH_AT32AP_IO_H
+
+/* For "bizarre" halfword swapping */
+#include <linux/byteorder/swabb.h>
+
+#if defined(CONFIG_AP7000_32_BIT_SMC)
+# define __swizzle_addr_b(addr)	(addr ^ 3UL)
+# define __swizzle_addr_w(addr)	(addr ^ 2UL)
+# define __swizzle_addr_l(addr)	(addr)
+# define ioswabb(a, x)		(x)
+# define ioswabw(a, x)		(x)
+# define ioswabl(a, x)		(x)
+# define __mem_ioswabb(a, x)	(x)
+# define __mem_ioswabw(a, x)	swab16(x)
+# define __mem_ioswabl(a, x)	swab32(x)
+#elif defined(CONFIG_AP7000_16_BIT_SMC)
+# define __swizzle_addr_b(addr)	(addr ^ 1UL)
+# define __swizzle_addr_w(addr)	(addr)
+# define __swizzle_addr_l(addr)	(addr)
+# define ioswabb(a, x)		(x)
+# define ioswabw(a, x)		(x)
+# define ioswabl(a, x)		swahw32(x)
+# define __mem_ioswabb(a, x)	(x)
+# define __mem_ioswabw(a, x)	swab16(x)
+# define __mem_ioswabl(a, x)	swahb32(x)
+#else
+# define __swizzle_addr_b(addr)	(addr)
+# define __swizzle_addr_w(addr)	(addr)
+# define __swizzle_addr_l(addr)	(addr)
+# define ioswabb(a, x)		(x)
+# define ioswabw(a, x)		swab16(x)
+# define ioswabl(a, x)		swab32(x)
+# define __mem_ioswabb(a, x)	(x)
+# define __mem_ioswabw(a, x)	(x)
+# define __mem_ioswabl(a, x)	(x)
+#endif
+
+#endif /* __ASM_AVR32_ARCH_AT32AP_IO_H */
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-avr32/arch-at32ap/smc.h avr32-git/include/asm-avr32/arch-at32ap/smc.h
--- linux-2.6.21.3/include/asm-avr32/arch-at32ap/smc.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-avr32/arch-at32ap/smc.h	2007-06-06 11:34:11.000000000 +0200
@@ -48,10 +48,32 @@
 	unsigned int	nwe_controlled:1;
 
 	/*
+	 * 0: NWAIT is disabled
+	 * 1: Reserved
+	 * 2: NWAIT is frozen mode
+	 * 3: NWAIT in ready mode
+	 */
+	unsigned int	nwait_mode:2;
+
+	/*
 	 * 0: Byte select access type
 	 * 1: Byte write access type
 	 */
 	unsigned int	byte_write:1;
+
+	/*
+	 * Number of clock cycles before data is released after
+	 * the rising edge of the read controlling signal
+	 *
+	 * Total cycles from SMC is tdf_cycles + 1
+	 */
+	unsigned int	tdf_cycles:4;
+
+	/*
+	 * 0: TDF optimization disabled
+	 * 1: TDF optimization enabled
+	 */
+	unsigned int	tdf_mode:1;
 };
 
 extern int smc_set_configuration(int cs, const struct smc_config *config);
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-avr32/arch-at32ap/time.h avr32-git/include/asm-avr32/arch-at32ap/time.h
--- linux-2.6.21.3/include/asm-avr32/arch-at32ap/time.h	1970-01-01 01:00:00.000000000 +0100
+++ avr32-git/include/asm-avr32/arch-at32ap/time.h	2007-06-06 11:34:11.000000000 +0200
@@ -0,0 +1,112 @@
+/*
+ * 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_AVR32_ARCH_AT32AP_TIME_H
+#define _ASM_AVR32_ARCH_AT32AP_TIME_H
+
+#include <linux/platform_device.h>
+
+extern struct irqaction timer_irqaction;
+extern struct platform_device at32_systc0_device;
+extern void local_timer_interrupt(int irq, void *dev_id);
+
+#define TIMER_BCR					0x000000c0
+#define TIMER_BCR_SYNC						 0
+#define TIMER_BMR					0x000000c4
+#define TIMER_BMR_TC0XC0S					 0
+#define TIMER_BMR_TC1XC1S					 2
+#define TIMER_BMR_TC2XC2S					 4
+#define TIMER_CCR					0x00000000
+#define TIMER_CCR_CLKDIS					 1
+#define TIMER_CCR_CLKEN						 0
+#define TIMER_CCR_SWTRG						 2
+#define TIMER_CMR					0x00000004
+#define TIMER_CMR_ABETRG					10
+#define TIMER_CMR_ACPA						16
+#define TIMER_CMR_ACPC						18
+#define TIMER_CMR_AEEVT						20
+#define TIMER_CMR_ASWTRG					22
+#define TIMER_CMR_BCPB						24
+#define TIMER_CMR_BCPC						26
+#define TIMER_CMR_BEEVT						28
+#define TIMER_CMR_BSWTRG					30
+#define TIMER_CMR_BURST						 4
+#define TIMER_CMR_CLKI						 3
+#define TIMER_CMR_CPCDIS					 7
+#define TIMER_CMR_CPCSTOP					 6
+#define TIMER_CMR_CPCTRG					14
+#define TIMER_CMR_EEVT						10
+#define TIMER_CMR_EEVTEDG					 8
+#define TIMER_CMR_ENETRG					12
+#define TIMER_CMR_ETRGEDG					 8
+#define TIMER_CMR_LDBDIS					 7
+#define TIMER_CMR_LDBSTOP					 6
+#define TIMER_CMR_LDRA						16
+#define TIMER_CMR_LDRB						18
+#define TIMER_CMR_TCCLKS					 0
+#define TIMER_CMR_WAVE						15
+#define TIMER_CMR_WAVSEL					13
+#define TIMER_CV					0x00000010
+#define TIMER_CV_CV						 0
+#define TIMER_IDR					0x00000028
+#define TIMER_IDR_COVFS						 0
+#define TIMER_IDR_CPAS						 2
+#define TIMER_IDR_CPBS						 3
+#define TIMER_IDR_CPCS						 4
+#define TIMER_IDR_ETRGS						 7
+#define TIMER_IDR_LDRAS						 5
+#define TIMER_IDR_LDRBS						 6
+#define TIMER_IDR_LOVRS						 1
+#define TIMER_IER					0x00000024
+#define TIMER_IER_COVFS						 0
+#define TIMER_IER_CPAS						 2
+#define TIMER_IER_CPBS						 3
+#define TIMER_IER_CPCS						 4
+#define TIMER_IER_ETRGS						 7
+#define TIMER_IER_LDRAS						 5
+#define TIMER_IER_LDRBS						 6
+#define TIMER_IER_LOVRS						 1
+#define TIMER_IMR					0x0000002c
+#define TIMER_IMR_COVFS						 0
+#define TIMER_IMR_CPAS						 2
+#define TIMER_IMR_CPBS						 3
+#define TIMER_IMR_CPCS						 4
+#define TIMER_IMR_ETRGS						 7
+#define TIMER_IMR_LDRAS						 5
+#define TIMER_IMR_LDRBS						 6
+#define TIMER_IMR_LOVRS						 1
+#define TIMER_RA					0x00000014
+#define TIMER_RA_RA						 0
+#define TIMER_RB					0x00000018
+#define TIMER_RB_RB						 0
+#define TIMER_RC					0x0000001c
+#define TIMER_RC_RC						 0
+#define TIMER_SR					0x00000020
+#define TIMER_SR_CLKSTA						16
+#define TIMER_SR_COVFS						 0
+#define TIMER_SR_CPAS						 2
+#define TIMER_SR_CPBS						 3
+#define TIMER_SR_CPCS						 4
+#define TIMER_SR_ETRGS						 7
+#define TIMER_SR_LDRAS						 5
+#define TIMER_SR_LDRBS						 6
+#define TIMER_SR_LOVRS						 1
+#define TIMER_SR_MTIOA						17
+#define TIMER_SR_MTIOB						18
+
+/* Bit manipulation macros */
+#define TIMER_BIT(name)		(1 << TIMER_##name)
+#define TIMER_BF(name,value)	((value) << TIMER_##name)
+
+/* Register access macros */
+#define timer_read(port,instance,reg) \
+	__raw_readl(port + (0x40 * instance) + TIMER_##reg)
+#define timer_write(port,instance,reg,value) \
+	__raw_writel((value), port + (0x40 * instance) + TIMER_##reg)
+
+#endif /* _ASM_AVR32_ARCH_AT32AP_TIME_H */
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-avr32/atomic.h avr32-git/include/asm-avr32/atomic.h
--- linux-2.6.21.3/include/asm-avr32/atomic.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-avr32/atomic.h	2007-06-06 11:34:11.000000000 +0200
@@ -173,7 +173,7 @@
 }
 
 #define atomic_xchg(v, new)	(xchg(&((v)->counter), new))
-#define atomic_cmpxchg(v, o, n)	((int)cmpxchg(&((v)->counter), (o), (n)))
+#define atomic_cmpxchg(v, o, n)	(cmpxchg(&((v)->counter), (o), (n)))
 
 #define atomic_sub(i, v)	(void)atomic_sub_return(i, v)
 #define atomic_add(i, v)	(void)atomic_add_return(i, v)
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-avr32/bug.h avr32-git/include/asm-avr32/bug.h
--- linux-2.6.21.3/include/asm-avr32/bug.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-avr32/bug.h	2007-06-06 11:34:11.000000000 +0200
@@ -18,27 +18,53 @@
 
 #ifdef CONFIG_DEBUG_BUGVERBOSE
 
-#define BUG()								\
-	do {								\
-		asm volatile(".hword	%0\n\t"				\
-			     ".hword	%1\n\t"				\
-			     ".long	%2"				\
-			     :						\
-			     : "n"(AVR32_BUG_OPCODE),			\
-			       "i"(__LINE__), "X"(__FILE__));		\
-	} while (0)
+#define _BUG_OR_WARN(flags)						\
+	asm volatile(							\
+		"1:	.hword	%0\n"					\
+		"	.section __bug_table,\"a\",@progbits\n"		\
+		"2:	.long	1b\n"					\
+		"	.long	%1\n"					\
+		"	.short	%2\n"					\
+		"	.short	%3\n"					\
+		"	.org	2b + %4\n"				\
+		"	.previous"					\
+		:							\
+		: "i"(AVR32_BUG_OPCODE), "i"(__FILE__),			\
+		  "i"(__LINE__), "i"(flags),				\
+		  "i"(sizeof(struct bug_entry)))
 
 #else
 
+#define _BUG_OR_WARN(flags)						\
+	asm volatile(							\
+		"1:	.hword	%0\n"					\
+		"	.section __bug_table,\"a\",@progbits\n"		\
+		"2:	.long	1b\n"					\
+		"	.short	%1\n"					\
+		"	.org	2b + %2\n"				\
+		"	.previous"					\
+		:							\
+		: "i"(AVR32_BUG_OPCODE), "i"(flags),			\
+		  "i"(sizeof(struct bug_entry)))
+
+#endif /* CONFIG_DEBUG_BUGVERBOSE */
+
 #define BUG()								\
 	do {								\
-		asm volatile(".hword	%0\n\t"				\
-			     : : "n"(AVR32_BUG_OPCODE));		\
+		_BUG_OR_WARN(0);					\
+		for (;;);						\
 	} while (0)
 
-#endif /* CONFIG_DEBUG_BUGVERBOSE */
+#define WARN_ON(condition)							\
+	({								\
+		typeof(condition) __ret_warn_on = (condition);		\
+		if (unlikely(__ret_warn_on))				\
+			_BUG_OR_WARN(BUGFLAG_WARNING);			\
+		unlikely(__ret_warn_on);				\
+	})
 
 #define HAVE_ARCH_BUG
+#define HAVE_ARCH_WARN_ON
 
 #endif /* CONFIG_BUG */
 
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-avr32/dma-controller.h avr32-git/include/asm-avr32/dma-controller.h
--- linux-2.6.21.3/include/asm-avr32/dma-controller.h	1970-01-01 01:00:00.000000000 +0100
+++ avr32-git/include/asm-avr32/dma-controller.h	2007-06-06 11:34:11.000000000 +0200
@@ -0,0 +1,166 @@
+/*
+ * 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.
+ */
+#ifndef __ASM_AVR32_DMA_CONTROLLER_H
+#define __ASM_AVR32_DMA_CONTROLLER_H
+
+#include <linux/device.h>
+
+#define DMA_DIR_MEM_TO_MEM		0x0000
+#define DMA_DIR_MEM_TO_PERIPH		0x0001
+#define DMA_DIR_PERIPH_TO_MEM		0x0002
+#define DMA_DIR_PERIPH_TO_PERIPH	0x0003
+
+#define DMA_WIDTH_8BIT			0
+#define DMA_WIDTH_16BIT			1
+#define DMA_WIDTH_32BIT			2
+
+struct dma_request {
+	struct dma_controller *dmac;
+	struct list_head list;
+
+	unsigned short channel;
+
+	void (*xfer_complete)(struct dma_request *req);
+	void (*block_complete)(struct dma_request *req);
+	void (*error)(struct dma_request *req);
+};
+
+struct dma_request_sg {
+	struct dma_request req;
+
+	int nr_sg;
+	struct scatterlist *sg;
+	unsigned long block_size;
+	unsigned int nr_blocks;
+
+	dma_addr_t data_reg;
+	unsigned short periph_id;
+
+	unsigned char direction;
+	unsigned char width;
+};
+#define to_dma_request_sg(_req)				\
+	container_of(_req, struct dma_request_sg, req)
+
+struct dma_request_cyclic {
+	struct dma_request req;
+
+        int periods;
+	unsigned long buffer_size;
+
+        dma_addr_t buffer_start;
+	dma_addr_t data_reg;
+
+	unsigned short periph_id;
+	unsigned char direction;
+	unsigned char width;
+
+        void *dev_id;
+};
+#define to_dma_request_cyclic(_req)				\
+	container_of(_req, struct dma_request_cyclic, req)
+
+struct dma_request_memcpy {
+	struct dma_request req;
+
+	dma_addr_t src_addr;
+	unsigned int src_width;
+	unsigned int src_stride;
+
+	dma_addr_t dst_addr;
+	unsigned int dst_width;
+	unsigned int dst_stride;
+
+	size_t length;
+
+	unsigned short src_reverse:1;
+	unsigned short dst_reverse:1;
+};
+#define to_dma_request_memcpy(_req)				\
+	container_of(_req, struct dma_request_memcpy, req)
+
+struct dma_controller {
+	struct list_head list;
+	int id;
+	struct device *dev;
+
+	int (*alloc_channel)(struct dma_controller *dmac);
+	void (*release_channel)(struct dma_controller *dmac,
+				int channel);
+	int (*prepare_request_sg)(struct dma_controller *dmac,
+				  struct dma_request_sg *req);
+        int (*prepare_request_cyclic)(struct dma_controller *dmac,
+				      struct dma_request_cyclic *req);
+	int (*prepare_request_memcpy)(struct dma_controller *dmac,
+				      struct dma_request_memcpy *req);
+	int (*start_request)(struct dma_controller *dmac,
+			     unsigned int channel);
+	int (*stop_request)(struct dma_controller *dmac,
+                            unsigned int channel);
+        dma_addr_t (*get_current_pos)(struct dma_controller *dmac,
+                                      unsigned int channel);
+};
+
+static inline int
+dma_alloc_channel(struct dma_controller *dmac)
+{
+	return dmac->alloc_channel(dmac);
+}
+
+static inline void
+dma_release_channel(struct dma_controller *dmac, int chan)
+{
+	dmac->release_channel(dmac, chan);
+}
+
+static inline int
+dma_prepare_request_sg(struct dma_controller *dmac,
+		       struct dma_request_sg *req)
+{
+	return dmac->prepare_request_sg(dmac, req);
+}
+
+static inline int
+dma_prepare_request_cyclic(struct dma_controller *dmac,
+			   struct dma_request_cyclic *req)
+{
+	return dmac->prepare_request_cyclic(dmac, req);
+}
+
+static inline int
+dma_prepare_request_memcpy(struct dma_controller *dmac,
+			   struct dma_request_memcpy *req)
+{
+	return dmac->prepare_request_memcpy(dmac, req);
+}
+
+static inline int
+dma_start_request(struct dma_controller *dmac,
+		  unsigned int channel)
+{
+	return dmac->start_request(dmac, channel);
+}
+
+static inline int
+dma_stop_request(struct dma_controller *dmac,
+                 unsigned int channel)
+{
+	return dmac->stop_request(dmac, channel);
+}
+
+static inline dma_addr_t
+dma_get_current_pos(struct dma_controller *dmac,
+                    unsigned int channel)
+{
+	return dmac->get_current_pos(dmac, channel);
+}
+
+extern int register_dma_controller(struct dma_controller *dmac);
+extern struct dma_controller *find_dma_controller(int id);
+
+#endif /* __ASM_AVR32_DMA_CONTROLLER_H */
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-avr32/io.h avr32-git/include/asm-avr32/io.h
--- linux-2.6.21.3/include/asm-avr32/io.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-avr32/io.h	2007-06-06 11:34:11.000000000 +0200
@@ -1,13 +1,15 @@
 #ifndef __ASM_AVR32_IO_H
 #define __ASM_AVR32_IO_H
 
+#include <linux/kernel.h>
 #include <linux/string.h>
-
-#ifdef __KERNEL__
+#include <linux/types.h>
 
 #include <asm/addrspace.h>
 #include <asm/byteorder.h>
 
+#include <asm/arch/io.h>
+
 /* virt_to_phys will only work when address is in P1 or P2 */
 static __inline__ unsigned long virt_to_phys(volatile void *address)
 {
@@ -36,104 +38,215 @@
 extern void __raw_readsw(const void __iomem *addr, void *data, int wordlen);
 extern void __raw_readsl(const void __iomem *addr, void *data, int longlen);
 
-static inline void writeb(unsigned char b, volatile void __iomem *addr)
+static inline void __raw_writeb(u8 v, volatile void __iomem *addr)
 {
-	*(volatile unsigned char __force *)addr = b;
+	*(volatile u8 __force *)addr = v;
 }
-static inline void writew(unsigned short b, volatile void __iomem *addr)
+static inline void __raw_writew(u16 v, volatile void __iomem *addr)
 {
-	*(volatile unsigned short __force *)addr = b;
+	*(volatile u16 __force *)addr = v;
 }
-static inline void writel(unsigned int b, volatile void __iomem *addr)
+static inline void __raw_writel(u32 v, volatile void __iomem *addr)
 {
-	*(volatile unsigned int __force *)addr = b;
+	*(volatile u32 __force *)addr = v;
 }
-#define __raw_writeb writeb
-#define __raw_writew writew
-#define __raw_writel writel
 
-static inline unsigned char readb(const volatile void __iomem *addr)
+static inline u8 __raw_readb(const volatile void __iomem *addr)
 {
-	return *(const volatile unsigned char __force *)addr;
+	return *(const volatile u8 __force *)addr;
 }
-static inline unsigned short readw(const volatile void __iomem *addr)
+static inline u16 __raw_readw(const volatile void __iomem *addr)
 {
-	return *(const volatile unsigned short __force *)addr;
+	return *(const volatile u16 __force *)addr;
 }
-static inline unsigned int readl(const volatile void __iomem *addr)
+static inline u32 __raw_readl(const volatile void __iomem *addr)
 {
-	return *(const volatile unsigned int __force *)addr;
+	return *(const volatile u32 __force *)addr;
 }
-#define __raw_readb readb
-#define __raw_readw readw
-#define __raw_readl readl
 
-#define writesb(p, d, l)	__raw_writesb((unsigned int)p, d, l)
-#define writesw(p, d, l)	__raw_writesw((unsigned int)p, d, l)
-#define writesl(p, d, l)	__raw_writesl((unsigned int)p, d, l)
+/* Convert I/O port address to virtual address */
+#ifndef __io
+# define __io(p)	((void *)phys_to_uncached(p))
+#endif
 
-#define readsb(p, d, l)		__raw_readsb((unsigned int)p, d, l)
-#define readsw(p, d, l)		__raw_readsw((unsigned int)p, d, l)
-#define readsl(p, d, l)		__raw_readsl((unsigned int)p, d, l)
+/*
+ * Not really sure about the best way to slow down I/O on
+ * AVR32. Defining it as a no-op until we have an actual test case.
+ */
+#define SLOW_DOWN_IO	do { } while (0)
 
+#define __BUILD_MEMORY_SINGLE(pfx, bwl, type)				\
+static inline void							\
+pfx##write##bwl(type val, volatile void __iomem *addr)			\
+{									\
+	volatile type *__addr;						\
+	type __val;							\
+									\
+	__addr = (void *)__swizzle_addr_##bwl((unsigned long)(addr));	\
+	__val = pfx##ioswab##bwl(__addr, val);				\
+									\
+	BUILD_BUG_ON(sizeof(type) > sizeof(unsigned long));		\
+									\
+	*__addr = __val;						\
+}									\
+									\
+static inline type pfx##read##bwl(const volatile void __iomem *addr)	\
+{									\
+	volatile type *__addr;						\
+	type __val;							\
+									\
+	__addr = (void *)__swizzle_addr_##bwl((unsigned long)(addr));	\
+									\
+	BUILD_BUG_ON(sizeof(type) > sizeof(unsigned long));		\
+									\
+	__val = *__addr;						\
+	return pfx##ioswab##bwl(__addr, __val);				\
+}
+
+#define __BUILD_IOPORT_SINGLE(pfx, bwl, type, p, slow)			\
+static inline void pfx##out##bwl##p(type val, unsigned long port)	\
+{									\
+	volatile type *__addr;						\
+	type __val;							\
+									\
+	__addr = __io(__swizzle_addr_##bwl(port));			\
+	__val = pfx##ioswab##bwl(__addr, val);				\
+									\
+	BUILD_BUG_ON(sizeof(type) > sizeof(unsigned long));		\
+									\
+	*__addr = __val;						\
+	slow;								\
+}									\
+									\
+static inline type pfx##in##bwl##p(unsigned long port)			\
+{									\
+	volatile type *__addr;						\
+	type __val;							\
+									\
+	__addr = __io(__swizzle_addr_##bwl(port));			\
+									\
+	BUILD_BUG_ON(sizeof(type) > sizeof(unsigned long));		\
+									\
+	__val = *__addr;						\
+	slow;								\
+									\
+	return pfx##ioswab##bwl(__addr, __val);				\
+}
+
+#define __BUILD_MEMORY_PFX(bus, bwl, type)				\
+	__BUILD_MEMORY_SINGLE(bus, bwl, type)
+
+#define BUILDIO_MEM(bwl, type)						\
+	__BUILD_MEMORY_PFX(, bwl, type)					\
+	__BUILD_MEMORY_PFX(__mem_, bwl, type)
+
+#define __BUILD_IOPORT_PFX(bus, bwl, type)				\
+	__BUILD_IOPORT_SINGLE(bus, bwl, type, ,)			\
+	__BUILD_IOPORT_SINGLE(bus, bwl, type, _p, SLOW_DOWN_IO)
+
+#define BUILDIO_IOPORT(bwl, type)					\
+	__BUILD_IOPORT_PFX(, bwl, type)					\
+	__BUILD_IOPORT_PFX(__mem_, bwl, type)
+
+BUILDIO_MEM(b, u8)
+BUILDIO_MEM(w, u16)
+BUILDIO_MEM(l, u32)
+
+BUILDIO_IOPORT(b, u8)
+BUILDIO_IOPORT(w, u16)
+BUILDIO_IOPORT(l, u32)
+
+#define readb_relaxed			readb
+#define readw_relaxed			readw
+#define readl_relaxed			readl
+
+#define __BUILD_MEMORY_STRING(bwl, type)				\
+static inline void writes##bwl(volatile void __iomem *addr,		\
+			       const void *data, unsigned int count)	\
+{									\
+	const type *__data = data;					\
+									\
+	while (count--)							\
+		__mem_write##bwl(*__data++, addr);			\
+}									\
+									\
+static inline void reads##bwl(const volatile void __iomem *addr,	\
+			      void *data, unsigned int count)		\
+{									\
+	type *__data = data;						\
+									\
+	while (count--)							\
+		*__data++ = __mem_read##bwl(addr);			\
+}
+
+#define __BUILD_IOPORT_STRING(bwl, type)				\
+static inline void outs##bwl(unsigned long port, const void *data,	\
+			     unsigned int count)			\
+{									\
+	const type *__data = data;					\
+									\
+	while (count--)							\
+		__mem_out##bwl(*__data++, port);			\
+}									\
+									\
+static inline void ins##bwl(unsigned long port, void *data,		\
+			   unsigned int count)				\
+{									\
+	type *__data = data;						\
+									\
+	while (count--)							\
+		*__data++ = __mem_in##bwl(port);			\
+}
+
+#define BUILDSTRING(bwl, type)						\
+	__BUILD_MEMORY_STRING(bwl, type)				\
+	__BUILD_IOPORT_STRING(bwl, type)
+
+BUILDSTRING(b, u8)
+BUILDSTRING(w, u16)
+BUILDSTRING(l, u32)
 
 /*
  * io{read,write}{8,16,32} macros in both le (for PCI style consumers) and native be
  */
 #ifndef ioread8
 
-#define ioread8(p)	({ unsigned int __v = __raw_readb(p); __v; })
+#define ioread8(p)		((unsigned int)readb(p))
 
-#define ioread16(p)	({ unsigned int __v = le16_to_cpu(__raw_readw(p)); __v; })
-#define ioread16be(p)	({ unsigned int __v = be16_to_cpu(__raw_readw(p)); __v; })
+#define ioread16(p)		((unsigned int)readw(p))
+#define ioread16be(p)		((unsigned int)__raw_readw(p))
 
-#define ioread32(p)	({ unsigned int __v = le32_to_cpu(__raw_readl(p)); __v; })
-#define ioread32be(p)	({ unsigned int __v = be32_to_cpu(__raw_readl(p)); __v; })
+#define ioread32(p)		((unsigned int)readl(p))
+#define ioread32be(p)		((unsigned int)__raw_readl(p))
 
-#define iowrite8(v,p)	__raw_writeb(v, p)
+#define iowrite8(v,p)		writeb(v, p)
 
-#define iowrite16(v,p)	__raw_writew(cpu_to_le16(v), p)
-#define iowrite16be(v,p)	__raw_writew(cpu_to_be16(v), p)
+#define iowrite16(v,p)		writew(v, p)
+#define iowrite16be(v,p)	__raw_writew(v, p)
 
-#define iowrite32(v,p)	__raw_writel(cpu_to_le32(v), p)
-#define iowrite32be(v,p)	__raw_writel(cpu_to_be32(v), p)
+#define iowrite32(v,p)		writel(v, p)
+#define iowrite32be(v,p)	__raw_writel(v, p)
 
-#define ioread8_rep(p,d,c)	__raw_readsb(p,d,c)
-#define ioread16_rep(p,d,c)	__raw_readsw(p,d,c)
-#define ioread32_rep(p,d,c)	__raw_readsl(p,d,c)
+#define ioread8_rep(p,d,c)	readsb(p,d,c)
+#define ioread16_rep(p,d,c)	readsw(p,d,c)
+#define ioread32_rep(p,d,c)	readsl(p,d,c)
 
-#define iowrite8_rep(p,s,c)	__raw_writesb(p,s,c)
-#define iowrite16_rep(p,s,c)	__raw_writesw(p,s,c)
-#define iowrite32_rep(p,s,c)	__raw_writesl(p,s,c)
+#define iowrite8_rep(p,s,c)	writesb(p,s,c)
+#define iowrite16_rep(p,s,c)	writesw(p,s,c)
+#define iowrite32_rep(p,s,c)	writesl(p,s,c)
 
 #endif
 
-
-/*
- * These two are only here because ALSA _thinks_ it needs them...
- */
 static inline void memcpy_fromio(void * to, const volatile void __iomem *from,
 				 unsigned long count)
 {
-	char *p = to;
-	while (count) {
-		count--;
-		*p = readb(from);
-		p++;
-		from++;
-	}
+	memcpy(to, (const void __force *)from, count);
 }
 
 static inline void  memcpy_toio(volatile void __iomem *to, const void * from,
 				unsigned long count)
 {
-	const char *p = from;
-	while (count) {
-		count--;
-		writeb(*p, to);
-		p++;
-		to++;
-	}
+	memcpy((void __force *)to, from, count);
 }
 
 static inline void memset_io(volatile void __iomem *addr, unsigned char val,
@@ -142,99 +255,8 @@
 	memset((void __force *)addr, val, count);
 }
 
-/*
- * Bad read/write accesses...
- */
-extern void __readwrite_bug(const char *fn);
-
 #define IO_SPACE_LIMIT	0xffffffff
 
-/* Convert I/O port address to virtual address */
-#define __io(p)		((void __iomem *)phys_to_uncached(p))
-
-/*
- *  IO port access primitives
- *  -------------------------
- *
- * The AVR32 doesn't have special IO access instructions; all IO is memory
- * mapped. Note that these are defined to perform little endian accesses
- * only. Their primary purpose is to access PCI and ISA peripherals.
- *
- * Note that for a big endian machine, this implies that the following
- * big endian mode connectivity is in place.
- *
- * The machine specific io.h include defines __io to translate an "IO"
- * address to a memory address.
- *
- * Note that we prevent GCC re-ordering or caching values in expressions
- * by introducing sequence points into the in*() definitions.  Note that
- * __raw_* do not guarantee this behaviour.
- *
- * The {in,out}[bwl] macros are for emulating x86-style PCI/ISA IO space.
- */
-#define outb(v, p)		__raw_writeb(v, __io(p))
-#define outw(v, p)		__raw_writew(cpu_to_le16(v), __io(p))
-#define outl(v, p)		__raw_writel(cpu_to_le32(v), __io(p))
-
-#define inb(p)			__raw_readb(__io(p))
-#define inw(p)			le16_to_cpu(__raw_readw(__io(p)))
-#define inl(p)			le32_to_cpu(__raw_readl(__io(p)))
-
-static inline void __outsb(unsigned long port, void *addr, unsigned int count)
-{
-	while (count--) {
-		outb(*(u8 *)addr, port);
-		addr++;
-	}
-}
-
-static inline void __insb(unsigned long port, void *addr, unsigned int count)
-{
-	while (count--) {
-		*(u8 *)addr = inb(port);
-		addr++;
-	}
-}
-
-static inline void __outsw(unsigned long port, void *addr, unsigned int count)
-{
-	while (count--) {
-		outw(*(u16 *)addr, port);
-		addr += 2;
-	}
-}
-
-static inline void __insw(unsigned long port, void *addr, unsigned int count)
-{
-	while (count--) {
-		*(u16 *)addr = inw(port);
-		addr += 2;
-	}
-}
-
-static inline void __outsl(unsigned long port, void *addr, unsigned int count)
-{
-	while (count--) {
-		outl(*(u32 *)addr, port);
-		addr += 4;
-	}
-}
-
-static inline void __insl(unsigned long port, void *addr, unsigned int count)
-{
-	while (count--) {
-		*(u32 *)addr = inl(port);
-		addr += 4;
-	}
-}
-
-#define outsb(port, addr, count)	__outsb(port, addr, count)
-#define insb(port, addr, count)		__insb(port, addr, count)
-#define outsw(port, addr, count)	__outsw(port, addr, count)
-#define insw(port, addr, count)		__insw(port, addr, count)
-#define outsl(port, addr, count)	__outsl(port, addr, count)
-#define insl(port, addr, count)		__insl(port, addr, count)
-
 extern void __iomem *__ioremap(unsigned long offset, size_t size,
 			       unsigned long flags);
 extern void __iounmap(void __iomem *addr);
@@ -292,6 +314,4 @@
  */
 #define xlate_dev_kmem_ptr(p)   p
 
-#endif /* __KERNEL__ */
-
 #endif /* __ASM_AVR32_IO_H */
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-avr32/kdebug.h avr32-git/include/asm-avr32/kdebug.h
--- linux-2.6.21.3/include/asm-avr32/kdebug.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-avr32/kdebug.h	2007-06-06 11:34:11.000000000 +0200
@@ -12,16 +12,12 @@
 
 int register_die_notifier(struct notifier_block *nb);
 int unregister_die_notifier(struct notifier_block *nb);
-int register_page_fault_notifier(struct notifier_block *nb);
-int unregister_page_fault_notifier(struct notifier_block *nb);
 extern struct atomic_notifier_head avr32_die_chain;
 
 /* Grossly misnamed. */
 enum die_val {
-	DIE_FAULT,
 	DIE_BREAKPOINT,
 	DIE_SSTEP,
-	DIE_PAGE_FAULT,
 };
 
 static inline int notify_die(enum die_val val, struct pt_regs *regs,
@@ -35,4 +31,18 @@
 	return atomic_notifier_call_chain(&avr32_die_chain, val, &args);
 }
 
+/*
+ * These are only here because kprobes.c wants them to implement a
+ * blatant layering violation.  Will hopefully go away soon once all
+ * architectures are updated.
+ */
+static inline int register_page_fault_notifier(struct notifier_block *nb)
+{
+	return 0;
+}
+static inline int unregister_page_fault_notifier(struct notifier_block *nb)
+{
+	return 0;
+}
+
 #endif /* __ASM_AVR32_KDEBUG_H */
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-avr32/kprobes.h avr32-git/include/asm-avr32/kprobes.h
--- linux-2.6.21.3/include/asm-avr32/kprobes.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-avr32/kprobes.h	2007-06-06 11:34:11.000000000 +0200
@@ -26,6 +26,7 @@
 	kprobe_opcode_t	insn[MAX_INSN_SIZE];
 };
 
+extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
 extern int kprobe_exceptions_notify(struct notifier_block *self,
 				    unsigned long val, void *data);
 
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-avr32/pgtable.h avr32-git/include/asm-avr32/pgtable.h
--- linux-2.6.21.3/include/asm-avr32/pgtable.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-avr32/pgtable.h	2007-06-06 11:34:11.000000000 +0200
@@ -394,10 +394,6 @@
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)	\
 	remap_pfn_range(vma, vaddr, pfn, size, prot)
 
-#define MK_IOSPACE_PFN(space, pfn)	(pfn)
-#define GET_IOSPACE(pfn)		0
-#define GET_PFN(pfn)			(pfn)
-
 /* No page table caches to initialize (?) */
 #define pgtable_cache_init()	do { } while(0)
 
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-avr32/processor.h avr32-git/include/asm-avr32/processor.h
--- linux-2.6.21.3/include/asm-avr32/processor.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-avr32/processor.h	2007-06-06 11:34:11.000000000 +0200
@@ -40,6 +40,14 @@
 	TLB_INVALID
 };
 
+#define AVR32_FEATURE_RMW	(1 << 0)
+#define AVR32_FEATURE_DSP	(1 << 1)
+#define AVR32_FEATURE_SIMD	(1 << 2)
+#define AVR32_FEATURE_OCD	(1 << 3)
+#define AVR32_FEATURE_PCTR	(1 << 4)
+#define AVR32_FEATURE_JAVA	(1 << 5)
+#define AVR32_FEATURE_FPU	(1 << 6)
+
 struct avr32_cpuinfo {
 	struct clk *clk;
 	unsigned long loops_per_jiffy;
@@ -48,6 +56,7 @@
 	unsigned short arch_revision;
 	unsigned short cpu_revision;
 	enum tlb_config tlb_config;
+	unsigned long features;
 
 	struct cache_info icache;
 	struct cache_info dcache;
@@ -125,10 +134,10 @@
 #define thread_saved_pc(tsk)    ((tsk)->thread.cpu_context.pc)
 
 struct pt_regs;
-void show_trace(struct task_struct *task, unsigned long *stack,
-		struct pt_regs *regs);
-
 extern unsigned long get_wchan(struct task_struct *p);
+extern void show_regs_log_lvl(struct pt_regs *regs, const char *log_lvl);
+extern void show_stack_log_lvl(struct task_struct *tsk, unsigned long sp,
+			       struct pt_regs *regs, const char *log_lvl);
 
 #define KSTK_EIP(tsk)	((tsk)->thread.cpu_context.pc)
 #define KSTK_ESP(tsk)	((tsk)->thread.cpu_context.ksp)
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-avr32/scatterlist.h avr32-git/include/asm-avr32/scatterlist.h
--- linux-2.6.21.3/include/asm-avr32/scatterlist.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-avr32/scatterlist.h	2007-06-06 11:34:11.000000000 +0200
@@ -1,6 +1,8 @@
 #ifndef __ASM_AVR32_SCATTERLIST_H
 #define __ASM_AVR32_SCATTERLIST_H
 
+#include <asm/types.h>
+
 struct scatterlist {
     struct page		*page;
     unsigned int	offset;
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-avr32/setup.h avr32-git/include/asm-avr32/setup.h
--- linux-2.6.21.3/include/asm-avr32/setup.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-avr32/setup.h	2007-06-06 11:34:11.000000000 +0200
@@ -110,7 +110,7 @@
 	int	(*parse)(struct tag *);
 };
 
-#define __tag __attribute_used__ __attribute__((__section__(".taglist")))
+#define __tag __attribute_used__ __attribute__((__section__(".taglist.init")))
 #define __tagtable(tag, fn)						\
 	static struct tagtable __tagtable_##fn __tag = { tag, fn }
 
@@ -124,19 +124,12 @@
 #define for_each_tag(t,base)						\
 	for (t = base; t->hdr.size; t = tag_next(t))
 
-extern struct tag_mem_range *mem_phys;
-extern struct tag_mem_range *mem_reserved;
-extern struct tag_mem_range *mem_ramdisk;
-
 extern struct tag *bootloader_tags;
 
-extern void setup_bootmem(void);
-extern void setup_processor(void);
-extern void board_setup_fbmem(unsigned long fbmem_start,
-			      unsigned long fbmem_size);
+extern resource_size_t fbmem_start;
+extern resource_size_t fbmem_size;
 
-/* Chip-specific hook to enable the use of SDRAM */
-void chip_enable_sdram(void);
+void setup_processor(void);
 
 #endif /* !__ASSEMBLY__ */
 
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-avr32/sysreg.h avr32-git/include/asm-avr32/sysreg.h
--- linux-2.6.21.3/include/asm-avr32/sysreg.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-avr32/sysreg.h	2007-06-06 11:34:11.000000000 +0200
@@ -7,326 +7,281 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#ifndef __ASM_AVR32_SYSREG_H__
-#define __ASM_AVR32_SYSREG_H__
+#ifndef __ASM_AVR32_SYSREG_H
+#define __ASM_AVR32_SYSREG_H
 
 /* sysreg register offsets */
-#define SYSREG_SR                               0x0000
-#define SYSREG_EVBA                             0x0004
-#define SYSREG_ACBA                             0x0008
-#define SYSREG_CPUCR                            0x000c
-#define SYSREG_ECR                              0x0010
-#define SYSREG_RSR_SUP                          0x0014
-#define SYSREG_RSR_INT0                         0x0018
-#define SYSREG_RSR_INT1                         0x001c
-#define SYSREG_RSR_INT2                         0x0020
-#define SYSREG_RSR_INT3                         0x0024
-#define SYSREG_RSR_EX                           0x0028
-#define SYSREG_RSR_NMI                          0x002c
-#define SYSREG_RSR_DBG                          0x0030
-#define SYSREG_RAR_SUP                          0x0034
-#define SYSREG_RAR_INT0                         0x0038
-#define SYSREG_RAR_INT1                         0x003c
-#define SYSREG_RAR_INT2                         0x0040
-#define SYSREG_RAR_INT3                         0x0044
-#define SYSREG_RAR_EX                           0x0048
-#define SYSREG_RAR_NMI                          0x004c
-#define SYSREG_RAR_DBG                          0x0050
-#define SYSREG_JECR                             0x0054
-#define SYSREG_JOSP                             0x0058
-#define SYSREG_JAVA_LV0                         0x005c
-#define SYSREG_JAVA_LV1                         0x0060
-#define SYSREG_JAVA_LV2                         0x0064
-#define SYSREG_JAVA_LV3                         0x0068
-#define SYSREG_JAVA_LV4                         0x006c
-#define SYSREG_JAVA_LV5                         0x0070
-#define SYSREG_JAVA_LV6                         0x0074
-#define SYSREG_JAVA_LV7                         0x0078
-#define SYSREG_JTBA                             0x007c
-#define SYSREG_JBCR                             0x0080
-#define SYSREG_CONFIG0                          0x0100
-#define SYSREG_CONFIG1                          0x0104
-#define SYSREG_COUNT                            0x0108
-#define SYSREG_COMPARE                          0x010c
-#define SYSREG_TLBEHI                           0x0110
-#define SYSREG_TLBELO                           0x0114
-#define SYSREG_PTBR                             0x0118
-#define SYSREG_TLBEAR                           0x011c
-#define SYSREG_MMUCR                            0x0120
-#define SYSREG_TLBARLO                          0x0124
-#define SYSREG_TLBARHI                          0x0128
-#define SYSREG_PCCNT                            0x012c
-#define SYSREG_PCNT0                            0x0130
-#define SYSREG_PCNT1                            0x0134
-#define SYSREG_PCCR                             0x0138
-#define SYSREG_BEAR                             0x013c
+#define SYSREG_SR				0x0000
+#define SYSREG_EVBA				0x0004
+#define SYSREG_ACBA				0x0008
+#define SYSREG_CPUCR				0x000c
+#define SYSREG_ECR				0x0010
+#define SYSREG_RSR_SUP				0x0014
+#define SYSREG_RSR_INT0				0x0018
+#define SYSREG_RSR_INT1				0x001c
+#define SYSREG_RSR_INT2				0x0020
+#define SYSREG_RSR_INT3				0x0024
+#define SYSREG_RSR_EX				0x0028
+#define SYSREG_RSR_NMI				0x002c
+#define SYSREG_RSR_DBG				0x0030
+#define SYSREG_RAR_SUP				0x0034
+#define SYSREG_RAR_INT0				0x0038
+#define SYSREG_RAR_INT1				0x003c
+#define SYSREG_RAR_INT2				0x0040
+#define SYSREG_RAR_INT3				0x0044
+#define SYSREG_RAR_EX				0x0048
+#define SYSREG_RAR_NMI				0x004c
+#define SYSREG_RAR_DBG				0x0050
+#define SYSREG_JECR				0x0054
+#define SYSREG_JOSP				0x0058
+#define SYSREG_JAVA_LV0				0x005c
+#define SYSREG_JAVA_LV1				0x0060
+#define SYSREG_JAVA_LV2				0x0064
+#define SYSREG_JAVA_LV3				0x0068
+#define SYSREG_JAVA_LV4				0x006c
+#define SYSREG_JAVA_LV5				0x0070
+#define SYSREG_JAVA_LV6				0x0074
+#define SYSREG_JAVA_LV7				0x0078
+#define SYSREG_JTBA				0x007c
+#define SYSREG_JBCR				0x0080
+#define SYSREG_CONFIG0				0x0100
+#define SYSREG_CONFIG1				0x0104
+#define SYSREG_COUNT				0x0108
+#define SYSREG_COMPARE				0x010c
+#define SYSREG_TLBEHI				0x0110
+#define SYSREG_TLBELO				0x0114
+#define SYSREG_PTBR				0x0118
+#define SYSREG_TLBEAR				0x011c
+#define SYSREG_MMUCR				0x0120
+#define SYSREG_TLBARLO				0x0124
+#define SYSREG_TLBARHI				0x0128
+#define SYSREG_PCCNT				0x012c
+#define SYSREG_PCNT0				0x0130
+#define SYSREG_PCNT1				0x0134
+#define SYSREG_PCCR				0x0138
+#define SYSREG_BEAR				0x013c
+#define SYSREG_SABAL				0x0300
+#define SYSREG_SABAH				0x0304
+#define SYSREG_SABD				0x0308
 
 /* Bitfields in SR */
-#define SYSREG_SR_C_OFFSET                      0
-#define SYSREG_SR_C_SIZE                        1
-#define SYSREG_Z_OFFSET                         1
-#define SYSREG_Z_SIZE                           1
-#define SYSREG_SR_N_OFFSET                      2
-#define SYSREG_SR_N_SIZE                        1
-#define SYSREG_SR_V_OFFSET                      3
-#define SYSREG_SR_V_SIZE                        1
-#define SYSREG_Q_OFFSET                         4
-#define SYSREG_Q_SIZE                           1
-#define SYSREG_GM_OFFSET                        16
-#define SYSREG_GM_SIZE                          1
-#define SYSREG_I0M_OFFSET                       17
-#define SYSREG_I0M_SIZE                         1
-#define SYSREG_I1M_OFFSET                       18
-#define SYSREG_I1M_SIZE                         1
-#define SYSREG_I2M_OFFSET                       19
-#define SYSREG_I2M_SIZE                         1
-#define SYSREG_I3M_OFFSET                       20
-#define SYSREG_I3M_SIZE                         1
-#define SYSREG_EM_OFFSET                        21
-#define SYSREG_EM_SIZE                          1
-#define SYSREG_M0_OFFSET                        22
-#define SYSREG_M0_SIZE                          1
-#define SYSREG_M1_OFFSET                        23
-#define SYSREG_M1_SIZE                          1
-#define SYSREG_M2_OFFSET                        24
-#define SYSREG_M2_SIZE                          1
-#define SYSREG_SR_D_OFFSET                      26
-#define SYSREG_SR_D_SIZE                        1
-#define SYSREG_DM_OFFSET                        27
-#define SYSREG_DM_SIZE                          1
-#define SYSREG_SR_J_OFFSET                      28
-#define SYSREG_SR_J_SIZE                        1
-#define SYSREG_R_OFFSET                         29
-#define SYSREG_R_SIZE                           1
-#define SYSREG_H_OFFSET                         30
-#define SYSREG_H_SIZE                           1
-
-/* Bitfields in EVBA */
-
-/* Bitfields in ACBA */
+#define SYSREG_SR_C_OFFSET			0
+#define SYSREG_SR_C_SIZE			1
+#define SYSREG_Z_OFFSET				1
+#define SYSREG_Z_SIZE				1
+#define SYSREG_SR_N_OFFSET			2
+#define SYSREG_SR_N_SIZE			1
+#define SYSREG_SR_V_OFFSET			3
+#define SYSREG_SR_V_SIZE			1
+#define SYSREG_Q_OFFSET				4
+#define SYSREG_Q_SIZE				1
+#define SYSREG_L_OFFSET				5
+#define SYSREG_L_SIZE				1
+#define SYSREG_T_OFFSET				14
+#define SYSREG_T_SIZE				1
+#define SYSREG_SR_R_OFFSET			15
+#define SYSREG_SR_R_SIZE			1
+#define SYSREG_GM_OFFSET			16
+#define SYSREG_GM_SIZE				1
+#define SYSREG_I0M_OFFSET			17
+#define SYSREG_I0M_SIZE				1
+#define SYSREG_I1M_OFFSET			18
+#define SYSREG_I1M_SIZE				1
+#define SYSREG_I2M_OFFSET			19
+#define SYSREG_I2M_SIZE				1
+#define SYSREG_I3M_OFFSET			20
+#define SYSREG_I3M_SIZE				1
+#define SYSREG_EM_OFFSET			21
+#define SYSREG_EM_SIZE				1
+#define SYSREG_M0_OFFSET			22
+#define SYSREG_M0_SIZE				1
+#define SYSREG_M1_OFFSET			23
+#define SYSREG_M1_SIZE				1
+#define SYSREG_M2_OFFSET			24
+#define SYSREG_M2_SIZE				1
+#define SYSREG_SR_D_OFFSET			26
+#define SYSREG_SR_D_SIZE			1
+#define SYSREG_DM_OFFSET			27
+#define SYSREG_DM_SIZE				1
+#define SYSREG_SR_J_OFFSET			28
+#define SYSREG_SR_J_SIZE			1
+#define SYSREG_H_OFFSET				29
+#define SYSREG_H_SIZE				1
 
 /* Bitfields in CPUCR */
-#define SYSREG_BI_OFFSET                        0
-#define SYSREG_BI_SIZE                          1
-#define SYSREG_BE_OFFSET                        1
-#define SYSREG_BE_SIZE                          1
-#define SYSREG_FE_OFFSET                        2
-#define SYSREG_FE_SIZE                          1
-#define SYSREG_RE_OFFSET                        3
-#define SYSREG_RE_SIZE                          1
-#define SYSREG_IBE_OFFSET                       4
-#define SYSREG_IBE_SIZE                         1
-#define SYSREG_IEE_OFFSET                       5
-#define SYSREG_IEE_SIZE                         1
-
-/* Bitfields in ECR */
-#define SYSREG_ECR_OFFSET                       0
-#define SYSREG_ECR_SIZE                         32
-
-/* Bitfields in RSR_SUP */
-
-/* Bitfields in RSR_INT0 */
-
-/* Bitfields in RSR_INT1 */
-
-/* Bitfields in RSR_INT2 */
-
-/* Bitfields in RSR_INT3 */
-
-/* Bitfields in RSR_EX */
-
-/* Bitfields in RSR_NMI */
-
-/* Bitfields in RSR_DBG */
-
-/* Bitfields in RAR_SUP */
-
-/* Bitfields in RAR_INT0 */
-
-/* Bitfields in RAR_INT1 */
-
-/* Bitfields in RAR_INT2 */
-
-/* Bitfields in RAR_INT3 */
-
-/* Bitfields in RAR_EX */
-
-/* Bitfields in RAR_NMI */
-
-/* Bitfields in RAR_DBG */
-
-/* Bitfields in JECR */
-
-/* Bitfields in JOSP */
-
-/* Bitfields in JAVA_LV0 */
-
-/* Bitfields in JAVA_LV1 */
-
-/* Bitfields in JAVA_LV2 */
-
-/* Bitfields in JAVA_LV3 */
-
-/* Bitfields in JAVA_LV4 */
-
-/* Bitfields in JAVA_LV5 */
-
-/* Bitfields in JAVA_LV6 */
-
-/* Bitfields in JAVA_LV7 */
-
-/* Bitfields in JTBA */
-
-/* Bitfields in JBCR */
+#define SYSREG_BI_OFFSET			0
+#define SYSREG_BI_SIZE				1
+#define SYSREG_BE_OFFSET			1
+#define SYSREG_BE_SIZE				1
+#define SYSREG_FE_OFFSET			2
+#define SYSREG_FE_SIZE				1
+#define SYSREG_RE_OFFSET			3
+#define SYSREG_RE_SIZE				1
+#define SYSREG_IBE_OFFSET			4
+#define SYSREG_IBE_SIZE				1
+#define SYSREG_IEE_OFFSET			5
+#define SYSREG_IEE_SIZE				1
 
 /* Bitfields in CONFIG0 */
-#define SYSREG_CONFIG0_D_OFFSET                 1
-#define SYSREG_CONFIG0_D_SIZE                   1
-#define SYSREG_CONFIG0_S_OFFSET                 2
-#define SYSREG_CONFIG0_S_SIZE                   1
-#define SYSREG_O_OFFSET                         3
-#define SYSREG_O_SIZE                           1
-#define SYSREG_P_OFFSET                         4
-#define SYSREG_P_SIZE                           1
-#define SYSREG_CONFIG0_J_OFFSET                 5
-#define SYSREG_CONFIG0_J_SIZE                   1
-#define SYSREG_F_OFFSET                         6
-#define SYSREG_F_SIZE                           1
-#define SYSREG_MMUT_OFFSET                      7
-#define SYSREG_MMUT_SIZE                        3
-#define SYSREG_AR_OFFSET                        10
-#define SYSREG_AR_SIZE                          3
-#define SYSREG_AT_OFFSET                        13
-#define SYSREG_AT_SIZE                          3
-#define SYSREG_PROCESSORREVISION_OFFSET         16
-#define SYSREG_PROCESSORREVISION_SIZE           8
-#define SYSREG_PROCESSORID_OFFSET               24
-#define SYSREG_PROCESSORID_SIZE                 8
+#define SYSREG_CONFIG0_R_OFFSET			0
+#define SYSREG_CONFIG0_R_SIZE			1
+#define SYSREG_CONFIG0_D_OFFSET			1
+#define SYSREG_CONFIG0_D_SIZE			1
+#define SYSREG_CONFIG0_S_OFFSET			2
+#define SYSREG_CONFIG0_S_SIZE			1
+#define SYSREG_CONFIG0_O_OFFSET			3
+#define SYSREG_CONFIG0_O_SIZE			1
+#define SYSREG_CONFIG0_P_OFFSET			4
+#define SYSREG_CONFIG0_P_SIZE			1
+#define SYSREG_CONFIG0_J_OFFSET			5
+#define SYSREG_CONFIG0_J_SIZE			1
+#define SYSREG_CONFIG0_F_OFFSET			6
+#define SYSREG_CONFIG0_F_SIZE			1
+#define SYSREG_MMUT_OFFSET			7
+#define SYSREG_MMUT_SIZE			3
+#define SYSREG_AR_OFFSET			10
+#define SYSREG_AR_SIZE				3
+#define SYSREG_AT_OFFSET			13
+#define SYSREG_AT_SIZE				3
+#define SYSREG_PROCESSORREVISION_OFFSET		16
+#define SYSREG_PROCESSORREVISION_SIZE		8
+#define SYSREG_PROCESSORID_OFFSET		24
+#define SYSREG_PROCESSORID_SIZE			8
 
 /* Bitfields in CONFIG1 */
-#define SYSREG_DASS_OFFSET                      0
-#define SYSREG_DASS_SIZE                        3
-#define SYSREG_DLSZ_OFFSET                      3
-#define SYSREG_DLSZ_SIZE                        3
-#define SYSREG_DSET_OFFSET                      6
-#define SYSREG_DSET_SIZE                        4
-#define SYSREG_IASS_OFFSET                      10
-#define SYSREG_IASS_SIZE                        2
-#define SYSREG_ILSZ_OFFSET                      13
-#define SYSREG_ILSZ_SIZE                        3
-#define SYSREG_ISET_OFFSET                      16
-#define SYSREG_ISET_SIZE                        4
-#define SYSREG_DMMUSZ_OFFSET                    20
-#define SYSREG_DMMUSZ_SIZE                      6
-#define SYSREG_IMMUSZ_OFFSET                    26
-#define SYSREG_IMMUSZ_SIZE                      6
-
-/* Bitfields in COUNT */
-
-/* Bitfields in COMPARE */
+#define SYSREG_DASS_OFFSET			0
+#define SYSREG_DASS_SIZE			3
+#define SYSREG_DLSZ_OFFSET			3
+#define SYSREG_DLSZ_SIZE			3
+#define SYSREG_DSET_OFFSET			6
+#define SYSREG_DSET_SIZE			4
+#define SYSREG_IASS_OFFSET			10
+#define SYSREG_IASS_SIZE			3
+#define SYSREG_ILSZ_OFFSET			13
+#define SYSREG_ILSZ_SIZE			3
+#define SYSREG_ISET_OFFSET			16
+#define SYSREG_ISET_SIZE			4
+#define SYSREG_DMMUSZ_OFFSET			20
+#define SYSREG_DMMUSZ_SIZE			6
+#define SYSREG_IMMUSZ_OFFSET			26
+#define SYSREG_IMMUSZ_SIZE			6
 
 /* Bitfields in TLBEHI */
-#define SYSREG_ASID_OFFSET                      0
-#define SYSREG_ASID_SIZE                        8
-#define SYSREG_TLBEHI_I_OFFSET                  8
-#define SYSREG_TLBEHI_I_SIZE                    1
-#define SYSREG_TLBEHI_V_OFFSET                  9
-#define SYSREG_TLBEHI_V_SIZE                    1
-#define SYSREG_VPN_OFFSET                       10
-#define SYSREG_VPN_SIZE                         22
+#define SYSREG_ASID_OFFSET			0
+#define SYSREG_ASID_SIZE			8
+#define SYSREG_TLBEHI_I_OFFSET			8
+#define SYSREG_TLBEHI_I_SIZE			1
+#define SYSREG_TLBEHI_V_OFFSET			9
+#define SYSREG_TLBEHI_V_SIZE			1
+#define SYSREG_VPN_OFFSET			10
+#define SYSREG_VPN_SIZE				22
 
 /* Bitfields in TLBELO */
-#define SYSREG_W_OFFSET                         0
-#define SYSREG_W_SIZE                           1
-#define SYSREG_TLBELO_D_OFFSET                  1
-#define SYSREG_TLBELO_D_SIZE                    1
-#define SYSREG_SZ_OFFSET                        2
-#define SYSREG_SZ_SIZE                          2
-#define SYSREG_AP_OFFSET                        4
-#define SYSREG_AP_SIZE                          3
-#define SYSREG_B_OFFSET                         7
-#define SYSREG_B_SIZE                           1
-#define SYSREG_G_OFFSET                         8
-#define SYSREG_G_SIZE                           1
-#define SYSREG_TLBELO_C_OFFSET                  9
-#define SYSREG_TLBELO_C_SIZE                    1
-#define SYSREG_PFN_OFFSET                       10
-#define SYSREG_PFN_SIZE                         22
-
-/* Bitfields in PTBR */
-
-/* Bitfields in TLBEAR */
+#define SYSREG_W_OFFSET				0
+#define SYSREG_W_SIZE				1
+#define SYSREG_TLBELO_D_OFFSET			1
+#define SYSREG_TLBELO_D_SIZE			1
+#define SYSREG_SZ_OFFSET			2
+#define SYSREG_SZ_SIZE				2
+#define SYSREG_AP_OFFSET			4
+#define SYSREG_AP_SIZE				3
+#define SYSREG_B_OFFSET				7
+#define SYSREG_B_SIZE				1
+#define SYSREG_G_OFFSET				8
+#define SYSREG_G_SIZE				1
+#define SYSREG_TLBELO_C_OFFSET			9
+#define SYSREG_TLBELO_C_SIZE			1
+#define SYSREG_PFN_OFFSET			10
+#define SYSREG_PFN_SIZE				22
 
 /* Bitfields in MMUCR */
-#define SYSREG_E_OFFSET                         0
-#define SYSREG_E_SIZE                           1
-#define SYSREG_M_OFFSET                         1
-#define SYSREG_M_SIZE                           1
-#define SYSREG_MMUCR_I_OFFSET                   2
-#define SYSREG_MMUCR_I_SIZE                     1
-#define SYSREG_MMUCR_N_OFFSET                   3
-#define SYSREG_MMUCR_N_SIZE                     1
-#define SYSREG_MMUCR_S_OFFSET                   4
-#define SYSREG_MMUCR_S_SIZE                     1
-#define SYSREG_DLA_OFFSET                       8
-#define SYSREG_DLA_SIZE                         6
-#define SYSREG_DRP_OFFSET                       14
-#define SYSREG_DRP_SIZE                         6
-#define SYSREG_ILA_OFFSET                       20
-#define SYSREG_ILA_SIZE                         6
-#define SYSREG_IRP_OFFSET                       26
-#define SYSREG_IRP_SIZE                         6
-
-/* Bitfields in TLBARLO */
-
-/* Bitfields in TLBARHI */
-
-/* Bitfields in PCCNT */
-
-/* Bitfields in PCNT0 */
-
-/* Bitfields in PCNT1 */
+#define SYSREG_E_OFFSET				0
+#define SYSREG_E_SIZE				1
+#define SYSREG_M_OFFSET				1
+#define SYSREG_M_SIZE				1
+#define SYSREG_MMUCR_I_OFFSET			2
+#define SYSREG_MMUCR_I_SIZE			1
+#define SYSREG_MMUCR_N_OFFSET			3
+#define SYSREG_MMUCR_N_SIZE			1
+#define SYSREG_MMUCR_S_OFFSET			4
+#define SYSREG_MMUCR_S_SIZE			1
+#define SYSREG_DLA_OFFSET			8
+#define SYSREG_DLA_SIZE				6
+#define SYSREG_DRP_OFFSET			14
+#define SYSREG_DRP_SIZE				6
+#define SYSREG_ILA_OFFSET			20
+#define SYSREG_ILA_SIZE				6
+#define SYSREG_IRP_OFFSET			26
+#define SYSREG_IRP_SIZE				6
 
 /* Bitfields in PCCR */
-
-/* Bitfields in BEAR */
+#define SYSREG_PCCR_R_OFFSET			1
+#define SYSREG_PCCR_R_SIZE			1
+#define SYSREG_PCCR_C_OFFSET			2
+#define SYSREG_PCCR_C_SIZE			1
+#define SYSREG_PCCR_S_OFFSET			3
+#define SYSREG_PCCR_S_SIZE			1
+#define SYSREG_IEC_OFFSET			4
+#define SYSREG_IEC_SIZE				1
+#define SYSREG_IE0_OFFSET			5
+#define SYSREG_IE0_SIZE				1
+#define SYSREG_IE1_OFFSET			6
+#define SYSREG_IE1_SIZE				1
+#define SYSREG_FC_OFFSET			8
+#define SYSREG_FC_SIZE				1
+#define SYSREG_F0_OFFSET			9
+#define SYSREG_F0_SIZE				1
+#define SYSREG_F1_OFFSET			10
+#define SYSREG_F1_SIZE				1
+#define SYSREG_CONF0_OFFSET			12
+#define SYSREG_CONF0_SIZE			6
+#define SYSREG_CONF1_OFFSET			18
+#define SYSREG_CONF1_SIZE			6
 
 /* Constants for ECR */
-#define ECR_UNRECOVERABLE                       0
-#define ECR_TLB_MULTIPLE                        1
-#define ECR_BUS_ERROR_WRITE                     2
-#define ECR_BUS_ERROR_READ                      3
-#define ECR_NMI                                 4
-#define ECR_ADDR_ALIGN_X                        5
-#define ECR_PROTECTION_X                        6
-#define ECR_DEBUG                               7
-#define ECR_ILLEGAL_OPCODE                      8
-#define ECR_UNIMPL_INSTRUCTION                  9
-#define ECR_PRIVILEGE_VIOLATION                 10
-#define ECR_FPE                                 11
-#define ECR_COPROC_ABSENT                       12
-#define ECR_ADDR_ALIGN_R                        13
-#define ECR_ADDR_ALIGN_W                        14
-#define ECR_PROTECTION_R                        15
-#define ECR_PROTECTION_W                        16
-#define ECR_DTLB_MODIFIED                       17
-#define ECR_TLB_MISS_X                          20
-#define ECR_TLB_MISS_R                          24
-#define ECR_TLB_MISS_W                          28
+#define ECR_UNRECOVERABLE			0
+#define ECR_TLB_MULTIPLE			1
+#define ECR_BUS_ERROR_WRITE			2
+#define ECR_BUS_ERROR_READ			3
+#define ECR_NMI					4
+#define ECR_ADDR_ALIGN_X			5
+#define ECR_PROTECTION_X			6
+#define ECR_DEBUG				7
+#define ECR_ILLEGAL_OPCODE			8
+#define ECR_UNIMPL_INSTRUCTION			9
+#define ECR_PRIVILEGE_VIOLATION			10
+#define ECR_FPE					11
+#define ECR_COPROC_ABSENT			12
+#define ECR_ADDR_ALIGN_R			13
+#define ECR_ADDR_ALIGN_W			14
+#define ECR_PROTECTION_R			15
+#define ECR_PROTECTION_W			16
+#define ECR_DTLB_MODIFIED			17
+#define ECR_TLB_MISS_X				20
+#define ECR_TLB_MISS_R				24
+#define ECR_TLB_MISS_W				28
 
 /* Bit manipulation macros */
-#define SYSREG_BIT(name)                        (1 << SYSREG_##name##_OFFSET)
-#define SYSREG_BF(name,value)                   (((value) & ((1 << SYSREG_##name##_SIZE) - 1)) << SYSREG_##name##_OFFSET)
-#define SYSREG_BFEXT(name,value)                (((value) >> SYSREG_##name##_OFFSET) & ((1 << SYSREG_##name##_SIZE) - 1))
-#define SYSREG_BFINS(name,value,old)            (((old) & ~(((1 << SYSREG_##name##_SIZE) - 1) << SYSREG_##name##_OFFSET)) | SYSREG_BF(name,value))
+#define SYSREG_BIT(name)				\
+	(1 << SYSREG_##name##_OFFSET)
+#define SYSREG_BF(name,value)				\
+	(((value) & ((1 << SYSREG_##name##_SIZE) - 1))	\
+	 << SYSREG_##name##_OFFSET)
+#define SYSREG_BFEXT(name,value)\
+	(((value) >> SYSREG_##name##_OFFSET)		\
+	 & ((1 << SYSREG_##name##_SIZE) - 1))
+#define SYSREG_BFINS(name,value,old)			\
+	(((old) & ~(((1 << SYSREG_##name##_SIZE) - 1)	\
+		    << SYSREG_##name##_OFFSET))		\
+	 | SYSREG_BF(name,value))
 
+/* Register access macros */
 #ifdef __CHECKER__
 extern unsigned long __builtin_mfsr(unsigned long reg);
 extern void __builtin_mtsr(unsigned long reg, unsigned long value);
 #endif
 
-/* Register access macros */
-#define sysreg_read(reg)                        __builtin_mfsr(SYSREG_##reg)
-#define sysreg_write(reg, value)                __builtin_mtsr(SYSREG_##reg, value)
+#define sysreg_read(reg)		__builtin_mfsr(SYSREG_##reg)
+#define sysreg_write(reg, value)	__builtin_mtsr(SYSREG_##reg, value)
 
-#endif /* __ASM_AVR32_SYSREG_H__ */
+#endif /* __ASM_AVR32_SYSREG_H */
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-avr32/system.h avr32-git/include/asm-avr32/system.h
--- linux-2.6.21.3/include/asm-avr32/system.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-avr32/system.h	2007-06-06 11:34:11.000000000 +0200
@@ -9,6 +9,7 @@
 #define __ASM_AVR32_SYSTEM_H
 
 #include <linux/compiler.h>
+#include <linux/linkage.h>
 #include <linux/types.h>
 
 #include <asm/ptrace.h>
@@ -140,15 +141,9 @@
 				   sizeof(*(ptr))))
 
 struct pt_regs;
-extern void __die(const char *, struct pt_regs *, unsigned long,
-		  const char *, const char *, unsigned long);
-extern void __die_if_kernel(const char *, struct pt_regs *, unsigned long,
-			    const char *, const char *, unsigned long);
-
-#define die(msg, regs, err)					\
-	__die(msg, regs, err, __FILE__ ":", __FUNCTION__, __LINE__)
-#define die_if_kernel(msg, regs, err)					\
-	__die_if_kernel(msg, regs, err, __FILE__ ":", __FUNCTION__, __LINE__)
+void NORET_TYPE die(const char *str, struct pt_regs *regs, long err);
+void _exception(long signr, struct pt_regs *regs, int code,
+		unsigned long addr);
 
 #define arch_align_stack(x)	(x)
 
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-avr32/thread_info.h avr32-git/include/asm-avr32/thread_info.h
--- linux-2.6.21.3/include/asm-avr32/thread_info.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-avr32/thread_info.h	2007-06-06 11:34:11.000000000 +0200
@@ -83,6 +83,7 @@
 #define TIF_SINGLE_STEP		6	/* single step after next break */
 #define TIF_MEMDIE		7
 #define TIF_RESTORE_SIGMASK	8	/* restore signal mask in do_signal */
+#define TIF_CPU_GOING_TO_SLEEP	9	/* CPU is entering sleep 0 mode */
 #define TIF_USERSPACE		31      /* true if FS sets userspace */
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
@@ -94,6 +95,7 @@
 #define _TIF_SINGLE_STEP	(1 << TIF_SINGLE_STEP)
 #define _TIF_MEMDIE		(1 << TIF_MEMDIE)
 #define _TIF_RESTORE_SIGMASK	(1 << TIF_RESTORE_SIGMASK)
+#define _TIF_CPU_GOING_TO_SLEEP (1 << TIF_CPU_GOING_TO_SLEEP)
 
 /* XXX: These two masks must never span more than 16 bits! */
 /* work to do on interrupt/exception return */
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-avr32/uaccess.h avr32-git/include/asm-avr32/uaccess.h
--- linux-2.6.21.3/include/asm-avr32/uaccess.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-avr32/uaccess.h	2007-06-06 11:34:11.000000000 +0200
@@ -181,24 +181,23 @@
 
 #define __get_user_nocheck(x, ptr, size)				\
 ({									\
-	typeof(*(ptr)) __gu_val = (typeof(*(ptr)) __force)0;		\
+	unsigned long __gu_val = 0;					\
 	int __gu_err = 0;						\
 									\
 	switch (size) {							\
 	case 1: __get_user_asm("ub", __gu_val, ptr, __gu_err); break;	\
 	case 2: __get_user_asm("uh", __gu_val, ptr, __gu_err); break;	\
 	case 4: __get_user_asm("w", __gu_val, ptr, __gu_err); break;	\
-	case 8: __get_user_asm("d", __gu_val, ptr, __gu_err); break;	\
 	default: __gu_err = __get_user_bad(); break;			\
 	}								\
 									\
-	x = __gu_val;							\
+	x = (typeof(*(ptr)))__gu_val;					\
 	__gu_err;							\
 })
 
 #define __get_user_check(x, ptr, size)					\
 ({									\
-	typeof(*(ptr)) __gu_val = (typeof(*(ptr)) __force)0;		\
+	unsigned long __gu_val = 0;					\
 	const typeof(*(ptr)) __user * __gu_addr = (ptr);		\
 	int __gu_err = 0;						\
 									\
@@ -216,10 +215,6 @@
 			__get_user_asm("w", __gu_val, __gu_addr,	\
 				       __gu_err);			\
 			break;						\
-		case 8:							\
-			__get_user_asm("d", __gu_val, __gu_addr,	\
-				       __gu_err);			\
-			break;						\
 		default:						\
 			__gu_err = __get_user_bad();			\
 			break;						\
@@ -227,7 +222,7 @@
 	} else {							\
 		__gu_err = -EFAULT;					\
 	}								\
-	x = __gu_val;							\
+	x = (typeof(*(ptr)))__gu_val;					\
 	__gu_err;							\
 })
 
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-avr32/unaligned.h avr32-git/include/asm-avr32/unaligned.h
--- linux-2.6.21.3/include/asm-avr32/unaligned.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-avr32/unaligned.h	2007-06-06 11:34:11.000000000 +0200
@@ -6,20 +6,31 @@
  * implementation.  The AVR32 AP implementation can handle unaligned
  * words, but halfwords must be halfword-aligned, and doublewords must
  * be word-aligned.
- *
- * TODO: Make all this CPU-specific and optimize.
  */
 
-#include <linux/string.h>
+#include <asm-generic/unaligned.h>
 
-/* Use memmove here, so gcc does not insert a __builtin_memcpy. */
+#ifdef CONFIG_CPU_AT32AP7000
 
+/* REVISIT calling memmove() may be smaller for 64-bit values ... */
+
+#undef get_unaligned
 #define get_unaligned(ptr) \
-  ({ __typeof__(*(ptr)) __tmp; memmove(&__tmp, (ptr), sizeof(*(ptr))); __tmp; })
+	___get_unaligned(ptr, sizeof((*ptr)))
+#define ___get_unaligned(ptr, size) \
+	((size == 4) ? *(ptr) : __get_unaligned(ptr, size))
+
+#undef put_unaligned
+#define put_unaligned(val, ptr) \
+	___put_unaligned((__u64)(val), ptr, sizeof((*ptr)))
+#define ___put_unaligned(val, ptr, size)		\
+do {							\
+	if (size == 4)					\
+		*(ptr) = (val);				\
+	else						\
+		__put_unaligned(val, ptr, size);	\
+} while (0)
 
-#define put_unaligned(val, ptr)				\
-  ({ __typeof__(*(ptr)) __tmp = (val);			\
-     memmove((ptr), &__tmp, sizeof(*(ptr)));		\
-     (void)0; })
+#endif
 
 #endif /* __ASM_AVR32_UNALIGNED_H */
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-frv/pgtable.h avr32-git/include/asm-frv/pgtable.h
--- linux-2.6.21.3/include/asm-frv/pgtable.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-frv/pgtable.h	2007-06-06 11:34:11.000000000 +0200
@@ -509,10 +509,6 @@
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)		\
 		remap_pfn_range(vma, vaddr, pfn, size, prot)
 
-#define MK_IOSPACE_PFN(space, pfn)	(pfn)
-#define GET_IOSPACE(pfn)		0
-#define GET_PFN(pfn)			(pfn)
-
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-frv/scatterlist.h avr32-git/include/asm-frv/scatterlist.h
--- linux-2.6.21.3/include/asm-frv/scatterlist.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-frv/scatterlist.h	2007-06-06 11:34:11.000000000 +0200
@@ -1,6 +1,8 @@
 #ifndef _ASM_SCATTERLIST_H
 #define _ASM_SCATTERLIST_H
 
+#include <asm/types.h>
+
 /*
  * Drivers must set either ->address or (preferred) ->page and ->offset
  * to indicate where data must be transferred to/from.
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-h8300/pgtable.h avr32-git/include/asm-h8300/pgtable.h
--- linux-2.6.21.3/include/asm-h8300/pgtable.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-h8300/pgtable.h	2007-06-06 11:34:12.000000000 +0200
@@ -55,10 +55,6 @@
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)		\
 		remap_pfn_range(vma, vaddr, pfn, size, prot)
 
-#define MK_IOSPACE_PFN(space, pfn)	(pfn)
-#define GET_IOSPACE(pfn)		0
-#define GET_PFN(pfn)			(pfn)
-
 /*
  * All 32bit addresses are effectively valid for vmalloc...
  * Sort of meaningless for non-VM targets.
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-h8300/scatterlist.h avr32-git/include/asm-h8300/scatterlist.h
--- linux-2.6.21.3/include/asm-h8300/scatterlist.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-h8300/scatterlist.h	2007-06-06 11:34:12.000000000 +0200
@@ -1,6 +1,8 @@
 #ifndef _H8300_SCATTERLIST_H
 #define _H8300_SCATTERLIST_H
 
+#include <asm/types.h>
+
 struct scatterlist {
 	struct page	*page;
 	unsigned int	offset;
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-i386/pgtable.h avr32-git/include/asm-i386/pgtable.h
--- linux-2.6.21.3/include/asm-i386/pgtable.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-i386/pgtable.h	2007-06-06 11:34:12.000000000 +0200
@@ -519,10 +519,6 @@
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)		\
 		remap_pfn_range(vma, vaddr, pfn, size, prot)
 
-#define MK_IOSPACE_PFN(space, pfn)	(pfn)
-#define GET_IOSPACE(pfn)		0
-#define GET_PFN(pfn)			(pfn)
-
 #include <asm-generic/pgtable.h>
 
 #endif /* _I386_PGTABLE_H */
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-i386/scatterlist.h avr32-git/include/asm-i386/scatterlist.h
--- linux-2.6.21.3/include/asm-i386/scatterlist.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-i386/scatterlist.h	2007-06-06 11:34:12.000000000 +0200
@@ -1,6 +1,8 @@
 #ifndef _I386_SCATTERLIST_H
 #define _I386_SCATTERLIST_H
 
+#include <asm/types.h>
+
 struct scatterlist {
     struct page		*page;
     unsigned int	offset;
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-ia64/pgtable.h avr32-git/include/asm-ia64/pgtable.h
--- linux-2.6.21.3/include/asm-ia64/pgtable.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-ia64/pgtable.h	2007-06-06 11:34:12.000000000 +0200
@@ -485,10 +485,6 @@
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)		\
 		remap_pfn_range(vma, vaddr, pfn, size, prot)
 
-#define MK_IOSPACE_PFN(space, pfn)	(pfn)
-#define GET_IOSPACE(pfn)		0
-#define GET_PFN(pfn)			(pfn)
-
 /*
  * ZERO_PAGE is a global shared page that is always zero: used
  * for zero-mapped memory areas etc..
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-ia64/scatterlist.h avr32-git/include/asm-ia64/scatterlist.h
--- linux-2.6.21.3/include/asm-ia64/scatterlist.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-ia64/scatterlist.h	2007-06-06 11:34:12.000000000 +0200
@@ -6,6 +6,8 @@
  *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
+#include <asm/types.h>
+
 struct scatterlist {
 	struct page *page;
 	unsigned int offset;
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-m32r/pgtable.h avr32-git/include/asm-m32r/pgtable.h
--- linux-2.6.21.3/include/asm-m32r/pgtable.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-m32r/pgtable.h	2007-06-06 11:34:12.000000000 +0200
@@ -381,10 +381,6 @@
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)	\
 		remap_pfn_range(vma, vaddr, pfn, size, prot)
 
-#define MK_IOSPACE_PFN(space, pfn)	(pfn)
-#define GET_IOSPACE(pfn)		0
-#define GET_PFN(pfn)			(pfn)
-
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-m32r/scatterlist.h avr32-git/include/asm-m32r/scatterlist.h
--- linux-2.6.21.3/include/asm-m32r/scatterlist.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-m32r/scatterlist.h	2007-06-06 11:34:12.000000000 +0200
@@ -1,6 +1,8 @@
 #ifndef _ASM_M32R_SCATTERLIST_H
 #define _ASM_M32R_SCATTERLIST_H
 
+#include <asm/types.h>
+
 struct scatterlist {
     char *  address;    /* Location data is to be transferred to, NULL for
                          * highmem page */
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-m68k/pgtable.h avr32-git/include/asm-m68k/pgtable.h
--- linux-2.6.21.3/include/asm-m68k/pgtable.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-m68k/pgtable.h	2007-06-06 11:34:12.000000000 +0200
@@ -143,10 +143,6 @@
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)		\
 		remap_pfn_range(vma, vaddr, pfn, size, prot)
 
-#define MK_IOSPACE_PFN(space, pfn)	(pfn)
-#define GET_IOSPACE(pfn)		0
-#define GET_PFN(pfn)			(pfn)
-
 /* MMU-specific headers */
 
 #ifdef CONFIG_SUN3
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-m68knommu/pgtable.h avr32-git/include/asm-m68knommu/pgtable.h
--- linux-2.6.21.3/include/asm-m68knommu/pgtable.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-m68knommu/pgtable.h	2007-06-06 11:34:12.000000000 +0200
@@ -59,10 +59,6 @@
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)		\
 		remap_pfn_range(vma, vaddr, pfn, size, prot)
 
-#define MK_IOSPACE_PFN(space, pfn)	(pfn)
-#define GET_IOSPACE(pfn)		0
-#define GET_PFN(pfn)			(pfn)
-
 /*
  * All 32bit addresses are effectively valid for vmalloc...
  * Sort of meaningless for non-VM targets.
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-m68knommu/scatterlist.h avr32-git/include/asm-m68knommu/scatterlist.h
--- linux-2.6.21.3/include/asm-m68knommu/scatterlist.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-m68knommu/scatterlist.h	2007-06-06 11:34:12.000000000 +0200
@@ -2,6 +2,7 @@
 #define _M68KNOMMU_SCATTERLIST_H
 
 #include <linux/mm.h>
+#include <asm/types.h>
 
 struct scatterlist {
 	struct page	*page;
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-mips/pgtable.h avr32-git/include/asm-mips/pgtable.h
--- linux-2.6.21.3/include/asm-mips/pgtable.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-mips/pgtable.h	2007-06-06 11:34:12.000000000 +0200
@@ -387,10 +387,6 @@
 		remap_pfn_range(vma, vaddr, pfn, size, prot)
 #endif
 
-#define MK_IOSPACE_PFN(space, pfn)	(pfn)
-#define GET_IOSPACE(pfn)		0
-#define GET_PFN(pfn)			(pfn)
-
 #include <asm-generic/pgtable.h>
 
 /*
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-mips/scatterlist.h avr32-git/include/asm-mips/scatterlist.h
--- linux-2.6.21.3/include/asm-mips/scatterlist.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-mips/scatterlist.h	2007-06-06 11:34:12.000000000 +0200
@@ -1,6 +1,8 @@
 #ifndef __ASM_SCATTERLIST_H
 #define __ASM_SCATTERLIST_H
 
+#include <asm/types.h>
+
 struct scatterlist {
 	struct page *	page;
 	unsigned int	offset;
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-parisc/pgtable.h avr32-git/include/asm-parisc/pgtable.h
--- linux-2.6.21.3/include/asm-parisc/pgtable.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-parisc/pgtable.h	2007-06-06 11:34:12.000000000 +0200
@@ -528,10 +528,6 @@
 
 #define pgprot_noncached(prot) __pgprot(pgprot_val(prot) | _PAGE_NO_CACHE)
 
-#define MK_IOSPACE_PFN(space, pfn)	(pfn)
-#define GET_IOSPACE(pfn)		0
-#define GET_PFN(pfn)			(pfn)
-
 /* We provide our own get_unmapped_area to provide cache coherency */
 
 #define HAVE_ARCH_UNMAPPED_AREA
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-parisc/scatterlist.h avr32-git/include/asm-parisc/scatterlist.h
--- linux-2.6.21.3/include/asm-parisc/scatterlist.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-parisc/scatterlist.h	2007-06-06 11:34:12.000000000 +0200
@@ -2,6 +2,7 @@
 #define _ASM_PARISC_SCATTERLIST_H
 
 #include <asm/page.h>
+#include <asm/types.h>
 
 struct scatterlist {
 	struct page *page;
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-ppc/pgtable.h avr32-git/include/asm-ppc/pgtable.h
--- linux-2.6.21.3/include/asm-ppc/pgtable.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-ppc/pgtable.h	2007-06-06 11:34:13.000000000 +0200
@@ -827,10 +827,6 @@
 		remap_pfn_range(vma, vaddr, pfn, size, prot)
 #endif
 
-#define MK_IOSPACE_PFN(space, pfn)	(pfn)
-#define GET_IOSPACE(pfn)		0
-#define GET_PFN(pfn)			(pfn)
-
 /*
  * No page table caches to initialise
  */
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-sh/pgtable.h avr32-git/include/asm-sh/pgtable.h
--- linux-2.6.21.3/include/asm-sh/pgtable.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-sh/pgtable.h	2007-06-06 11:34:13.000000000 +0200
@@ -568,10 +568,6 @@
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)		\
 		remap_pfn_range(vma, vaddr, pfn, size, prot)
 
-#define MK_IOSPACE_PFN(space, pfn)	(pfn)
-#define GET_IOSPACE(pfn)		0
-#define GET_PFN(pfn)			(pfn)
-
 struct mm_struct;
 
 /*
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-sh/scatterlist.h avr32-git/include/asm-sh/scatterlist.h
--- linux-2.6.21.3/include/asm-sh/scatterlist.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-sh/scatterlist.h	2007-06-06 11:34:13.000000000 +0200
@@ -1,6 +1,8 @@
 #ifndef __ASM_SH_SCATTERLIST_H
 #define __ASM_SH_SCATTERLIST_H
 
+#include <asm/types.h>
+
 struct scatterlist {
     struct page * page; /* Location for highmem page, if any */
     unsigned int offset;/* for highmem, page offset */
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-sh64/pgtable.h avr32-git/include/asm-sh64/pgtable.h
--- linux-2.6.21.3/include/asm-sh64/pgtable.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-sh64/pgtable.h	2007-06-06 11:34:13.000000000 +0200
@@ -485,10 +485,6 @@
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)		\
 		remap_pfn_range(vma, vaddr, pfn, size, prot)
 
-#define MK_IOSPACE_PFN(space, pfn)	(pfn)
-#define GET_IOSPACE(pfn)		0
-#define GET_PFN(pfn)			(pfn)
-
 #endif /* !__ASSEMBLY__ */
 
 /*
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-sh64/scatterlist.h avr32-git/include/asm-sh64/scatterlist.h
--- linux-2.6.21.3/include/asm-sh64/scatterlist.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-sh64/scatterlist.h	2007-06-06 11:34:13.000000000 +0200
@@ -11,6 +11,8 @@
 #ifndef __ASM_SH64_SCATTERLIST_H
 #define __ASM_SH64_SCATTERLIST_H
 
+#include <asm/types.h>
+
 struct scatterlist {
     struct page * page; /* Location for highmem page, if any */
     unsigned int offset;/* for highmem, page offset */
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-sparc64/scatterlist.h avr32-git/include/asm-sparc64/scatterlist.h
--- linux-2.6.21.3/include/asm-sparc64/scatterlist.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-sparc64/scatterlist.h	2007-06-06 11:34:13.000000000 +0200
@@ -3,6 +3,7 @@
 #define _SPARC64_SCATTERLIST_H
 
 #include <asm/page.h>
+#include <asm/types.h>
 
 struct scatterlist {
 	struct page	*page;
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-v850/scatterlist.h avr32-git/include/asm-v850/scatterlist.h
--- linux-2.6.21.3/include/asm-v850/scatterlist.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-v850/scatterlist.h	2007-06-06 11:34:13.000000000 +0200
@@ -14,6 +14,8 @@
 #ifndef __V850_SCATTERLIST_H__
 #define __V850_SCATTERLIST_H__
 
+#include <asm/types.h>
+
 struct scatterlist {
 	struct page	*page;
 	unsigned	offset;
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-x86_64/pgtable.h avr32-git/include/asm-x86_64/pgtable.h
--- linux-2.6.21.3/include/asm-x86_64/pgtable.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-x86_64/pgtable.h	2007-06-06 11:34:13.000000000 +0200
@@ -413,10 +413,6 @@
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)		\
 		remap_pfn_range(vma, vaddr, pfn, size, prot)
 
-#define MK_IOSPACE_PFN(space, pfn)	(pfn)
-#define GET_IOSPACE(pfn)		0
-#define GET_PFN(pfn)			(pfn)
-
 #define HAVE_ARCH_UNMAPPED_AREA
 
 #define pgtable_cache_init()   do { } while (0)
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-x86_64/scatterlist.h avr32-git/include/asm-x86_64/scatterlist.h
--- linux-2.6.21.3/include/asm-x86_64/scatterlist.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-x86_64/scatterlist.h	2007-06-06 11:34:13.000000000 +0200
@@ -1,6 +1,8 @@
 #ifndef _X8664_SCATTERLIST_H
 #define _X8664_SCATTERLIST_H
 
+#include <asm/types.h>
+
 struct scatterlist {
     struct page		*page;
     unsigned int	offset;
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/asm-xtensa/scatterlist.h avr32-git/include/asm-xtensa/scatterlist.h
--- linux-2.6.21.3/include/asm-xtensa/scatterlist.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/asm-xtensa/scatterlist.h	2007-06-06 11:34:13.000000000 +0200
@@ -11,6 +11,8 @@
 #ifndef _XTENSA_SCATTERLIST_H
 #define _XTENSA_SCATTERLIST_H
 
+#include <asm/types.h>
+
 struct scatterlist {
 	struct page 	*page;
 	unsigned int	offset;
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/linux/fb.h avr32-git/include/linux/fb.h
--- linux-2.6.21.3/include/linux/fb.h	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/include/linux/fb.h	2007-06-06 11:34:13.000000000 +0200
@@ -833,7 +833,7 @@
 #define fb_writeq sbus_writeq
 #define fb_memset sbus_memset_io
 
-#elif defined(__i386__) || defined(__alpha__) || defined(__x86_64__) || defined(__hppa__) || (defined(__sh__) && !defined(__SH5__)) || defined(__powerpc__)
+#elif defined(__i386__) || defined(__alpha__) || defined(__x86_64__) || defined(__hppa__) || (defined(__sh__) && !defined(__SH5__)) || defined(__powerpc__) || defined(__avr32__)
 
 #define fb_readb __raw_readb
 #define fb_readw __raw_readw
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/linux/i2c-gpio.h avr32-git/include/linux/i2c-gpio.h
--- linux-2.6.21.3/include/linux/i2c-gpio.h	1970-01-01 01:00:00.000000000 +0100
+++ avr32-git/include/linux/i2c-gpio.h	2007-06-06 11:34:13.000000000 +0200
@@ -0,0 +1,38 @@
+/*
+ * i2c-gpio interface to platform code
+ *
+ * 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 _LINUX_I2C_GPIO_H
+#define _LINUX_I2C_GPIO_H
+
+/**
+ * struct i2c_gpio_platform_data - Platform-dependent data for i2c-gpio
+ * @sda_pin: GPIO pin ID to use for SDA
+ * @scl_pin: GPIO pin ID to use for SCL
+ * @udelay: signal toggle delay. SCL frequency is (500 / udelay) kHz
+ * @timeout: clock stretching timeout in jiffies. If the slave keeps
+ *	SCL low for longer than this, the transfer will time out.
+ * @sda_is_open_drain: SDA is configured as open drain, i.e. the pin
+ *	isn't actively driven high when setting the output value high.
+ *	gpio_get_value() must return the actual pin state even if the
+ *	pin is configured as an output.
+ * @scl_is_open_drain: SCL is set up as open drain. Same requirements
+ *	as for sda_is_open_drain apply.
+ * @scl_is_output_only: SCL output drivers cannot be turned off.
+ */
+struct i2c_gpio_platform_data {
+	unsigned int	sda_pin;
+	unsigned int	scl_pin;
+	int		udelay;
+	int		timeout;
+	unsigned int	sda_is_open_drain:1;
+	unsigned int	scl_is_open_drain:1;
+	unsigned int	scl_is_output_only:1;
+};
+
+#endif /* _LINUX_I2C_GPIO_H */
diff -Nur -x .gitignore -x .git linux-2.6.21.3/include/video/atmel_lcdc.h avr32-git/include/video/atmel_lcdc.h
--- linux-2.6.21.3/include/video/atmel_lcdc.h	1970-01-01 01:00:00.000000000 +0100
+++ avr32-git/include/video/atmel_lcdc.h	2007-06-06 11:34:13.000000000 +0200
@@ -0,0 +1,196 @@
+/*
+ *  Header file for AT91/AT32 LCD 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_LCDC_H__
+#define __ATMEL_LCDC_H__
+
+ /* LCD Controller info data structure */
+struct atmel_lcdfb_info {
+	spinlock_t		lock;
+	struct fb_info		*info;
+	void __iomem		*mmio;
+	unsigned long		irq_base;
+
+	unsigned int		guard_time;
+	struct platform_device	*pdev;
+	struct clk		*bus_clk;
+	struct clk		*lcdc_clk;
+	unsigned int		default_bpp;
+	unsigned int		default_lcdcon2;
+	unsigned int		default_dmacon;
+	void (*atmel_lcdfb_power_control)(int on);
+	struct fb_monspecs	*default_monspecs;
+	u32			pseudo_palette[16];
+};
+
+#define ATMEL_LCDC_DMABADDR1	0x00
+#define ATMEL_LCDC_DMABADDR2	0x04
+#define ATMEL_LCDC_DMAFRMPT1	0x08
+#define ATMEL_LCDC_DMAFRMPT2	0x0c
+#define ATMEL_LCDC_DMAFRMADD1	0x10
+#define ATMEL_LCDC_DMAFRMADD2	0x14
+
+#define ATMEL_LCDC_DMAFRMCFG	0x18
+#define	ATMEL_LCDC_FRSIZE	(0x7fffff <<  0)
+#define	ATMEL_LCDC_BLENGTH_OFFSET	24
+#define	ATMEL_LCDC_BLENGTH	(0x7f     << ATMEL_LCDC_BLENGTH_OFFSET)
+
+#define ATMEL_LCDC_DMACON	0x1c
+#define	ATMEL_LCDC_DMAEN	(0x1 << 0)
+#define	ATMEL_LCDC_DMARST	(0x1 << 1)
+#define	ATMEL_LCDC_DMABUSY	(0x1 << 2)
+#define		ATMEL_LCDC_DMAUPDT	(0x1 << 3)
+#define		ATMEL_LCDC_DMA2DEN	(0x1 << 4)
+
+#define ATMEL_LCDC_DMA2DCFG	0x20
+#define		ATMEL_LCDC_ADDRINC_OFFSET	0
+#define		ATMEL_LCDC_ADDRINC		(0xffff)
+#define		ATMEL_LCDC_PIXELOFF_OFFSET	24
+#define		ATMEL_LCDC_PIXELOFF		(0x1f << 24)
+
+#define ATMEL_LCDC_LCDCON1	0x0800
+#define	ATMEL_LCDC_BYPASS	(1     <<  0)
+#define	ATMEL_LCDC_CLKVAL_OFFSET	12
+#define	ATMEL_LCDC_CLKVAL	(0x1ff << ATMEL_LCDC_CLKVAL_OFFSET)
+#define	ATMEL_LCDC_LINCNT	(0x7ff << 21)
+
+#define ATMEL_LCDC_LCDCON2	0x0804
+#define	ATMEL_LCDC_DISTYPE	(3 << 0)
+#define		ATMEL_LCDC_DISTYPE_STNMONO	(0 << 0)
+#define		ATMEL_LCDC_DISTYPE_STNCOLOR	(1 << 0)
+#define		ATMEL_LCDC_DISTYPE_TFT		(2 << 0)
+#define	ATMEL_LCDC_SCANMOD	(1 << 2)
+#define		ATMEL_LCDC_SCANMOD_SINGLE	(0 << 2)
+#define		ATMEL_LCDC_SCANMOD_DUAL		(1 << 2)
+#define	ATMEL_LCDC_IFWIDTH	(3 << 3)
+#define		ATMEL_LCDC_IFWIDTH_4		(0 << 3)
+#define		ATMEL_LCDC_IFWIDTH_8		(1 << 3)
+#define		ATMEL_LCDC_IFWIDTH_16		(2 << 3)
+#define	ATMEL_LCDC_PIXELSIZE	(7 << 5)
+#define		ATMEL_LCDC_PIXELSIZE_1		(0 << 5)
+#define		ATMEL_LCDC_PIXELSIZE_2		(1 << 5)
+#define		ATMEL_LCDC_PIXELSIZE_4		(2 << 5)
+#define		ATMEL_LCDC_PIXELSIZE_8		(3 << 5)
+#define		ATMEL_LCDC_PIXELSIZE_16		(4 << 5)
+#define		ATMEL_LCDC_PIXELSIZE_24		(5 << 5)
+#define		ATMEL_LCDC_PIXELSIZE_32		(6 << 5)
+#define	ATMEL_LCDC_INVVD	(1 << 8)
+#define		ATMEL_LCDC_INVVD_NORMAL		(0 << 8)
+#define		ATMEL_LCDC_INVVD_INVERTED	(1 << 8)
+#define	ATMEL_LCDC_INVFRAME	(1 << 9 )
+#define		ATMEL_LCDC_INVFRAME_NORMAL	(0 << 9)
+#define		ATMEL_LCDC_INVFRAME_INVERTED	(1 << 9)
+#define	ATMEL_LCDC_INVLINE	(1 << 10)
+#define		ATMEL_LCDC_INVLINE_NORMAL	(0 << 10)
+#define		ATMEL_LCDC_INVLINE_INVERTED	(1 << 10)
+#define	ATMEL_LCDC_INVCLK	(1 << 11)
+#define		ATMEL_LCDC_INVCLK_NORMAL	(0 << 11)
+#define		ATMEL_LCDC_INVCLK_INVERTED	(1 << 11)
+#define	ATMEL_LCDC_INVDVAL	(1 << 12)
+#define		ATMEL_LCDC_INVDVAL_NORMAL	(0 << 12)
+#define		ATMEL_LCDC_INVDVAL_INVERTED	(1 << 12)
+#define	ATMEL_LCDC_CLKMOD	(1 << 15)
+#define		ATMEL_LCDC_CLKMOD_ACTIVEDISPLAY	(0 << 15)
+#define		ATMEL_LCDC_CLKMOD_ALWAYSACTIVE	(1 << 15)
+#define	ATMEL_LCDC_MEMOR	(1 << 31)
+#define		ATMEL_LCDC_MEMOR_BIG		(0 << 31)
+#define		ATMEL_LCDC_MEMOR_LITTLE		(1 << 31)
+
+#define ATMEL_LCDC_TIM1		0x0808
+#define	ATMEL_LCDC_VFP		(0xff <<  0)
+#define	ATMEL_LCDC_VBP_OFFSET		8
+#define	ATMEL_LCDC_VBP		(0xff <<  ATMEL_LCDC_VBP_OFFSET)
+#define	ATMEL_LCDC_VPW_OFFSET		16
+#define	ATMEL_LCDC_VPW		(0x3f << ATMEL_LCDC_VPW_OFFSET)
+#define	ATMEL_LCDC_VHDLY_OFFSET		24
+#define	ATMEL_LCDC_VHDLY	(0xf  << ATMEL_LCDC_VHDLY_OFFSET)
+
+#define ATMEL_LCDC_TIM2		0x080c
+#define	ATMEL_LCDC_HBP		(0xff  <<  0)
+#define	ATMEL_LCDC_HPW_OFFSET		8
+#define	ATMEL_LCDC_HPW		(0x3f  <<  ATMEL_LCDC_HPW_OFFSET)
+#define	ATMEL_LCDC_HFP_OFFSET		21
+#define	ATMEL_LCDC_HFP		(0x7ff << ATMEL_LCDC_HFP_OFFSET)
+
+#define ATMEL_LCDC_LCDFRMCFG	0x0810
+#define	ATMEL_LCDC_LINEVAL	(0x7ff <<  0)
+#define	ATMEL_LCDC_HOZVAL_OFFSET	21
+#define	ATMEL_LCDC_HOZVAL	(0x7ff << ATMEL_LCDC_HOZVAL_OFFSET)
+
+#define ATMEL_LCDC_FIFO		0x0814
+#define	ATMEL_LCDC_FIFOTH	(0xffff)
+
+#define ATMEL_LCDC_MVAL		0x0818
+
+#define ATMEL_LCDC_DP1_2	0x081c
+#define ATMEL_LCDC_DP4_7	0x0820
+#define ATMEL_LCDC_DP3_5	0x0824
+#define ATMEL_LCDC_DP2_3	0x0828
+#define ATMEL_LCDC_DP5_7	0x082c
+#define ATMEL_LCDC_DP3_4	0x0830
+#define ATMEL_LCDC_DP4_5	0x0834
+#define ATMEL_LCDC_DP6_7	0x0838
+#define	ATMEL_LCDC_DP1_2_VAL	(0xff)
+#define	ATMEL_LCDC_DP4_7_VAL	(0xfffffff)
+#define	ATMEL_LCDC_DP3_5_VAL	(0xfffff)
+#define	ATMEL_LCDC_DP2_3_VAL	(0xfff)
+#define	ATMEL_LCDC_DP5_7_VAL	(0xfffffff)
+#define	ATMEL_LCDC_DP3_4_VAL	(0xffff)
+#define	ATMEL_LCDC_DP4_5_VAL	(0xfffff)
+#define	ATMEL_LCDC_DP6_7_VAL	(0xfffffff)
+
+#define ATMEL_LCDC_PWRCON	0x083c
+#define	ATMEL_LCDC_PWR		(1    <<  0)
+#define	ATMEL_LCDC_GUARDT_OFFSET	1
+#define	ATMEL_LCDC_GUARDT	(0x7f <<  ATMEL_LCDC_GUARDT_OFFSET)
+#define	ATMEL_LCDC_BUSY		(1    << 31)
+
+#define ATMEL_LCDC_CONTRAST_CTR	0x0840
+#define	ATMEL_LCDC_PS		(3 << 0)
+#define		ATMEL_LCDC_PS_DIV1		(0 << 0)
+#define		ATMEL_LCDC_PS_DIV2		(1 << 0)
+#define		ATMEL_LCDC_PS_DIV4		(2 << 0)
+#define		ATMEL_LCDC_PS_DIV8		(3 << 0)
+#define	ATMEL_LCDC_POL		(1 << 2)
+#define		ATMEL_LCDC_POL_NEGATIVE		(0 << 2)
+#define		ATMEL_LCDC_POL_POSITIVE		(1 << 2)
+#define	ATMEL_LCDC_ENA		(1 << 3)
+#define		ATMEL_LCDC_ENA_PWMDISABLE	(0 << 3)
+#define		ATMEL_LCDC_ENA_PWMENABLE	(1 << 3)
+
+#define ATMEL_LCDC_CONTRAST_VAL	0x0844
+#define	ATMEL_LCDC_CVAL	(0xff)
+
+#define ATMEL_LCDC_IER		0x0848
+#define ATMEL_LCDC_IDR		0x084c
+#define ATMEL_LCDC_IMR		0x0850
+#define ATMEL_LCDC_ISR		0x0854
+#define ATMEL_LCDC_ICR		0x0858
+#define	ATMEL_LCDC_LNI		(1 << 0)
+#define	ATMEL_LCDC_LSTLNI	(1 << 1)
+#define	ATMEL_LCDC_EOFI		(1 << 2)
+#define	ATMEL_LCDC_UFLWI	(1 << 4)
+#define	ATMEL_LCDC_OWRI		(1 << 5)
+#define	ATMEL_LCDC_MERI		(1 << 6)
+
+#define ATMEL_LCDC_LUT(n)	(0x0c00 + ((n)*4))
+
+#endif /* __ATMEL_LCDC_H__ */
diff -Nur -x .gitignore -x .git linux-2.6.21.3/MAINTAINERS avr32-git/MAINTAINERS
--- linux-2.6.21.3/MAINTAINERS	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/MAINTAINERS	2007-06-06 11:33:46.000000000 +0200
@@ -1434,6 +1434,11 @@
 W:	http://www.icp-vortex.com/
 S:	Supported
 
+GENERIC GPIO I2C DRIVER
+P:	Haavard Skinnemoen
+M:	hskinnemoen@atmel.com
+S:	Supported
+
 GENERIC HDLC DRIVER, N2, C101, PCI200SYN and WANXL DRIVERS
 P:	Krzysztof Halasa
 M:	khc@pm.waw.pl
diff -Nur -x .gitignore -x .git linux-2.6.21.3/scripts/checkstack.pl avr32-git/scripts/checkstack.pl
--- linux-2.6.21.3/scripts/checkstack.pl	2007-05-24 23:22:47.000000000 +0200
+++ avr32-git/scripts/checkstack.pl	2007-06-06 11:34:14.000000000 +0200
@@ -12,6 +12,7 @@
 #	sh64 port by Paul Mundt
 #	Random bits by Matt Mackall <mpm@selenic.com>
 #	M68k port by Geert Uytterhoeven and Andreas Schwab
+#	AVR32 port by Haavard Skinnemoen <hskinnemoen@atmel.com>
 #
 #	Usage:
 #	objdump -d vmlinux | stackcheck.pl [arch]
@@ -37,6 +38,10 @@
 	if ($arch eq 'arm') {
 		#c0008ffc:	e24dd064	sub	sp, sp, #100	; 0x64
 		$re = qr/.*sub.*sp, sp, #(([0-9]{2}|[3-9])[0-9]{2})/o;
+	} elsif ($arch eq 'avr32') {
+		#8000008a:       20 1d           sub sp,4
+		#80000ca8:       fa cd 05 b0     sub sp,sp,1456
+		$re = qr/^.*sub.*sp.*,([0-9]{1,8})/o;
 	} elsif ($arch =~ /^i[3456]86$/) {
 		#c0105234:       81 ec ac 05 00 00       sub    $0x5ac,%esp
 		$re = qr/^.*[as][du][db]    \$(0x$x{1,8}),\%esp$/o;
