-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,
+diff -x .git -Nur linux-2.6.22.1/arch/avr32/boards/atngw100/setup.c linux-avr32.git/arch/avr32/boards/atngw100/setup.c
+--- linux-2.6.22.1/arch/avr32/boards/atngw100/setup.c 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/arch/avr32/boards/atngw100/setup.c 2007-07-12 13:59:49.000000000 +0200
+@@ -13,6 +13,7 @@
+ #include <linux/linkage.h>
+ #include <linux/platform_device.h>
+ #include <linux/types.h>
++#include <linux/leds.h>
+ #include <linux/spi/spi.h>
+
+ #include <asm/io.h>
+@@ -21,6 +22,7 @@
+ #include <asm/arch/at32ap7000.h>
+ #include <asm/arch/board.h>
+ #include <asm/arch/init.h>
++#include <asm/arch/portmux.h>
+
+ /* Initialized by bootloader-specific startup code. */
+ struct tag *bootloader_tags __initdata;
+@@ -39,6 +41,11 @@
+ },
+ };
+
++static struct mci_platform_data __initdata mci0_data = {
++ .detect_pin = GPIO_PIN_PC(25),
++ .wp_pin = GPIO_PIN_PE(0),
+};
+
-+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,
+ /*
+ * The next two functions should go away as the boot loader is
+ * supposed to initialize the macb address registers with a valid
+@@ -100,8 +107,31 @@
+ at32_setup_serial_console(0);
+ }
+
++static const struct gpio_led ngw_leds[] = {
++ { .name = "sys", .gpio = GPIO_PIN_PA(16), .active_low = 1,
++ .default_trigger = "heartbeat",
+ },
++ { .name = "a", .gpio = GPIO_PIN_PA(19), .active_low = 1, },
++ { .name = "b", .gpio = GPIO_PIN_PE(19), .active_low = 1, },
++};
++
++static const struct gpio_led_platform_data ngw_led_data = {
++ .num_leds = ARRAY_SIZE(ngw_leds),
++ .leds = (void *) ngw_leds,
++};
++
++static struct platform_device ngw_gpio_leds = {
++ .name = "leds-gpio",
++ .id = -1,
++ .dev = {
++ .platform_data = (void *) &ngw_led_data,
++ }
+};
+
-+static struct physmap_flash_data flash_data = {
-+ .width = 2,
-+ .nr_parts = ARRAY_SIZE(flash_parts),
-+ .parts = flash_parts,
+ static int __init atngw100_init(void)
+ {
++ unsigned i;
++
+ /*
+ * ATNGW100 uses 16-bit SDRAM interface, so we don't need to
+ * reserve any pins for it.
+@@ -115,6 +145,14 @@
+ set_hw_addr(at32_add_device_eth(1, ð_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, NULL);
++
++ for (i = 0; i < ARRAY_SIZE(ngw_leds); i++) {
++ at32_select_gpio(ngw_leds[i].gpio,
++ AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH);
++ }
++ platform_device_register(&ngw_gpio_leds);
+
+ return 0;
+ }
+diff -x .git -Nur linux-2.6.22.1/arch/avr32/boards/atstk1000/atstk1002.c linux-avr32.git/arch/avr32/boards/atstk1000/atstk1002.c
+--- linux-2.6.22.1/arch/avr32/boards/atstk1000/atstk1002.c 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/arch/avr32/boards/atstk1000/atstk1002.c 2007-07-12 13:59:49.000000000 +0200
+@@ -11,6 +11,7 @@
+ #include <linux/etherdevice.h>
+ #include <linux/init.h>
+ #include <linux/kernel.h>
++#include <linux/leds.h>
+ #include <linux/platform_device.h>
+ #include <linux/string.h>
+ #include <linux/types.h>
+@@ -27,7 +28,6 @@
+
+ #include "atstk1000.h"
+
+-#define SW2_DEFAULT /* MMCI and UART_A available */
+
+ struct eth_addr {
+ u8 addr[6];
+@@ -36,6 +36,7 @@
+ static struct eth_addr __initdata hw_addr[2];
+ static struct eth_platform_data __initdata eth_data[2];
+
++#ifndef CONFIG_BOARD_ATSTK1002_SW1_CUSTOM
+ static struct spi_board_info spi0_board_info[] __initdata = {
+ {
+ /* QVGA display */
+@@ -45,6 +46,18 @@
+ .mode = SPI_MODE_3,
+ },
+ };
++#endif
++
++#ifdef CONFIG_BOARD_ATSTK1002_SPI1
++static struct spi_board_info spi1_board_info[] __initdata = { {
++ /* patch in custom entries here */
++} };
++#endif
++
++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
+@@ -101,12 +114,71 @@
+ clk_put(pclk);
+ }
+
+-void __init setup_board(void)
++#ifdef CONFIG_BOARD_ATSTK1002_J2_LED
++
++static struct gpio_led stk_j2_led[] = {
++#ifdef CONFIG_BOARD_ATSTK1002_J2_LED8
++#define LEDSTRING "J2 jumpered to LED8"
++ { .name = "led0:amber", .gpio = GPIO_PIN_PB( 8), },
++ { .name = "led1:amber", .gpio = GPIO_PIN_PB( 9), },
++ { .name = "led2:amber", .gpio = GPIO_PIN_PB(10), },
++ { .name = "led3:amber", .gpio = GPIO_PIN_PB(13), },
++ { .name = "led4:amber", .gpio = GPIO_PIN_PB(14), },
++ { .name = "led5:amber", .gpio = GPIO_PIN_PB(15), },
++ { .name = "led6:amber", .gpio = GPIO_PIN_PB(16), },
++ { .name = "led7:amber", .gpio = GPIO_PIN_PB(30),
++ .default_trigger = "heartbeat", },
++#else /* RGB */
++#define LEDSTRING "J2 jumpered to RGB LEDs"
++ { .name = "r1:red", .gpio = GPIO_PIN_PB( 8), },
++ { .name = "g1:green", .gpio = GPIO_PIN_PB(10), },
++ { .name = "b1:blue", .gpio = GPIO_PIN_PB(14), },
++
++ { .name = "r2:red", .gpio = GPIO_PIN_PB( 9),
++ .default_trigger = "heartbeat", },
++ { .name = "g2:green", .gpio = GPIO_PIN_PB(13), },
++ { .name = "b2:blue", .gpio = GPIO_PIN_PB(15),
++ .default_trigger = "heartbeat", },
++ /* PB16, PB30 unused */
++#endif
+};
+
-+static struct resource flash_resource = {
-+ .start = 0x00000000,
-+ .end = 0x007fffff,
-+ .flags = IORESOURCE_MEM,
++static struct gpio_led_platform_data stk_j2_led_data = {
++ .num_leds = ARRAY_SIZE(stk_j2_led),
++ .leds = stk_j2_led,
+};
+
-+static struct platform_device flash_device = {
-+ .name = "physmap-flash",
-+ .id = 0,
-+ .resource = &flash_resource,
-+ .num_resources = 1,
++static struct platform_device stk_j2_led_dev = {
++ .name = "leds-gpio",
++ .id = 2, /* gpio block J2 */
+ .dev = {
-+ .platform_data = &flash_data,
++ .platform_data = &stk_j2_led_data,
+ },
+};
+
-+/* This needs to be called after the SMC has been initialized */
-+static int __init atngw100_flash_init(void)
-+{
-+ int ret;
++static void setup_j2_leds(void)
+ {
+-#ifdef SW2_DEFAULT
+- at32_map_usart(1, 0); /* USART 1/A: /dev/ttyS0, DB9 */
++ unsigned i;
+
-+ ret = smc_set_configuration(0, &flash_config);
-+ if (ret < 0) {
-+ printk(KERN_ERR "atngw100: failed to set NOR flash timing\n");
-+ return ret;
-+ }
++ for (i = 0; i < ARRAY_SIZE(stk_j2_led); i++)
++ at32_select_gpio(stk_j2_led[i].gpio, AT32_GPIOF_OUTPUT);
+
-+ platform_device_register(&flash_device);
++ printk("STK1002: " LEDSTRING "\n");
++ platform_device_register(&stk_j2_led_dev);
++}
+
-+ return 0;
+ #else
++static void setup_j2_leds(void)
++{
+}
-+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>
++#endif
+
-+#include <asm/io.h>
-+#include <asm/setup.h>
++void __init setup_board(void)
++{
++#ifdef CONFIG_BOARD_ATSTK1002_SW2_CUSTOM
+ at32_map_usart(0, 1); /* USART 0/B: /dev/ttyS1, IRDA */
++#else
++ at32_map_usart(1, 0); /* USART 1/A: /dev/ttyS0, DB9 */
+ #endif
+ /* USART 2/unused: expansion connector */
+ at32_map_usart(3, 2); /* USART 3/C: /dev/ttyS2, DB9 */
+@@ -140,18 +212,40 @@
+
+ at32_add_system_devices();
+
+-#ifdef SW2_DEFAULT
+- at32_add_device_usart(0);
+-#else
++#ifdef CONFIG_BOARD_ATSTK1002_SW2_CUSTOM
+ at32_add_device_usart(1);
++#else
++ at32_add_device_usart(0);
+ #endif
+ at32_add_device_usart(2);
+
++#ifndef CONFIG_BOARD_ATSTK1002_SW6_CUSTOM
+ set_hw_addr(at32_add_device_eth(0, ð_data[0]));
+-
+- at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info));
++#endif
++#ifdef CONFIG_BOARD_ATSTK1002_SW5_CUSTOM
++ set_hw_addr(at32_add_device_eth(1, ð_data[1]));
++#else
+ at32_add_device_lcdc(0, &atstk1000_lcdc_data,
+ fbmem_start, fbmem_size);
++#endif
+
-+#include <asm/arch/at32ap7000.h>
-+#include <asm/arch/board.h>
-+#include <asm/arch/init.h>
++#ifndef CONFIG_BOARD_ATSTK1002_SW1_CUSTOM
++ at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info));
++#endif
++#ifdef CONFIG_BOARD_ATSTK1002_SPI1
++ at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
++#endif
++ at32_add_device_twi(0);
++#ifndef CONFIG_BOARD_ATSTK1002_SW2_CUSTOM
++ at32_add_device_mci(0, &mci0_data);
++#endif
++ at32_add_device_usba(0, NULL);
++ at32_add_device_abdac(0);
++#ifndef CONFIG_BOARD_ATSTK1002_SW3_CUSTOM
++ at32_add_device_ssc(0, ATMEL_SSC_TX);
++#endif
+
-+/* Initialized by bootloader-specific startup code. */
-+struct tag *bootloader_tags __initdata;
++ setup_j2_leds();
+
+ return 0;
+ }
+diff -x .git -Nur linux-2.6.22.1/arch/avr32/boards/atstk1000/Kconfig linux-avr32.git/arch/avr32/boards/atstk1000/Kconfig
+--- linux-2.6.22.1/arch/avr32/boards/atstk1000/Kconfig 1970-01-01 01:00:00.000000000 +0100
++++ linux-avr32.git/arch/avr32/boards/atstk1000/Kconfig 2007-07-12 13:59:49.000000000 +0200
+@@ -0,0 +1,79 @@
++# STK1000 customization
+
-+struct eth_addr {
-+ u8 addr[6];
-+};
-+static struct eth_addr __initdata hw_addr[2];
-+static struct eth_platform_data __initdata eth_data[2];
++if BOARD_ATSTK1002
+
-+static struct spi_board_info spi0_board_info[] __initdata = {
-+ {
-+ .modalias = "mtd_dataflash",
-+ .max_speed_hz = 10000000,
-+ .chip_select = 0,
-+ },
-+};
++config BOARD_ATSTK1002_CUSTOM
++ bool "Non-default STK-1002 jumper settings"
++ help
++ You will normally leave the jumpers on the CPU card at their
++ default settings. If you need to use certain peripherals,
++ you will need to change some of those jumpers.
+
-+static struct mci_platform_data __initdata mci0_data = {
-+ .detect_pin = GPIO_PIN_PC(25),
-+ .wp_pin = GPIO_PIN_PE(0),
-+};
++if BOARD_ATSTK1002_CUSTOM
+
-+/*
-+ * 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;
++config BOARD_ATSTK1002_SW1_CUSTOM
++ bool "SW1: use SSC1 (not SPI0)"
++ help
++ This also prevents using the external DAC as an audio interface,
++ and means you can't initialize the on-board QVGA display.
+
-+ 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));
++config BOARD_ATSTK1002_SW2_CUSTOM
++ bool "SW2: use IRDA or TIMER0 (not UART-A, MMC/SD, and PS2-A)"
++ help
++ If you change this you'll want an updated boot loader putting
++ the console on UART-C not UART-A.
+
-+ return 0;
-+}
-+__tagtable(ATAG_ETHERNET, parse_tag_ethernet);
++config BOARD_ATSTK1002_SW3_CUSTOM
++ bool "SW3: use TIMER1 (not SSC0 and GCLK)"
++ help
++ This also prevents using the external DAC as an audio interface.
+
-+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;
++config BOARD_ATSTK1002_SW4_CUSTOM
++ bool "SW4: use ISI/Camera (not GPIOs, SPI1, and PS2-B)"
++ help
++ To use the camera interface you'll need a custom card (on the
++ PCI-format connector) connect a video sensor.
+
-+ if (!res)
-+ return;
-+ if (pdev->id >= ARRAY_SIZE(hw_addr))
-+ return;
++config BOARD_ATSTK1002_SW5_CUSTOM
++ bool "SW5: use MACB1 (not LCDC)"
+
-+ addr = hw_addr[pdev->id].addr;
-+ if (!is_valid_ether_addr(addr))
-+ return;
++config BOARD_ATSTK1002_SW6_CUSTOM
++ bool "SW6: more GPIOs (not MACB0)"
+
-+ /*
-+ * 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;
++endif # custom
+
-+ 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);
-+}
++config BOARD_ATSTK1002_SPI1
++ bool "Configure SPI1 controller"
++ depends on !BOARD_ATSTK1002_SW4_CUSTOM
++ help
++ All the signals for the second SPI controller are available on
++ GPIO lines and accessed through the J1 jumper block. Say "y"
++ here to configure that SPI controller.
+
-+struct platform_device *at32_usart_map[1];
-+unsigned int at32_nr_usarts = 1;
++config BOARD_ATSTK1002_J2_LED
++ bool
++ default BOARD_ATSTK1002_J2_LED8 || BOARD_ATSTK1002_J2_RGB
+
-+void __init setup_board(void)
-+{
-+ at32_map_usart(1, 0); /* USART 1: /dev/ttyS0, DB9 */
-+ at32_setup_serial_console(0);
-+}
++choice
++ prompt "LEDs connected to J2:"
++ depends on LEDS_GPIO && !BOARD_ATSTK1002_SW4_CUSTOM
++ optional
++ help
++ Select this if you have jumpered the J2 jumper block to the
++ LED0..LED7 amber leds, or to the RGB leds, using a ten-pin
++ IDC cable. A default "heartbeat" trigger is provided, but
++ you can of course override this.
+
-+static int __init atngw100_init(void)
-+{
-+ /*
-+ * ATNGW100 uses 16-bit SDRAM interface, so we don't need to
-+ * reserve any pins for it.
-+ */
++config BOARD_ATSTK1002_J2_LED8
++ bool "LED0..LED7"
++ help
++ Select this if J2 is jumpered to LED0..LED7 amber leds.
+
-+ at32_add_system_devices();
++config BOARD_ATSTK1002_J2_RGB
++ bool "RGB leds"
++ help
++ Select this if J2 is jumpered to the RGB leds.
+
-+ at32_add_device_usart(0);
++endchoice
+
-+ set_hw_addr(at32_add_device_eth(0, ð_data[0]));
-+ set_hw_addr(at32_add_device_eth(1, ð_data[1]));
++endif # stk 1002
+diff -x .git -Nur linux-2.6.22.1/arch/avr32/configs/atngw100_defconfig linux-avr32.git/arch/avr32/configs/atngw100_defconfig
+--- linux-2.6.22.1/arch/avr32/configs/atngw100_defconfig 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/arch/avr32/configs/atngw100_defconfig 2007-07-12 13:59:49.000000000 +0200
+@@ -712,7 +712,21 @@
+ #
+ # LED devices
+ #
+-# CONFIG_NEW_LEDS is not set
++CONFIG_NEW_LEDS=y
++CONFIG_LEDS_CLASS=y
+
-+ 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);
++#
++# LED drivers
++#
++CONFIG_LEDS_GPIO=y
+
-+ 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 @@
++#
++# LED Triggers
++#
++CONFIG_LEDS_TRIGGERS=y
++CONFIG_LEDS_TRIGGER_TIMER=y
++CONFIG_LEDS_TRIGGER_HEARTBEAT=y
++
+
+ #
+ # LED drivers
+diff -x .git -Nur linux-2.6.22.1/arch/avr32/drivers/dw-dmac.c linux-avr32.git/arch/avr32/drivers/dw-dmac.c
+--- linux-2.6.22.1/arch/avr32/drivers/dw-dmac.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-avr32.git/arch/avr32/drivers/dw-dmac.c 2007-06-06 11:33:46.000000000 +0200
+@@ -0,0 +1,761 @@
+/*
-+ * ATSTK1000 setup code: Daughterboard interface
++ * Driver for the Synopsys DesignWare DMA Controller
+ *
-+ * Copyright (C) 2007 Atmel Corporation
++ * 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 __ARCH_AVR32_BOARDS_ATSTK1000_ATSTK1000_H
-+#define __ARCH_AVR32_BOARDS_ATSTK1000_ATSTK1000_H
++#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>
+
-+extern struct atmel_lcdfb_info atstk1000_lcdc_data;
++#include <asm/dma-controller.h>
++#include <asm/io.h>
+
-+#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 "dw-dmac.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, ð_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,
++#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 {
+ goto out_free_pool;
+
+ ret = request_irq(platform_get_irq(pdev, 0), dmac_interrupt,
-+ SA_SAMPLE_RANDOM, pdev->name, dmac);
++ IRQF_SAMPLE_RANDOM, pdev->name, dmac);
+ if (ret)
+ goto out_unmap_regs;
+
+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
+diff -x .git -Nur linux-2.6.22.1/arch/avr32/drivers/dw-dmac.h linux-avr32.git/arch/avr32/drivers/dw-dmac.h
+--- linux-2.6.22.1/arch/avr32/drivers/dw-dmac.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-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
+#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
+diff -x .git -Nur linux-2.6.22.1/arch/avr32/drivers/Makefile linux-avr32.git/arch/avr32/drivers/Makefile
+--- linux-2.6.22.1/arch/avr32/drivers/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-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"
+diff -x .git -Nur linux-2.6.22.1/arch/avr32/Kconfig linux-avr32.git/arch/avr32/Kconfig
+--- linux-2.6.22.1/arch/avr32/Kconfig 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/arch/avr32/Kconfig 2007-07-12 13:59:49.000000000 +0200
+@@ -113,6 +113,10 @@
+ bool "ATNGW100 Network Gateway"
endchoice
-+source "arch/avr32/mach-at32ap/Kconfig"
++if BOARD_ATSTK1000
++source "arch/avr32/boards/atstk1000/Kconfig"
++endif
+
- config LOAD_ADDRESS
- hex
- default 0x10000000 if LOADER_U_BOOT=y && CPU_AT32AP7000=y
-@@ -164,6 +171,10 @@
+ choice
+ prompt "Boot loader type"
+ default LOADER_U_BOOT
+@@ -171,6 +175,10 @@
enabling Nexus-compliant debuggers to keep track of the PID of the
currently executing task.
# 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);
- }
+@@ -185,6 +193,27 @@
-@@ -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;
- }
+ endmenu
+
++menu "Power managment options"
++
++menu "CPU Frequency scaling"
++
++source "drivers/cpufreq/Kconfig"
++
++config CPU_FREQ_AT32AP
++ bool "CPU frequency driver for AT32AP"
++ depends on CPU_FREQ && PLATFORM_AT32AP
++ default n
++ help
++ This enables the CPU frequency driver for AT32AP processors.
++
++ For details, take a look in <file:Documentation/cpu-freq>.
++
++ If in doubt, say N.
++
++endmenu
++
++endmenu
++
+ menu "Bus options"
- #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
+ config PCI
+diff -x .git -Nur linux-2.6.22.1/arch/avr32/kernel/dma-controller.c linux-avr32.git/arch/avr32/kernel/dma-controller.c
+--- linux-2.6.22.1/arch/avr32/kernel/dma-controller.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-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
+ 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
+diff -x .git -Nur linux-2.6.22.1/arch/avr32/kernel/Makefile linux-avr32.git/arch/avr32/kernel/Makefile
+--- linux-2.6.22.1/arch/avr32/kernel/Makefile 2007-07-10 20:56:30.000000000 +0200
++++ linux-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-$(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.
- */
+diff -x .git -Nur linux-2.6.22.1/arch/avr32/mach-at32ap/at32ap7000.c linux-avr32.git/arch/avr32/mach-at32ap/at32ap7000.c
+--- linux-2.6.22.1/arch/avr32/mach-at32ap/at32ap7000.c 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/arch/avr32/mach-at32ap/at32ap7000.c 2007-07-12 13:59:49.000000000 +0200
+@@ -17,14 +17,20 @@
+ #include <asm/arch/at32ap7000.h>
+ #include <asm/arch/board.h>
+ #include <asm/arch/portmux.h>
+-#include <asm/arch/sm.h>
--#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>
+ #include <video/atmel_lcdc.h>
- void *module_alloc(unsigned long size)
-@@ -315,10 +316,10 @@
- vfree(module->arch.syminfo);
- module->arch.syminfo = NULL;
+ #include "clock.h"
+ #include "hmatrix.h"
+ #include "pio.h"
+-#include "sm.h"
++#include "pm.h"
++
++/*
++ * We can reduce the code size a bit by using a constant here. Since
++ * this file is completely chip-specific, it's safe to not use
++ * ioremap. Generic drivers should of course never do this.
++ */
++#define AT32_PM_BASE 0xfff00000
-- return 0;
-+ return module_bug_finalize(hdr, sechdrs, module);
+ #define PBMEM(base) \
+ { \
+@@ -88,6 +94,8 @@
+ .index = _index, \
}
- void module_arch_cleanup(struct module *module)
++static DEFINE_SPINLOCK(pm_lock);
++
+ unsigned long at32ap7000_osc_rates[3] = {
+ [0] = 32768,
+ /* FIXME: these are ATSTK1002-specific */
+@@ -104,11 +112,11 @@
{
--
-+ module_bug_cleanup(module);
+ unsigned long div, mul, rate;
+
+- if (!(control & SM_BIT(PLLEN)))
++ if (!(control & PM_BIT(PLLEN)))
+ return 0;
+
+- div = SM_BFEXT(PLLDIV, control) + 1;
+- mul = SM_BFEXT(PLLMUL, control) + 1;
++ div = PM_BFEXT(PLLDIV, control) + 1;
++ mul = PM_BFEXT(PLLMUL, control) + 1;
+
+ rate = clk->parent->get_rate(clk->parent);
+ rate = (rate + div / 2) / div;
+@@ -121,7 +129,7 @@
+ {
+ u32 control;
+
+- control = sm_readl(&system_manager, PM_PLL0);
++ control = pm_readl(PLL0);
+
+ return pll_get_rate(clk, control);
}
-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>
+@@ -130,7 +138,7 @@
+ {
+ u32 control;
- #include <asm/sysreg.h>
-@@ -19,6 +20,8 @@
- void (*pm_power_off)(void) = NULL;
- EXPORT_SYMBOL(pm_power_off);
+- control = sm_readl(&system_manager, PM_PLL1);
++ control = pm_readl(PLL1);
-+extern void cpu_idle_sleep(void);
-+
- /*
- * This file handles the architecture-dependent parts of process handling..
- */
-@@ -27,9 +30,8 @@
+ return pll_get_rate(clk, control);
+ }
+@@ -187,108 +195,139 @@
+
+ static void cpu_clk_mode(struct clk *clk, int enabled)
{
- /* 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 */
+- struct at32_sm *sm = &system_manager;
+ unsigned long flags;
+ u32 mask;
+
+- spin_lock_irqsave(&sm->lock, flags);
+- mask = sm_readl(sm, PM_CPU_MASK);
++ spin_lock_irqsave(&pm_lock, flags);
++ mask = pm_readl(CPU_MASK);
+ if (enabled)
+ mask |= 1 << clk->index;
+ else
+ mask &= ~(1 << clk->index);
+- sm_writel(sm, PM_CPU_MASK, mask);
+- spin_unlock_irqrestore(&sm->lock, flags);
++ pm_writel(CPU_MASK, mask);
++ spin_unlock_irqrestore(&pm_lock, flags);
}
-+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)
+ static unsigned long cpu_clk_get_rate(struct clk *clk)
+ {
+ unsigned long cksel, shift = 0;
+
+- cksel = sm_readl(&system_manager, PM_CKSEL);
+- if (cksel & SM_BIT(CPUDIV))
+- shift = SM_BFEXT(CPUSEL, cksel) + 1;
++ cksel = pm_readl(CKSEL);
++ if (cksel & PM_BIT(CPUDIV))
++ shift = PM_BFEXT(CPUSEL, cksel) + 1;
+
+ return bus_clk_get_rate(clk, shift);
+ }
+
++static long cpu_clk_set_rate(struct clk *clk, unsigned long rate, int apply)
+{
-+ return (p > (unsigned long)tinfo)
-+ && (p < (unsigned long)tinfo + THREAD_SIZE - 3);
-+}
++ u32 control;
++ unsigned long parent_rate, child_div, actual_rate, div;
+
-+#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;
++ parent_rate = clk->parent->get_rate(clk->parent);
++ control = pm_readl(CKSEL);
+
-+ if (regs)
-+ fp = regs->r7;
-+ else if (tsk == current)
-+ asm("mov %0, r7" : "=r"(fp));
++ if (control & PM_BIT(HSBDIV))
++ child_div = 1 << (PM_BFEXT(HSBSEL, control) + 1);
+ 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);
++ child_div = 1;
+
-+ 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);
++ if (rate > 3 * (parent_rate / 4) || child_div == 1) {
++ actual_rate = parent_rate;
++ control &= ~PM_BIT(CPUDIV);
++ } else {
++ unsigned int cpusel;
++ div = (parent_rate + rate / 2) / rate;
++ if (div > child_div)
++ div = child_div;
++ cpusel = (div > 1) ? (fls(div) - 2) : 0;
++ control = PM_BIT(CPUDIV) | PM_BFINS(CPUSEL, cpusel, control);
++ actual_rate = parent_rate / (1 << (cpusel + 1));
+ }
-+}
+
-+void show_stack(struct task_struct *tsk, unsigned long *stack)
-+{
-+ show_stack_log_lvl(tsk, (unsigned long)stack, NULL, "");
-+}
++ pr_debug("clk %s: new rate %lu (actual rate %lu)\n",
++ clk->name, rate, actual_rate);
+
-+void dump_stack(void)
-+{
-+ unsigned long stack;
++ if (apply)
++ pm_writel(CKSEL, control);
+
-+ show_trace_log_lvl(current, &stack, NULL, "");
++ return actual_rate;
+}
-+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"
- };
+ static void hsb_clk_mode(struct clk *clk, int enabled)
+ {
+- struct at32_sm *sm = &system_manager;
+ unsigned long flags;
+ u32 mask;
+
+- spin_lock_irqsave(&sm->lock, flags);
+- mask = sm_readl(sm, PM_HSB_MASK);
++ spin_lock_irqsave(&pm_lock, flags);
++ mask = pm_readl(HSB_MASK);
+ if (enabled)
+ mask |= 1 << clk->index;
+ else
+ mask &= ~(1 << clk->index);
+- sm_writel(sm, PM_HSB_MASK, mask);
+- spin_unlock_irqrestore(&sm->lock, flags);
++ pm_writel(HSB_MASK, mask);
++ spin_unlock_irqrestore(&pm_lock, flags);
+ }
--void show_regs(struct pt_regs *regs)
-+void show_regs_log_lvl(struct pt_regs *regs, const char *log_lvl)
+ static unsigned long hsb_clk_get_rate(struct clk *clk)
{
- 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, "");
+ unsigned long cksel, shift = 0;
+
+- cksel = sm_readl(&system_manager, PM_CKSEL);
+- if (cksel & SM_BIT(HSBDIV))
+- shift = SM_BFEXT(HSBSEL, cksel) + 1;
++ cksel = pm_readl(CKSEL);
++ if (cksel & PM_BIT(HSBDIV))
++ shift = PM_BFEXT(HSBSEL, cksel) + 1;
+
+ return bus_clk_get_rate(clk, shift);
}
- 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 @@
+ static void pba_clk_mode(struct clk *clk, int enabled)
+ {
+- struct at32_sm *sm = &system_manager;
+ unsigned long flags;
+ u32 mask;
+
+- spin_lock_irqsave(&sm->lock, flags);
+- mask = sm_readl(sm, PM_PBA_MASK);
++ spin_lock_irqsave(&pm_lock, flags);
++ mask = pm_readl(PBA_MASK);
+ if (enabled)
+ mask |= 1 << clk->index;
+ else
+ mask &= ~(1 << clk->index);
+- sm_writel(sm, PM_PBA_MASK, mask);
+- spin_unlock_irqrestore(&sm->lock, flags);
++ pm_writel(PBA_MASK, mask);
++ spin_unlock_irqrestore(&pm_lock, flags);
+ }
- #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;
+ static unsigned long pba_clk_get_rate(struct clk *clk)
+ {
+ unsigned long cksel, shift = 0;
- /*
-- * 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];
+- cksel = sm_readl(&system_manager, PM_CKSEL);
+- if (cksel & SM_BIT(PBADIV))
+- shift = SM_BFEXT(PBASEL, cksel) + 1;
++ cksel = pm_readl(CKSEL);
++ if (cksel & PM_BIT(PBADIV))
++ shift = PM_BFEXT(PBASEL, cksel) + 1;
- /*
-- * 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,
-+};
+ return bus_clk_get_rate(clk, shift);
+ }
- /*
-- * 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)
+ static void pbb_clk_mode(struct clk *clk, int enabled)
{
-@@ -157,11 +291,9 @@
+- struct at32_sm *sm = &system_manager;
+ unsigned long flags;
+ u32 mask;
+
+- spin_lock_irqsave(&sm->lock, flags);
+- mask = sm_readl(sm, PM_PBB_MASK);
++ spin_lock_irqsave(&pm_lock, flags);
++ mask = pm_readl(PBB_MASK);
+ if (enabled)
+ mask |= 1 << clk->index;
+ else
+ mask &= ~(1 << clk->index);
+- sm_writel(sm, PM_PBB_MASK, mask);
+- spin_unlock_irqrestore(&sm->lock, flags);
++ pm_writel(PBB_MASK, mask);
++ spin_unlock_irqrestore(&pm_lock, flags);
}
- __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)
+ static unsigned long pbb_clk_get_rate(struct clk *clk)
{
-- struct tag_mem_range *cur, **pprev;
-- struct tag_mem_range *new;
-+ unsigned long start, end;
+ unsigned long cksel, shift = 0;
- /*
- * 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
+- cksel = sm_readl(&system_manager, PM_CKSEL);
+- if (cksel & SM_BIT(PBBDIV))
+- shift = SM_BFEXT(PBBSEL, cksel) + 1;
++ cksel = pm_readl(CKSEL);
++ if (cksel & PM_BIT(PBBDIV))
++ shift = PM_BFEXT(PBBSEL, cksel) + 1;
- return 0;
+ return bus_clk_get_rate(clk, shift);
}
-+__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)
+@@ -296,6 +335,7 @@
+ static struct clk cpu_clk = {
+ .name = "cpu",
+ .get_rate = cpu_clk_get_rate,
++ .set_rate = cpu_clk_set_rate,
+ .users = 1,
+ };
+ static struct clk hsb_clk = {
+@@ -327,12 +367,12 @@
{
-- 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);
+ u32 control;
- static int __init parse_tag_cmdline(struct tag *tag)
- {
-@@ -207,12 +358,6 @@
+- control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
++ control = pm_readl(GCCTRL(clk->index));
+ if (enabled)
+- control |= SM_BIT(CEN);
++ control |= PM_BIT(CEN);
+ else
+- control &= ~SM_BIT(CEN);
+- sm_writel(&system_manager, PM_GCCTRL + 4 * clk->index, control);
++ control &= ~PM_BIT(CEN);
++ pm_writel(GCCTRL(clk->index), control);
}
- __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 unsigned long genclk_get_rate(struct clk *clk)
+@@ -340,9 +380,9 @@
+ u32 control;
+ unsigned long div = 1;
--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);
- }
+- control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
+- if (control & SM_BIT(DIVEN))
+- div = 2 * (SM_BFEXT(DIV, control) + 1);
++ control = pm_readl(GCCTRL(clk->index));
++ if (control & PM_BIT(DIVEN))
++ div = 2 * (PM_BFEXT(DIV, control) + 1);
-+/*
-+ * 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;
+ return clk->parent->get_rate(clk->parent) / div;
+ }
+@@ -353,23 +393,22 @@
+ unsigned long parent_rate, actual_rate, div;
-+ 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);
+ parent_rate = clk->parent->get_rate(clk->parent);
+- control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
++ control = pm_readl(GCCTRL(clk->index));
- setup_processor();
-@@ -289,24 +555,16 @@
- ((cpu_hz + 500) / 1000) % 1000);
+ if (rate > 3 * parent_rate / 4) {
+ actual_rate = parent_rate;
+- control &= ~SM_BIT(DIVEN);
++ control &= ~PM_BIT(DIVEN);
+ } else {
+ div = (parent_rate + rate) / (2 * rate) - 1;
+- control = SM_BFINS(DIV, div, control) | SM_BIT(DIVEN);
++ control = PM_BFINS(DIV, div, control) | PM_BIT(DIVEN);
+ actual_rate = parent_rate / (2 * (div + 1));
}
-- 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();
+- printk("clk %s: new rate %lu (actual rate %lu)\n",
+- clk->name, rate, actual_rate);
++ dev_dbg(clk->dev, "clk %s: new rate %lu (actual rate %lu)\n",
++ clk->name, rate, actual_rate);
-- board_setup_fbmem(fbmem_start, fbmem_size);
--
- #ifdef CONFIG_VT
- conswitchp = &dummy_con;
- #endif
+ if (apply)
+- sm_writel(&system_manager, PM_GCCTRL + 4 * clk->index,
+- control);
++ pm_writel(GCCTRL(clk->index), control);
- paging_init();
--
- resource_init();
+ return actual_rate;
}
-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>
+@@ -378,24 +417,24 @@
+ {
+ u32 control;
+
+- printk("clk %s: new parent %s (was %s)\n",
+- clk->name, parent->name, clk->parent->name);
++ dev_dbg(clk->dev, "clk %s: new parent %s (was %s)\n",
++ clk->name, parent->name, clk->parent->name);
+
+- control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
++ control = pm_readl(GCCTRL(clk->index));
+
+ if (parent == &osc1 || parent == &pll1)
+- control |= SM_BIT(OSCSEL);
++ control |= PM_BIT(OSCSEL);
+ else if (parent == &osc0 || parent == &pll0)
+- control &= ~SM_BIT(OSCSEL);
++ control &= ~PM_BIT(OSCSEL);
+ else
+ return -EINVAL;
- #include <asm/div64.h>
- #include <asm/sysreg.h>
- #include <asm/io.h>
- #include <asm/sections.h>
+ if (parent == &pll0 || parent == &pll1)
+- control |= SM_BIT(PLLSEL);
++ control |= PM_BIT(PLLSEL);
+ else
+- control &= ~SM_BIT(PLLSEL);
++ control &= ~PM_BIT(PLLSEL);
--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);
- }
+- sm_writel(&system_manager, PM_GCCTRL + 4 * clk->index, control);
++ pm_writel(GCCTRL(clk->index), control);
+ clk->parent = parent;
--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,
- };
+ return 0;
+@@ -408,11 +447,11 @@
-+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);
- }
+ BUG_ON(clk->index > 7);
- 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;
+- control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
+- if (control & SM_BIT(OSCSEL))
+- parent = (control & SM_BIT(PLLSEL)) ? &pll1 : &osc1;
++ control = pm_readl(GCCTRL(clk->index));
++ if (control & PM_BIT(OSCSEL))
++ parent = (control & PM_BIT(PLLSEL)) ? &pll1 : &osc1;
+ else
+- parent = (control & SM_BIT(PLLSEL)) ? &pll0 : &osc0;
++ parent = (control & PM_BIT(PLLSEL)) ? &pll0 : &osc0;
--/* 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 @@
- }
+ clk->parent = parent;
}
-
--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;
-+
+@@ -420,21 +459,53 @@
+ /* --------------------------------------------------------------------
+ * System peripherals
+ * -------------------------------------------------------------------- */
+-static struct resource sm_resource[] = {
+- PBMEM(0xfff00000),
+- NAMED_IRQ(19, "eim"),
+- NAMED_IRQ(20, "pm"),
+- NAMED_IRQ(21, "rtc"),
++static struct resource at32_pm0_resource[] = {
+ {
-+ u64 tmp;
++ .start = 0xfff00000,
++ .end = 0xfff0007f,
++ .flags = IORESOURCE_MEM,
++ },
++ IRQ(20),
+ };
+-struct platform_device at32_sm_device = {
+- .name = "sm",
+- .id = 0,
+- .resource = sm_resource,
+- .num_resources = ARRAY_SIZE(sm_resource),
+
-+ tmp = TICK_NSEC;
-+ tmp <<= shift;
-+ tmp += mult / 2;
-+ do_div(tmp, mult);
++static struct resource at32ap700x_rtc0_resource[] = {
++ {
++ .start = 0xfff00080,
++ .end = 0xfff000af,
++ .flags = IORESOURCE_MEM,
++ },
++ IRQ(21),
++};
+
-+ cycles_per_jiffy = tmp;
-+ }
++static struct resource at32_wdt0_resource[] = {
++ {
++ .start = 0xfff000b0,
++ .end = 0xfff000bf,
++ .flags = IORESOURCE_MEM,
++ },
++};
+
-+ ret = setup_irq(0, &timer_irqaction);
-+ if (ret) {
-+ pr_debug("timer: could not request IRQ 0: %d\n", ret);
-+ return -ENODEV;
-+ }
++static struct resource at32_eic0_resource[] = {
++ {
++ .start = 0xfff00100,
++ .end = 0xfff0013f,
++ .flags = IORESOURCE_MEM,
++ },
++ IRQ(19),
+ };
+-static struct clk at32_sm_pclk = {
+
-+ printk(KERN_INFO "timer: AT32AP COUNT-COMPARE at irq 0, "
-+ "%lu.%03lu MHz\n",
-+ ((count_hz + 500) / 1000) / 1000,
-+ ((count_hz + 500) / 1000) % 1000);
++DEFINE_DEV(at32_pm, 0);
++DEFINE_DEV(at32ap700x_rtc, 0);
++DEFINE_DEV(at32_wdt, 0);
++DEFINE_DEV(at32_eic, 0);
+
-+ return 0;
- }
++/*
++ * Peripheral clock for PM, RTC, WDT and EIC. PM will ensure that this
++ * is always running.
++ */
++static struct clk at32_pm_pclk = {
+ .name = "pclk",
+- .dev = &at32_sm_device.dev,
++ .dev = &at32_pm0_device.dev,
+ .parent = &pbb_clk,
+ .mode = pbb_clk_mode,
+ .get_rate = pbb_clk_get_rate,
+@@ -491,6 +562,17 @@
+ .users = 1,
+ };
- /*
- * 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);
++static struct resource dmaca0_resource[] = {
++ {
++ .start = 0xff200000,
++ .end = 0xff20ffff,
++ .flags = IORESOURCE_MEM,
++ },
++ IRQ(2),
++};
++DEFINE_DEV(dmaca, 0);
++DEV_CLK(hclk, dmaca0, hsb, 10);
+
-+ 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()));
- }
+ /* --------------------------------------------------------------------
+ * HMATRIX
+ * -------------------------------------------------------------------- */
+@@ -583,12 +665,14 @@
--static irqreturn_t
--timer_interrupt(int irq, void *dev_id)
-+irqreturn_t __weak timer_interrupt(int irq, void *dev_id)
+ void __init at32_add_system_devices(void)
{
-- unsigned int count;
+- system_manager.eim_first_irq = EIM_IRQ_BASE;
-
- /* ack timer interrupt and try to set next interrupt */
-- count = avr32_hpt_read();
- avr32_timer_ack();
+- platform_device_register(&at32_sm_device);
++ platform_device_register(&at32_pm0_device);
+ platform_device_register(&at32_intc0_device);
++ platform_device_register(&at32ap700x_rtc0_device);
++ platform_device_register(&at32_wdt0_device);
++ platform_device_register(&at32_eic0_device);
+ platform_device_register(&smc0_device);
+ platform_device_register(&pdc_device);
++ platform_device_register(&dmaca0_device);
-- /* 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;
- }
+ platform_device_register(&at32_systc0_device);
--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;
+@@ -894,6 +978,83 @@
+ }
-+ /*
-+ * 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(¤t->sighand->siglock);
-+ handler = current->sighand->action[signr-1].sa.sa_handler;
-+ spin_unlock_irq(¤t->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
-+ * -------------------------------------------------------------------- */
+ /* --------------------------------------------------------------------
++ * TWI
++ * -------------------------------------------------------------------- */
+
+static struct resource atmel_twi0_resource[] = {
+ PBMEM(0xffe00800),
+/* --------------------------------------------------------------------
* 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 @@
- };
+ static struct atmel_lcdfb_info atmel_lcdfb0_data;
+@@ -1013,6 +1174,228 @@
+ }
- 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)
+ /* --------------------------------------------------------------------
++ * USB Device Controller
++ * -------------------------------------------------------------------- */
++static struct resource usba0_resource[] __initdata = {
++ {
++ .name = "fifo",
++ .start = 0xff300000,
++ .end = 0xff3fffff,
++ .flags = IORESOURCE_MEM,
++ }, {
++ .name = "regs",
++ .start = 0xfff03000,
++ .end = 0xfff033ff,
++ .flags = IORESOURCE_MEM,
++ },
++ IRQ(31),
++};
++static struct clk usba0_pclk = {
++ .name = "pclk",
++ .parent = &pbb_clk,
++ .mode = pbb_clk_mode,
++ .get_rate = pbb_clk_get_rate,
++ .index = 12,
++};
++static struct clk usba0_hclk = {
++ .name = "hclk",
++ .parent = &hsb_clk,
++ .mode = hsb_clk_mode,
++ .get_rate = hsb_clk_get_rate,
++ .index = 6,
++};
++
++struct platform_device *__init
++at32_add_device_usba(unsigned int id, struct usba_platform_data *data)
++{
++ struct platform_device *pdev;
++
++ if (id != 0)
+ 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;
++ pdev = platform_device_alloc("atmel_usba_udc", 0);
++ if (!pdev)
++ return NULL;
+
-+ default:
-+ goto err_invalid_id;
-+ }
++ if (platform_device_add_resources(pdev, usba0_resource,
++ ARRAY_SIZE(usba0_resource)))
++ goto out_free_pdev;
++
++ if (data) {
++ if (platform_device_add_data(pdev, data, sizeof(*data)))
++ goto out_free_pdev;
+
-+ if (fbmem_len) {
-+ pdev->resource[2].start = fbmem_start;
-+ pdev->resource[2].end = fbmem_start + fbmem_len - 1;
-+ pdev->resource[2].flags = IORESOURCE_MEM;
++ if (data->vbus_pin != GPIO_PIN_NONE)
++ at32_select_gpio(data->vbus_pin, 0);
+ }
+
-+ info = pdev->dev.platform_data;
-+ memcpy(info, data, sizeof(struct atmel_lcdfb_info));
-+ info->default_monspecs = monspecs;
++ usba0_pclk.dev = &pdev->dev;
++ usba0_hclk.dev = &pdev->dev;
++
++ platform_device_add(pdev);
+
-+ platform_device_register(pdev);
+ return pdev;
+
-+err_invalid_id:
-+ kfree(modedb);
-+err_dup_modedb:
-+ kfree(monspecs);
++out_free_pdev:
++ platform_device_put(pdev);
+ return NULL;
+}
+
+/* --------------------------------------------------------------------
-+ * USB Device Controller
++ * SSC
+ * -------------------------------------------------------------------- */
-+static struct resource usba0_resource[] = {
-+ {
-+ .start = 0xff300000,
-+ .end = 0xff3fffff,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ PBMEM(0xfff03000),
-+ IRQ(31),
++static struct resource ssc0_resource[] = {
++ PBMEM(0xffe01c00),
++ IRQ(10),
++};
++DEFINE_DEV(ssc, 0);
++DEV_CLK(pclk, ssc0, pba, 7);
++
++static struct resource ssc1_resource[] = {
++ PBMEM(0xffe02000),
++ IRQ(11),
+};
-+DEFINE_DEV(usba, 0);
-+DEV_CLK(pclk, usba0, pbb, 12);
-+DEV_CLK(hclk, usba0, hsb, 6);
++DEFINE_DEV(ssc, 1);
++DEV_CLK(pclk, ssc1, pba, 8);
+
-+struct platform_device *__init at32_add_device_usba(unsigned int id)
++static struct resource ssc2_resource[] = {
++ PBMEM(0xffe02400),
++ IRQ(12),
++};
++DEFINE_DEV(ssc, 2);
++DEV_CLK(pclk, ssc2, pba, 9);
++
++struct platform_device *__init
++at32_add_device_ssc(unsigned int id, unsigned int flags)
+{
+ struct platform_device *pdev;
+
+ switch (id) {
+ case 0:
-+ pdev = &usba0_device;
-+ /* USB pads are not multiplexed */
- break;
++ pdev = &ssc0_device;
++ if (flags & ATMEL_SSC_RF)
++ select_peripheral(PA(21), PERIPH_A, 0); /* RF */
++ if (flags & ATMEL_SSC_RK)
++ select_peripheral(PA(22), PERIPH_A, 0); /* RK */
++ if (flags & ATMEL_SSC_TK)
++ select_peripheral(PA(23), PERIPH_A, 0); /* TK */
++ if (flags & ATMEL_SSC_TF)
++ select_peripheral(PA(24), PERIPH_A, 0); /* TF */
++ if (flags & ATMEL_SSC_TD)
++ select_peripheral(PA(25), PERIPH_A, 0); /* TD */
++ if (flags & ATMEL_SSC_RD)
++ select_peripheral(PA(26), PERIPH_A, 0); /* RD */
++ break;
++ case 1:
++ pdev = &ssc1_device;
++ if (flags & ATMEL_SSC_RF)
++ select_peripheral(PA(0), PERIPH_B, 0); /* RF */
++ if (flags & ATMEL_SSC_RK)
++ select_peripheral(PA(1), PERIPH_B, 0); /* RK */
++ if (flags & ATMEL_SSC_TK)
++ select_peripheral(PA(2), PERIPH_B, 0); /* TK */
++ if (flags & ATMEL_SSC_TF)
++ select_peripheral(PA(3), PERIPH_B, 0); /* TF */
++ if (flags & ATMEL_SSC_TD)
++ select_peripheral(PA(4), PERIPH_B, 0); /* TD */
++ if (flags & ATMEL_SSC_RD)
++ select_peripheral(PA(5), PERIPH_B, 0); /* RD */
++ break;
++ case 2:
++ pdev = &ssc2_device;
++ if (flags & ATMEL_SSC_TD)
++ select_peripheral(PB(13), PERIPH_A, 0); /* TD */
++ if (flags & ATMEL_SSC_RD)
++ select_peripheral(PB(14), PERIPH_A, 0); /* RD */
++ if (flags & ATMEL_SSC_TK)
++ select_peripheral(PB(15), PERIPH_A, 0); /* TK */
++ if (flags & ATMEL_SSC_TF)
++ select_peripheral(PB(16), PERIPH_A, 0); /* TF */
++ if (flags & ATMEL_SSC_RF)
++ select_peripheral(PB(17), PERIPH_A, 0); /* RF */
++ if (flags & ATMEL_SSC_RK)
++ select_peripheral(PB(18), PERIPH_A, 0); /* RK */
++ break;
+ default:
+ return NULL;
+ }
+};
+DEFINE_DEV(atmel_ac97c, 0);
+DEV_CLK(pclk, atmel_ac97c0, pbb, 10);
-
++
+struct platform_device *__init
+at32_add_device_ac97c(unsigned int id)
+{
+ 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));
++ default:
++ return NULL;
++ }
++
+ platform_device_register(pdev);
+ return pdev;
+}
+ default:
+ return NULL;
+ }
-
- platform_device_register(pdev);
- return pdev;
-@@ -950,18 +1249,21 @@
++
++ platform_device_register(pdev);
++ return pdev;
++}
++
++/* --------------------------------------------------------------------
+ * GCLK
+ * -------------------------------------------------------------------- */
+ static struct clk gclk0 = {
+@@ -1066,7 +1449,7 @@
+ &hsb_clk,
+ &pba_clk,
&pbb_clk,
- &at32_sm_pclk,
+- &at32_sm_pclk,
++ &at32_pm_pclk,
&at32_intc0_pclk,
-+ &hmatrix_clk,
+ &hmatrix_clk,
&ebi_clk,
- &hramc_clk,
- &smc0_pclk,
+@@ -1075,6 +1458,7 @@
&smc0_mck,
&pdc_hclk,
&pdc_pclk,
&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 @@
+@@ -1092,8 +1476,18 @@
&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,
+ &atmel_lcdfb0_hck1,
+ &atmel_lcdfb0_pixclk,
+ &usba0_pclk,
+ &usba0_hclk,
++ &ssc0_pclk,
++ &ssc1_pclk,
++ &ssc2_pclk,
+ &atmel_ac97c0_pclk,
+ &abdac0_pclk,
+ &abdac0_sample_clk,
&gclk0,
&gclk1,
&gclk2,
-@@ -1012,7 +1321,8 @@
- genclk_init_parent(&gclk2);
+@@ -1113,18 +1507,20 @@
+
+ void __init at32_clock_init(void)
+ {
+- struct at32_sm *sm = &system_manager;
+ u32 cpu_mask = 0, hsb_mask = 0, pba_mask = 0, pbb_mask = 0;
+ int i;
+
+- if (sm_readl(sm, PM_MCCTRL) & SM_BIT(PLLSEL))
++ if (pm_readl(MCCTRL) & PM_BIT(PLLSEL)) {
+ main_clock = &pll0;
+- else
++ cpu_clk.parent = &pll0;
++ } else {
+ main_clock = &osc0;
++ cpu_clk.parent = &osc0;
++ }
+
+- if (sm_readl(sm, PM_PLL0) & SM_BIT(PLLOSC))
++ if (pm_readl(PLL0) & PM_BIT(PLLOSC))
+ pll0.parent = &osc1;
+- if (sm_readl(sm, PM_PLL1) & SM_BIT(PLLOSC))
++ if (pm_readl(PLL1) & PM_BIT(PLLOSC))
+ pll1.parent = &osc1;
+
+ genclk_init_parent(&gclk0);
+@@ -1133,6 +1529,7 @@
genclk_init_parent(&gclk3);
genclk_init_parent(&gclk4);
-- genclk_init_parent(&lcdc0_pixclk);
-+ genclk_init_parent(&atmel_lcdfb0_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 @@
+@@ -1157,8 +1554,8 @@
+ pbb_mask |= 1 << clk->index;
+ }
- #include "clock.h"
+- sm_writel(sm, PM_CPU_MASK, cpu_mask);
+- sm_writel(sm, PM_HSB_MASK, hsb_mask);
+- sm_writel(sm, PM_PBA_MASK, pba_mask);
+- sm_writel(sm, PM_PBB_MASK, pbb_mask);
++ pm_writel(CPU_MASK, cpu_mask);
++ pm_writel(HSB_MASK, hsb_mask);
++ pm_writel(PBA_MASK, pba_mask);
++ pm_writel(PBB_MASK, pbb_mask);
+ }
+diff -x .git -Nur linux-2.6.22.1/arch/avr32/mach-at32ap/at32ap.c linux-avr32.git/arch/avr32/mach-at32ap/at32ap.c
+--- linux-2.6.22.1/arch/avr32/mach-at32ap/at32ap.c 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/arch/avr32/mach-at32ap/at32ap.c 2007-07-12 13:59:49.000000000 +0200
+@@ -11,41 +11,10 @@
+ #include <linux/init.h>
+ #include <linux/platform_device.h>
--static spinlock_t clk_lock = SPIN_LOCK_UNLOCKED;
-+static DEFINE_SPINLOCK(clk_lock);
+-#include <asm/io.h>
+-
+ #include <asm/arch/init.h>
+-#include <asm/arch/sm.h>
+-
+-struct at32_sm system_manager;
+-
+-static int __init at32_sm_init(void)
+-{
+- struct resource *regs;
+- struct at32_sm *sm = &system_manager;
+- int ret = -ENXIO;
+-
+- regs = platform_get_resource(&at32_sm_device, IORESOURCE_MEM, 0);
+- if (!regs)
+- goto fail;
+-
+- spin_lock_init(&sm->lock);
+- sm->pdev = &at32_sm_device;
+-
+- ret = -ENOMEM;
+- sm->regs = ioremap(regs->start, regs->end - regs->start + 1);
+- if (!sm->regs)
+- goto fail;
+-
+- return 0;
+-
+-fail:
+- printk(KERN_ERR "Failed to initialize System Manager: %d\n", ret);
+- return ret;
+-}
- struct clk *clk_get(struct device *dev, const char *id)
+ void __init setup_platform(void)
{
-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 @@
+- at32_sm_init();
+ at32_clock_init();
+ at32_portmux_init();
+ }
+diff -x .git -Nur linux-2.6.22.1/arch/avr32/mach-at32ap/cpufreq.c linux-avr32.git/arch/avr32/mach-at32ap/cpufreq.c
+--- linux-2.6.22.1/arch/avr32/mach-at32ap/cpufreq.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-avr32.git/arch/avr32/mach-at32ap/cpufreq.c 2007-07-12 13:59:49.000000000 +0200
+@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2004-2007 Atmel Corporation
+ *
+ * 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>
++/*#define DEBUG*/
++
++#include <linux/kernel.h>
++#include <linux/types.h>
+#include <linux/init.h>
-+#include <linux/profile.h>
-+#include <linux/sysdev.h>
++#include <linux/cpufreq.h>
++#include <linux/io.h>
++#include <linux/clk.h>
+#include <linux/err.h>
++#include <asm/system.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;
++static struct clk *cpuclk;
+
-+/* 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)
++static int at32_verify_speed(struct cpufreq_policy *policy)
+{
-+ 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);
++ if (policy->cpu != 0)
++ return -EINVAL;
+
-+ /* 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);
-+ }
++ cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
++ policy->cpuinfo.max_freq);
++ return 0;
+}
+
-+u32 avr32_hpt_read(void)
++static unsigned int at32_get_speed(unsigned int cpu)
+{
-+ return timer_read(ioregs, 0, CV);
++ /* No SMP support */
++ if (cpu)
++ return 0;
++ return (unsigned int)((clk_get_rate(cpuclk) + 500) / 1000);
+}
+
-+static int avr32_timer_calc_div_and_set_jiffies(struct clk *pclk)
++static int at32_set_target(struct cpufreq_policy *policy,
++ unsigned int target_freq,
++ unsigned int relation)
+{
-+ 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;
++ struct cpufreq_freqs freqs;
++ long freq;
+
-+ do {
-+ count_hz = clk_get_rate(pclk) / divs[i];
-+ mult = clocksource_hz2mult(count_hz, shift);
-+ clocksource_avr32.mult = mult;
++ /* Convert target_freq from kHz to Hz */
++ freq = clk_round_rate(cpuclk, target_freq * 1000);
+
-+ tmp = TICK_NSEC;
-+ tmp <<= shift;
-+ tmp += mult / 2;
-+ do_div(tmp, mult);
++ /* Check if policy->min <= new_freq <= policy->max */
++ if(freq < (policy->min * 1000) || freq > (policy->max * 1000))
++ return -EINVAL;
+
-+ cycles_per_jiffy = tmp;
-+ } while (cycles_per_jiffy > cycles_max && ++i < divs_size);
++ pr_debug("cpufreq: requested frequency %u Hz\n", target_freq * 1000);
+
-+ clock_div = i + 1;
++ freqs.old = at32_get_speed(0);
++ freqs.new = (freq + 500) / 1000;
++ freqs.cpu = 0;
++ freqs.flags = 0;
+
-+ if (clock_div > divs_size) {
-+ pr_debug("timer: could not calculate clock divider\n");
-+ return -EFAULT;
-+ }
++ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
++ clk_set_rate(cpuclk, freq);
++ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
-+ /* Set the clock divider */
-+ timer_write(ioregs, 0, CMR, TIMER_BF(CMR_TCCLKS, clock_div));
++ pr_debug("cpufreq: set frequency %lu Hz\n", freq);
+
+ return 0;
+}
+
-+int avr32_hpt_init(unsigned int count)
++static int __init at32_cpufreq_driver_init(struct cpufreq_policy *policy)
+{
-+ 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;
++ if (policy->cpu != 0)
++ return -EINVAL;
+
-+ ret = setup_irq(irq, &timer_irqaction);
-+ if (ret) {
-+ pr_debug("timer: could not request irq %d: %d\n",
-+ irq, ret);
-+ goto out_error_io;
++ cpuclk = clk_get(NULL, "cpu");
++ if (IS_ERR(cpuclk)) {
++ pr_debug("cpufreq: could not get CPU clk\n");
++ return PTR_ERR(cpuclk);
+ }
+
-+ expirelo = (timer_read(ioregs, 0, CV) / cycles_per_jiffy + 1)
-+ * cycles_per_jiffy;
++ policy->cpuinfo.min_freq = (clk_round_rate(cpuclk, 1) + 500) / 1000;
++ policy->cpuinfo.max_freq = (clk_round_rate(cpuclk, ~0UL) + 500) / 1000;
++ policy->cpuinfo.transition_latency = 0;
++ policy->cur = at32_get_speed(0);
++ policy->min = policy->cpuinfo.min_freq;
++ policy->max = policy->cpuinfo.max_freq;
++ policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+
-+ /* 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);
++ printk("cpufreq: AT32AP CPU frequency driver\n");
+
+ 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;
-+}
++static struct cpufreq_driver at32_driver = {
++ .name = "at32ap",
++ .owner = THIS_MODULE,
++ .init = at32_cpufreq_driver_init,
++ .verify = at32_verify_speed,
++ .target = at32_set_target,
++ .get = at32_get_speed,
++ .flags = CPUFREQ_STICKY,
++};
+
-+irqreturn_t timer_interrupt(int irq, void *dev_id)
++static int __init at32_cpufreq_init(void)
+{
-+ 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();
++ return cpufreq_register_driver(&at32_driver);
++}
+
-+ /*
-+ * Call the generic timer interrupt handler
-+ */
-+ write_seqlock(&xtime_lock);
-+ do_timer(1);
-+ write_sequnlock(&xtime_lock);
++arch_initcall(at32_cpufreq_init);
+diff -x .git -Nur linux-2.6.22.1/arch/avr32/mach-at32ap/extint.c linux-avr32.git/arch/avr32/mach-at32ap/extint.c
+--- linux-2.6.22.1/arch/avr32/mach-at32ap/extint.c 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/arch/avr32/mach-at32ap/extint.c 2007-07-12 13:59:49.000000000 +0200
+@@ -17,42 +17,83 @@
+
+ #include <asm/io.h>
+
+-#include <asm/arch/sm.h>
+-
+-#include "sm.h"
++/* EIC register offsets */
++#define EIC_IER 0x0000
++#define EIC_IDR 0x0004
++#define EIC_IMR 0x0008
++#define EIC_ISR 0x000c
++#define EIC_ICR 0x0010
++#define EIC_MODE 0x0014
++#define EIC_EDGE 0x0018
++#define EIC_LEVEL 0x001c
++#define EIC_TEST 0x0020
++#define EIC_NMIC 0x0024
++
++/* Bitfields in TEST */
++#define EIC_TESTEN_OFFSET 31
++#define EIC_TESTEN_SIZE 1
++
++/* Bitfields in NMIC */
++#define EIC_EN_OFFSET 0
++#define EIC_EN_SIZE 1
+
-+ /*
-+ * 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);
++/* Bit manipulation macros */
++#define EIC_BIT(name) \
++ (1 << EIC_##name##_OFFSET)
++#define EIC_BF(name,value) \
++ (((value) & ((1 << EIC_##name##_SIZE) - 1)) \
++ << EIC_##name##_OFFSET)
++#define EIC_BFEXT(name,value) \
++ (((value) >> EIC_##name##_OFFSET) \
++ & ((1 << EIC_##name##_SIZE) - 1))
++#define EIC_BFINS(name,value,old) \
++ (((old) & ~(((1 << EIC_##name##_SIZE) - 1) \
++ << EIC_##name##_OFFSET)) \
++ | EIC_BF(name,value))
+
-+ return IRQ_HANDLED;
-+ }
++/* Register access macros */
++#define eic_readl(port,reg) \
++ __raw_readl((port)->regs + EIC_##reg)
++#define eic_writel(port,reg,value) \
++ __raw_writel((value), (port)->regs + EIC_##reg)
+
-+ 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/
++struct eic {
++ void __iomem *regs;
++ struct irq_chip *chip;
++ unsigned int first_irq;
++};
- 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 @@
+-static void eim_ack_irq(unsigned int irq)
++static void eic_ack_irq(unsigned int irq)
+ {
+- struct at32_sm *sm = get_irq_chip_data(irq);
+- sm_writel(sm, EIM_ICR, 1 << (irq - sm->eim_first_irq));
++ struct eic *eic = get_irq_chip_data(irq);
++ eic_writel(eic, ICR, 1 << (irq - eic->first_irq));
}
- EXPORT_SYMBOL(dma_free_coherent);
--#if 0
- void *dma_alloc_writecombine(struct device *dev, size_t size,
- dma_addr_t *handle, gfp_t gfp)
+-static void eim_mask_irq(unsigned int irq)
++static void eic_mask_irq(unsigned int irq)
{
- 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);
+- struct at32_sm *sm = get_irq_chip_data(irq);
+- sm_writel(sm, EIM_IDR, 1 << (irq - sm->eim_first_irq));
++ struct eic *eic = get_irq_chip_data(irq);
++ eic_writel(eic, IDR, 1 << (irq - eic->first_irq));
}
- EXPORT_SYMBOL(dma_alloc_writecombine);
-
-@@ -132,8 +137,7 @@
- iounmap(cpu_addr);
+-static void eim_mask_ack_irq(unsigned int irq)
++static void eic_mask_ack_irq(unsigned int irq)
+ {
+- struct at32_sm *sm = get_irq_chip_data(irq);
+- sm_writel(sm, EIM_ICR, 1 << (irq - sm->eim_first_irq));
+- sm_writel(sm, EIM_IDR, 1 << (irq - sm->eim_first_irq));
++ struct eic *eic = get_irq_chip_data(irq);
++ eic_writel(eic, ICR, 1 << (irq - eic->first_irq));
++ eic_writel(eic, IDR, 1 << (irq - eic->first_irq));
+ }
-- page = bus_to_page(handle);
-+ page = phys_to_page(handle);
- __dma_free(dev, size, page, handle);
+-static void eim_unmask_irq(unsigned int irq)
++static void eic_unmask_irq(unsigned int irq)
+ {
+- struct at32_sm *sm = get_irq_chip_data(irq);
+- sm_writel(sm, EIM_IER, 1 << (irq - sm->eim_first_irq));
++ struct eic *eic = get_irq_chip_data(irq);
++ eic_writel(eic, IER, 1 << (irq - eic->first_irq));
}
- 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)
+-static int eim_set_irq_type(unsigned int irq, unsigned int flow_type)
++static int eic_set_irq_type(unsigned int irq, unsigned int flow_type)
{
-- return atomic_notifier_chain_register(¬ify_page_fault_chain, nb);
--}
-+ int ret = 0;
+- struct at32_sm *sm = get_irq_chip_data(irq);
++ struct eic *eic = get_irq_chip_data(irq);
+ struct irq_desc *desc;
+- unsigned int i = irq - sm->eim_first_irq;
++ unsigned int i = irq - eic->first_irq;
+ u32 mode, edge, level;
+- unsigned long flags;
+ int ret = 0;
+
+ flow_type &= IRQ_TYPE_SENSE_MASK;
+@@ -60,11 +101,10 @@
+ flow_type = IRQ_TYPE_LEVEL_LOW;
+
+ desc = &irq_desc[irq];
+- spin_lock_irqsave(&sm->lock, flags);
+
+- mode = sm_readl(sm, EIM_MODE);
+- edge = sm_readl(sm, EIM_EDGE);
+- level = sm_readl(sm, EIM_LEVEL);
++ mode = eic_readl(eic, MODE);
++ edge = eic_readl(eic, EDGE);
++ level = eic_readl(eic, LEVEL);
+
+ switch (flow_type) {
+ case IRQ_TYPE_LEVEL_LOW:
+@@ -89,9 +129,9 @@
+ }
--int unregister_page_fault_notifier(struct notifier_block *nb)
--{
-- return atomic_notifier_chain_unregister(¬ify_page_fault_chain, nb);
--}
-+ if (!user_mode(regs)) {
-+ if (kprobe_running() && kprobe_fault_handler(regs, trap))
-+ ret = 1;
-+ }
+ if (ret == 0) {
+- sm_writel(sm, EIM_MODE, mode);
+- sm_writel(sm, EIM_EDGE, edge);
+- sm_writel(sm, EIM_LEVEL, level);
++ eic_writel(eic, MODE, mode);
++ eic_writel(eic, EDGE, edge);
++ eic_writel(eic, LEVEL, level);
+
+ if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
+ flow_type |= IRQ_LEVEL;
+@@ -99,35 +139,33 @@
+ desc->status |= flow_type;
+ }
--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(¬ify_page_fault_chain, val, &args);
-+ return ret;
+- spin_unlock_irqrestore(&sm->lock, flags);
+-
+ 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)
+
+-struct irq_chip eim_chip = {
+- .name = "eim",
+- .ack = eim_ack_irq,
+- .mask = eim_mask_irq,
+- .mask_ack = eim_mask_ack_irq,
+- .unmask = eim_unmask_irq,
+- .set_type = eim_set_irq_type,
++struct irq_chip eic_chip = {
++ .name = "eic",
++ .ack = eic_ack_irq,
++ .mask = eic_mask_irq,
++ .mask_ack = eic_mask_ack_irq,
++ .unmask = eic_unmask_irq,
++ .set_type = eic_set_irq_type,
+ };
+
+-static void demux_eim_irq(unsigned int irq, struct irq_desc *desc)
++static void demux_eic_irq(unsigned int irq, struct irq_desc *desc)
{
-- return NOTIFY_DONE;
-+ return 0;
+- struct at32_sm *sm = desc->handler_data;
++ struct eic *eic = desc->handler_data;
+ struct irq_desc *ext_desc;
+ unsigned long status, pending;
+ unsigned int i, ext_irq;
+
+- status = sm_readl(sm, EIM_ISR);
+- pending = status & sm_readl(sm, EIM_IMR);
++ status = eic_readl(eic, ISR);
++ pending = status & eic_readl(eic, IMR);
+
+ while (pending) {
+ i = fls(pending) - 1;
+ pending &= ~(1 << i);
+
+- ext_irq = i + sm->eim_first_irq;
++ ext_irq = i + eic->first_irq;
+ ext_desc = irq_desc + ext_irq;
+ if (ext_desc->status & IRQ_LEVEL)
+ handle_level_irq(ext_irq, ext_desc);
+@@ -136,51 +174,85 @@
+ }
}
- #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)
+-static int __init eim_init(void)
++static int __init eic_probe(struct platform_device *pdev)
{
-@@ -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;
- }
+- struct at32_sm *sm = &system_manager;
++ struct eic *eic;
++ struct resource *regs;
+ unsigned int i;
+ unsigned int nr_irqs;
+ unsigned int int_irq;
++ int ret;
+ u32 pattern;
-@@ -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;
+- /*
+- * The EIM is really the same module as SM, so register
+- * mapping, etc. has been taken care of already.
+- */
++ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ int_irq = platform_get_irq(pdev, 0);
++ if (!regs || !int_irq) {
++ dev_dbg(&pdev->dev, "missing regs and/or irq resource\n");
++ return -ENXIO;
++ }
++
++ ret = -ENOMEM;
++ eic = kzalloc(sizeof(struct eic), GFP_KERNEL);
++ if (!eic) {
++ dev_dbg(&pdev->dev, "no memory for eic structure\n");
++ goto err_kzalloc;
++ }
++
++ eic->first_irq = EIM_IRQ_BASE + 32 * pdev->id;
++ eic->regs = ioremap(regs->start, regs->end - regs->start + 1);
++ if (!eic->regs) {
++ dev_dbg(&pdev->dev, "failed to map regs\n");
++ goto err_ioremap;
++ }
/*
- * We ran out of memory, or some other thing happened to us
- * that made us unable to handle the page fault gracefully.
+ * Find out how many interrupt lines that are actually
+ * implemented in hardware.
*/
- 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);
+- sm_writel(sm, EIM_IDR, ~0UL);
+- sm_writel(sm, EIM_MODE, ~0UL);
+- pattern = sm_readl(sm, EIM_MODE);
++ eic_writel(eic, IDR, ~0UL);
++ eic_writel(eic, MODE, ~0UL);
++ pattern = eic_readl(eic, MODE);
+ nr_irqs = fls(pattern);
+
+ /* Trigger on falling edge unless overridden by driver */
+- sm_writel(sm, EIM_MODE, 0UL);
+- sm_writel(sm, EIM_EDGE, 0UL);
++ eic_writel(eic, MODE, 0UL);
++ eic_writel(eic, EDGE, 0UL);
+
+- sm->eim_chip = &eim_chip;
++ eic->chip = &eic_chip;
+
+ for (i = 0; i < nr_irqs; i++) {
+ /* NOTE the handler we set here is ignored by the demux */
+- set_irq_chip_and_handler(sm->eim_first_irq + i, &eim_chip,
++ set_irq_chip_and_handler(eic->first_irq + i, &eic_chip,
+ handle_level_irq);
+- set_irq_chip_data(sm->eim_first_irq + i, sm);
++ set_irq_chip_data(eic->first_irq + i, eic);
+ }
-- /*
-- * 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);
+- int_irq = platform_get_irq_byname(sm->pdev, "eim");
-
- /* 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);
- }
+- set_irq_chained_handler(int_irq, demux_eim_irq);
+- set_irq_data(int_irq, sm);
++ set_irq_chained_handler(int_irq, demux_eic_irq);
++ set_irq_data(int_irq, eic);
- 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);
- }
+- printk("EIM: External Interrupt Module at 0x%p, IRQ %u\n",
+- sm->regs, int_irq);
+- printk("EIM: Handling %u external IRQs, starting with IRQ %u\n",
+- nr_irqs, sm->eim_first_irq);
++ dev_info(&pdev->dev,
++ "External Interrupt Controller at 0x%p, IRQ %u\n",
++ eic->regs, int_irq);
++ dev_info(&pdev->dev,
++ "Handling %u external IRQs, starting with IRQ %u\n",
++ nr_irqs, eic->first_irq);
- /*
-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);
+ return 0;
++
++err_ioremap:
++ kfree(eic);
++err_kzalloc:
++ return ret;
++}
++
++static struct platform_driver eic_driver = {
++ .driver = {
++ .name = "at32_eic",
++ },
++};
++
++static int __init eic_init(void)
++{
++ return platform_driver_probe(&eic_driver, eic_probe);
}
-
--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 @@
+-arch_initcall(eim_init);
++arch_initcall(eic_init);
+diff -x .git -Nur linux-2.6.22.1/arch/avr32/mach-at32ap/gpio-dev.c linux-avr32.git/arch/avr32/mach-at32ap/gpio-dev.c
+--- linux-2.6.22.1/arch/avr32/mach-at32ap/gpio-dev.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-avr32.git/arch/avr32/mach-at32ap/gpio-dev.c 2007-07-12 13:59:49.000000000 +0200
+@@ -0,0 +1,570 @@
+/*
-+ * Register definitions for the Atmel Two-Wire Interface
++ * GPIO /dev and configfs interface
++ *
++ * 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/configfs.h>
++#include <linux/cdev.h>
++#include <linux/fs.h>
++#include <linux/interrupt.h>
++#include <linux/poll.h>
++#include <linux/uaccess.h>
++#include <linux/wait.h>
+
-+#ifndef __ASM_AVR32_TWI_H__
-+#define __ASM_AVR32_TWI_H__
++#include <asm/gpio.h>
++#include <asm/arch/portmux.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
++#define GPIO_DEV_MAX 8
+
-+/* 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
++static struct class *gpio_dev_class;
++static dev_t gpio_devt;
+
-+/* 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
++struct gpio_item {
++ spinlock_t lock;
+
-+/* Bitfields in SMR */
-+#define TWI_SADR_OFFSET 16
-+#define TWI_SADR_SIZE 7
++ int enabled;
++ int initialized;
++ int port;
++ u32 pin_mask;
++ u32 oe_mask;
+
-+/* Bitfields in IADR */
-+#define TWI_IADR_OFFSET 0
-+#define TWI_IADR_SIZE 24
++ /* Pin state last time we read it (for blocking reads) */
++ u32 pin_state;
++ int changed;
+
-+/* 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
++ wait_queue_head_t change_wq;
++ struct fasync_struct *async_queue;
+
-+/* 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
++ int id;
++ struct class_device *gpio_dev;
++ struct cdev char_dev;
++ struct config_item item;
++};
+
-+/* Bitfields in RHR */
-+#define TWI_RXDATA_OFFSET 0
-+#define TWI_RXDATA_SIZE 8
++struct gpio_attribute {
++ struct configfs_attribute attr;
++ ssize_t (*show)(struct gpio_item *, char *);
++ ssize_t (*store)(struct gpio_item *, const char *, size_t);
++};
+
-+/* Bitfields in THR */
-+#define TWI_TXDATA_OFFSET 0
-+#define TWI_TXDATA_SIZE 8
++static irqreturn_t gpio_dev_interrupt(int irq, void *dev_id)
++{
++ struct gpio_item *gpio = dev_id;
++ u32 old_state, new_state;
+
-+/* 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
++ old_state = gpio->pin_state;
++ new_state = at32_gpio_get_value_multiple(gpio->port, gpio->pin_mask);
++ gpio->pin_state = new_state;
+
-+/* 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))
++ if (new_state != old_state) {
++ gpio->changed = 1;
++ wake_up_interruptible(&gpio->change_wq);
+
-+/* 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)
++ if (gpio->async_queue)
++ kill_fasync(&gpio->async_queue, SIGIO, POLL_IN);
++ }
+
-+#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.
-+ */
++ return IRQ_HANDLED;
++}
+
++static int gpio_dev_open(struct inode *inode, struct file *file)
++{
++ struct gpio_item *gpio = container_of(inode->i_cdev,
++ struct gpio_item,
++ char_dev);
++ unsigned int irq;
++ unsigned int i;
++ int ret;
+
-+#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"
++ nonseekable_open(inode, file);
++ config_item_get(&gpio->item);
++ file->private_data = gpio;
++
++ gpio->pin_state = at32_gpio_get_value_multiple(gpio->port,
++ gpio->pin_mask);
++ gpio->changed = 1;
++
++ for (i = 0; i < 32; i++) {
++ if (gpio->pin_mask & (1 << i)) {
++ irq = gpio_to_irq(32 * gpio->port + i);
++ ret = request_irq(irq, gpio_dev_interrupt, 0,
++ "gpio-dev", gpio);
++ if (ret)
++ goto err_irq;
++ }
++ }
+
-+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");
++ return 0;
+
++err_irq:
++ while (i--) {
++ if (gpio->pin_mask & (1 << i)) {
++ irq = gpio_to_irq(32 * gpio->port + i);
++ free_irq(irq, gpio);
++ }
++ }
+
-+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;
++ config_item_put(&gpio->item);
+
-+};
-+#define to_atmel_twi(adap) container_of(adap, struct atmel_twi, adapter)
++ return ret;
++}
+
-+/*
-+ * Initialize the TWI hardware registers.
-+ */
-+static int __devinit twi_hwinit(struct atmel_twi *twi)
++static int gpio_dev_fasync(int fd, struct file *file, int mode)
+{
-+ unsigned long cdiv, ckdiv=0;
++ struct gpio_item *gpio = file->private_data;
+
-+ twi_writel(twi, IDR, ~0UL);
-+ twi_writel(twi, CR, TWI_BIT(SWRST)); /*Reset peripheral*/
-+ twi_readl(twi, SR);
++ return fasync_helper(fd, file, mode, &gpio->async_queue);
++}
+
-+ cdiv = (clk_get_rate(twi->pclk) / (2 * baudrate)) - 4;
++static int gpio_dev_release(struct inode *inode, struct file *file)
++{
++ struct gpio_item *gpio = file->private_data;
++ unsigned int irq;
++ unsigned int i;
+
-+ while (cdiv > 255) {
-+ ckdiv++;
-+ cdiv = cdiv >> 1;
++ gpio_dev_fasync(-1, file, 0);
++
++ for (i = 0; i < 32; i++) {
++ if (gpio->pin_mask & (1 << i)) {
++ irq = gpio_to_irq(32 * gpio->port + i);
++ free_irq(irq, gpio);
++ }
+ }
+
-+ if (ckdiv > 7)
-+ return -EINVAL;
-+ else
-+ twi_writel(twi, CWGR, (TWI_BF(CKDIV, ckdiv)
-+ | TWI_BF(CHDIV, cdiv)
-+ | TWI_BF(CLDIV, cdiv)));
++ config_item_put(&gpio->item);
++
+ 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)
++static unsigned int gpio_dev_poll(struct file *file, poll_table *wait)
+{
-+ int timeout = msecs_to_jiffies(100);
-+
-+ twi->intmask = mask;
-+ init_completion(&twi->comp);
-+
-+ twi_writel(twi, IER, mask);
++ struct gpio_item *gpio = file->private_data;
++ unsigned int mask = 0;
+
-+ if(!wait_for_completion_timeout(&twi->comp, timeout))
-+ return -ETIMEDOUT;
++ poll_wait(file, &gpio->change_wq, wait);
++ if (gpio->changed)
++ mask |= POLLIN | POLLRDNORM;
+
-+ return 0;
++ return mask;
+}
+
-+/*
-+ * Generic i2c master transfer entrypoint.
-+ */
-+static int twi_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
++static ssize_t gpio_dev_read(struct file *file, char __user *buf,
++ size_t count, loff_t *offset)
+{
-+ struct atmel_twi *twi = to_atmel_twi(adap);
-+ struct i2c_msg *pmsg;
-+ int i;
++ struct gpio_item *gpio = file->private_data;
++ u32 value;
+
-+ /* get first message */
-+ pmsg = msgs;
++ spin_lock_irq(&gpio->lock);
++ while (!gpio->changed) {
++ spin_unlock_irq(&gpio->lock);
+
-+ dev_dbg(&adap->dev, "twi_xfer: processing %d messages:\n", num);
++ if (file->f_flags & O_NONBLOCK)
++ return -EAGAIN;
+
-+ for (i = 0; i < num; i++, pmsg++) {
++ if (wait_event_interruptible(gpio->change_wq, gpio->changed))
++ return -ERESTARTSYS;
+
-+ 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));
++ spin_lock_irq(&gpio->lock);
++ }
+
-+ 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);
++ gpio->changed = 0;
++ value = at32_gpio_get_value_multiple(gpio->port, gpio->pin_mask);
+
-+ /* enable */
-+ twi_writel(twi, CR, TWI_BIT(MSEN));
++ spin_unlock_irq(&gpio->lock);
+
-+ 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;
-+ }
++ count = min(count, (size_t)4);
++ if (copy_to_user(buf, &value, count))
++ return -EFAULT;
+
-+ /* 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;
-+ }
++ return count;
++}
+
-+ } 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;
-+ }
-+ }
++static ssize_t gpio_dev_write(struct file *file, const char __user *buf,
++ size_t count, loff_t *offset)
++{
++ struct gpio_item *gpio = file->private_data;
++ u32 value = 0;
++ u32 mask = ~0UL;
+
-+ /* Disable TWI interface */
-+ twi_writel(twi, CR, TWI_BIT(MSDIS));
++ count = min(count, (size_t)4);
++ if (copy_from_user(&value, buf, count))
++ return -EFAULT;
+
-+ } /* end cur msg */
++ /* Assuming big endian */
++ mask <<= (4 - count) * 8;
++ mask &= gpio->pin_mask;
+
-+ return i;
++ at32_gpio_set_value_multiple(gpio->port, value, mask);
++
++ return count;
+}
+
++static struct file_operations gpio_dev_fops = {
++ .owner = THIS_MODULE,
++ .llseek = no_llseek,
++ .open = gpio_dev_open,
++ .release = gpio_dev_release,
++ .fasync = gpio_dev_fasync,
++ .poll = gpio_dev_poll,
++ .read = gpio_dev_read,
++ .write = gpio_dev_write,
++};
+
-+static irqreturn_t twi_interrupt(int irq, void *dev_id, struct pt_regs *regs)
++static struct gpio_item *to_gpio_item(struct config_item *item)
+{
-+ struct atmel_twi *twi = dev_id;
-+ int status = twi_readl(twi, SR);
++ return item ? container_of(item, struct gpio_item, item) : NULL;
++}
+
-+ 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;
++static ssize_t gpio_show_gpio_id(struct gpio_item *gpio, char *page)
++{
++ return sprintf(page, "%d\n", gpio->port);
++}
++
++static ssize_t gpio_store_gpio_id(struct gpio_item *gpio,
++ const char *page, size_t count)
++{
++ unsigned long id;
++ char *p = (char *)page;
++ ssize_t ret = -EINVAL;
++
++ id = simple_strtoul(p, &p, 0);
++ if (!p || (*p && (*p != '\n')))
++ return -EINVAL;
++
++ /* Switching PIO is not allowed when live... */
++ spin_lock(&gpio->lock);
++ if (!gpio->enabled) {
++ ret = -ENXIO;
++ if (at32_gpio_port_is_valid(id)) {
++ gpio->port = id;
++ ret = count;
+ }
+ }
++ spin_unlock(&gpio->lock);
+
-+ return IRQ_HANDLED;
++ return ret;
++}
+
-+nack:
-+ printk(KERN_INFO "NACK received!\n");
++static ssize_t gpio_show_pin_mask(struct gpio_item *gpio, char *page)
++{
++ return sprintf(page, "0x%08x\n", gpio->pin_mask);
++}
+
-+complete:
-+ twi_writel(twi, IDR, ~0UL);
-+ complete(&twi->comp);
++static ssize_t gpio_store_pin_mask(struct gpio_item *gpio,
++ const char *page, size_t count)
++{
++ u32 new_mask;
++ char *p = (char *)page;
++ ssize_t ret = -EINVAL;
+
-+ return IRQ_HANDLED;
++ new_mask = simple_strtoul(p, &p, 0);
++ if (!p || (*p && (*p != '\n')))
++ return -EINVAL;
+
-+}
++ /* Can't update the pin mask while live. */
++ spin_lock(&gpio->lock);
++ if (!gpio->enabled) {
++ gpio->oe_mask &= new_mask;
++ gpio->pin_mask = new_mask;
++ ret = count;
++ }
++ spin_unlock(&gpio->lock);
+
++ return ret;
++}
+
-+/*
-+ * Return list of supported functionality.
-+ */
-+static u32 twi_func(struct i2c_adapter *adapter)
++static ssize_t gpio_show_oe_mask(struct gpio_item *gpio, char *page)
+{
-+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
++ return sprintf(page, "0x%08x\n", gpio->oe_mask);
+}
+
-+/* 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)
++static ssize_t gpio_store_oe_mask(struct gpio_item *gpio,
++ const char *page, size_t count)
+{
-+ struct atmel_twi *twi;
-+ struct resource *regs;
-+ struct clk *pclk;
-+ struct i2c_adapter *adapter;
-+ int rc, irq;
++ u32 mask;
++ char *p = (char *)page;
++ ssize_t ret = -EINVAL;
+
-+ 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);
++ mask = simple_strtoul(p, &p, 0);
++ if (!p || (*p && (*p != '\n')))
++ return -EINVAL;
+
-+ 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;
++ spin_lock(&gpio->lock);
++ if (!gpio->enabled) {
++ gpio->oe_mask = mask & gpio->pin_mask;
++ ret = count;
+ }
++ spin_unlock(&gpio->lock);
+
-+ twi->pclk = pclk;
-+ twi->regs = ioremap(regs->start, regs->end - regs->start + 1);
-+ if (!twi->regs)
-+ goto err_ioremap;
++ return ret;
++}
+
-+ 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;
++static ssize_t gpio_show_enabled(struct gpio_item *gpio, char *page)
++{
++ return sprintf(page, "%d\n", gpio->enabled);
++}
+
-+ rc = twi_hwinit(twi);
-+ if (rc) {
-+ dev_err(&pdev->dev, "Unable to set baudrate\n");
-+ goto err_hw_init;
-+ }
++static ssize_t gpio_store_enabled(struct gpio_item *gpio,
++ const char *page, size_t count)
++{
++ char *p = (char *)page;
++ int enabled;
++ int ret;
+
-+ adapter = &twi->adapter;
-+ sprintf(adapter->name, "TWI");
-+ adapter->algo = &twi_algorithm;
-+ adapter->class = I2C_CLASS_HWMON;
-+ adapter->dev.parent = &pdev->dev;
++ enabled = simple_strtoul(p, &p, 0);
++ if (!p || (*p && (*p != '\n')))
++ return -EINVAL;
+
-+ platform_set_drvdata(pdev, twi);
++ /* make it a boolean value */
++ enabled = !!enabled;
+
-+ rc = i2c_add_adapter(adapter);
-+ if (rc) {
-+ dev_err(&pdev->dev, "Adapter %s registration failed\n",
-+ adapter->name);
-+ goto err_register;
++ if (gpio->enabled == enabled)
++ /* No change; do nothing. */
++ return count;
++
++ BUG_ON(gpio->id >= GPIO_DEV_MAX);
++
++ if (!enabled) {
++ class_device_unregister(gpio->gpio_dev);
++ cdev_del(&gpio->char_dev);
++ at32_deselect_pins(gpio->port, gpio->pin_mask);
++ gpio->initialized = 0;
++ } else {
++ if (gpio->port < 0 || !gpio->pin_mask)
++ return -ENODEV;
+ }
+
-+ dev_info(&pdev->dev, "Atmel TWI i2c bus device (baudrate %dk) at 0x%08lx.\n",
-+ baudrate/1000, (unsigned long)regs->start);
++ /* Disallow any updates to gpio_id or pin_mask */
++ spin_lock(&gpio->lock);
++ gpio->enabled = enabled;
++ spin_unlock(&gpio->lock);
+
-+ return 0;
++ if (!enabled)
++ return count;
+
++ /* Now, try to allocate the pins */
++ ret = at32_select_gpio_pins(gpio->port, gpio->pin_mask, gpio->oe_mask);
++ if (ret)
++ goto err_alloc_pins;
+
-+err_register:
-+ platform_set_drvdata(pdev, NULL);
++ gpio->initialized = 1;
+
-+err_hw_init:
-+ free_irq(irq, twi);
++ cdev_init(&gpio->char_dev, &gpio_dev_fops);
++ gpio->char_dev.owner = THIS_MODULE;
++ ret = cdev_add(&gpio->char_dev, MKDEV(MAJOR(gpio_devt), gpio->id), 1);
++ if (ret < 0)
++ goto err_cdev_add;
++ gpio->gpio_dev = class_device_create(gpio_dev_class, NULL,
++ MKDEV(MAJOR(gpio_devt), gpio->id),
++ NULL,
++ "gpio%d", gpio->id);
++ if (IS_ERR(gpio->gpio_dev)) {
++ printk(KERN_ERR "failed to create gpio%d\n", gpio->id);
++ ret = PTR_ERR(gpio->gpio_dev);
++ goto err_class_dev;
++ }
+
-+err_irq:
-+ iounmap(twi->regs);
++ printk(KERN_INFO "created gpio%d (port%d/0x%08x) as (%d:%d)\n",
++ gpio->id, gpio->port, gpio->pin_mask,
++ MAJOR(gpio->gpio_dev->devt), MINOR(gpio->gpio_dev->devt));
+
-+err_ioremap:
-+ kfree(twi);
++ return 0;
+
-+err_alloc_twi:
-+ clk_disable(pclk);
-+ clk_put(pclk);
++err_class_dev:
++ cdev_del(&gpio->char_dev);
++err_cdev_add:
++ at32_deselect_pins(gpio->port, gpio->pin_mask);
++ gpio->initialized = 0;
++err_alloc_pins:
++ spin_lock(&gpio->lock);
++ gpio->enabled = 0;
++ spin_unlock(&gpio->lock);
+
-+ return rc;
++ return ret;
+}
+
-+static int __devexit twi_remove(struct platform_device *pdev)
++static struct gpio_attribute gpio_item_attr_gpio_id = {
++ .attr = {
++ .ca_owner = THIS_MODULE,
++ .ca_name = "gpio_id",
++ .ca_mode = S_IRUGO | S_IWUSR,
++ },
++ .show = gpio_show_gpio_id,
++ .store = gpio_store_gpio_id,
++};
++static struct gpio_attribute gpio_item_attr_pin_mask = {
++ .attr = {
++ .ca_owner = THIS_MODULE,
++ .ca_name = "pin_mask",
++ .ca_mode = S_IRUGO | S_IWUSR,
++ },
++ .show = gpio_show_pin_mask,
++ .store = gpio_store_pin_mask,
++};
++static struct gpio_attribute gpio_item_attr_oe_mask = {
++ .attr = {
++ .ca_owner = THIS_MODULE,
++ .ca_name = "oe_mask",
++ .ca_mode = S_IRUGO | S_IWUSR,
++ },
++ .show = gpio_show_oe_mask,
++ .store = gpio_store_oe_mask,
++};
++static struct gpio_attribute gpio_item_attr_enabled = {
++ .attr = {
++ .ca_owner = THIS_MODULE,
++ .ca_name = "enabled",
++ .ca_mode = S_IRUGO | S_IWUSR,
++ },
++ .show = gpio_show_enabled,
++ .store = gpio_store_enabled,
++};
++
++static struct configfs_attribute *gpio_item_attrs[] = {
++ &gpio_item_attr_gpio_id.attr,
++ &gpio_item_attr_pin_mask.attr,
++ &gpio_item_attr_oe_mask.attr,
++ &gpio_item_attr_enabled.attr,
++ NULL,
++};
++
++static ssize_t gpio_show_attr(struct config_item *item,
++ struct configfs_attribute *attr,
++ char *page)
+{
-+ struct atmel_twi *twi = platform_get_drvdata(pdev);
-+ int res;
++ struct gpio_item *gpio_item = to_gpio_item(item);
++ struct gpio_attribute *gpio_attr
++ = container_of(attr, struct gpio_attribute, attr);
++ ssize_t ret = 0;
+
-+ 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);
++ if (gpio_attr->show)
++ ret = gpio_attr->show(gpio_item, page);
++ return ret;
++}
+
-+ return res;
++static ssize_t gpio_store_attr(struct config_item *item,
++ struct configfs_attribute *attr,
++ const char *page, size_t count)
++{
++ struct gpio_item *gpio_item = to_gpio_item(item);
++ struct gpio_attribute *gpio_attr
++ = container_of(attr, struct gpio_attribute, attr);
++ ssize_t ret = -EINVAL;
++
++ if (gpio_attr->store)
++ ret = gpio_attr->store(gpio_item, page, count);
++ return ret;
+}
+
-+static struct platform_driver twi_driver = {
-+ .probe = twi_probe,
-+ .remove = __devexit_p(twi_remove),
-+ .driver = {
-+ .name = "atmel_twi",
-+ .owner = THIS_MODULE,
++static void gpio_release(struct config_item *item)
++{
++ kfree(to_gpio_item(item));
++}
++
++static struct configfs_item_operations gpio_item_ops = {
++ .release = gpio_release,
++ .show_attribute = gpio_show_attr,
++ .store_attribute = gpio_store_attr,
++};
++
++static struct config_item_type gpio_item_type = {
++ .ct_item_ops = &gpio_item_ops,
++ .ct_attrs = gpio_item_attrs,
++ .ct_owner = THIS_MODULE,
++};
++
++static struct config_item *gpio_make_item(struct config_group *group,
++ const char *name)
++{
++ static int next_id;
++ struct gpio_item *gpio;
++
++ if (next_id >= GPIO_DEV_MAX)
++ return NULL;
++
++ gpio = kzalloc(sizeof(struct gpio_item), GFP_KERNEL);
++ if (!gpio)
++ return NULL;
++
++ gpio->id = next_id++;
++ config_item_init_type_name(&gpio->item, name, &gpio_item_type);
++ spin_lock_init(&gpio->lock);
++ init_waitqueue_head(&gpio->change_wq);
++
++ return &gpio->item;
++}
++
++static void gpio_drop_item(struct config_group *group,
++ struct config_item *item)
++{
++ struct gpio_item *gpio = to_gpio_item(item);
++
++ spin_lock(&gpio->lock);
++ if (gpio->enabled) {
++ class_device_unregister(gpio->gpio_dev);
++ cdev_del(&gpio->char_dev);
++ }
++
++ if (gpio->initialized) {
++ at32_deselect_pins(gpio->port, gpio->pin_mask);
++ gpio->initialized = 0;
++ gpio->enabled = 0;
++ }
++ spin_unlock(&gpio->lock);
++}
++
++static struct configfs_group_operations gpio_group_ops = {
++ .make_item = gpio_make_item,
++ .drop_item = gpio_drop_item,
++};
++
++static struct config_item_type gpio_group_type = {
++ .ct_group_ops = &gpio_group_ops,
++ .ct_owner = THIS_MODULE,
++};
++
++static struct configfs_subsystem gpio_subsys = {
++ .su_group = {
++ .cg_item = {
++ .ci_namebuf = "gpio",
++ .ci_type = &gpio_group_type,
++ },
+ },
+};
+
-+static int __init atmel_twi_init(void)
++static int __init gpio_dev_init(void)
+{
-+ return platform_driver_register(&twi_driver);
++ int err;
++
++ gpio_dev_class = class_create(THIS_MODULE, "gpio-dev");
++ if (IS_ERR(gpio_dev_class)) {
++ err = PTR_ERR(gpio_dev_class);
++ goto err_class_create;
++ }
++
++ err = alloc_chrdev_region(&gpio_devt, 0, GPIO_DEV_MAX, "gpio");
++ if (err < 0)
++ goto err_alloc_chrdev;
++
++ /* Configfs initialization */
++ config_group_init(&gpio_subsys.su_group);
++ init_MUTEX(&gpio_subsys.su_sem);
++ err = configfs_register_subsystem(&gpio_subsys);
++ if (err)
++ goto err_register_subsys;
++
++ return 0;
++
++err_register_subsys:
++ unregister_chrdev_region(gpio_devt, GPIO_DEV_MAX);
++err_alloc_chrdev:
++ class_destroy(gpio_dev_class);
++err_class_create:
++ printk(KERN_WARNING "Failed to initialize gpio /dev interface\n");
++ return err;
+}
++late_initcall(gpio_dev_init);
+diff -x .git -Nur linux-2.6.22.1/arch/avr32/mach-at32ap/Kconfig linux-avr32.git/arch/avr32/mach-at32ap/Kconfig
+--- linux-2.6.22.1/arch/avr32/mach-at32ap/Kconfig 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/arch/avr32/mach-at32ap/Kconfig 2007-07-12 13:59:49.000000000 +0200
+@@ -26,6 +26,13 @@
+
+ endchoice
+
++config GPIO_DEV
++ bool "GPIO /dev interface"
++ select CONFIGFS_FS
++ default n
++ help
++ Say `Y' to enable a /dev interface to the GPIO pins.
+
-+static void __exit atmel_twi_exit(void)
+ endmenu
+
+ endif # PLATFORM_AT32AP
+diff -x .git -Nur linux-2.6.22.1/arch/avr32/mach-at32ap/Makefile linux-avr32.git/arch/avr32/mach-at32ap/Makefile
+--- linux-2.6.22.1/arch/avr32/mach-at32ap/Makefile 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/arch/avr32/mach-at32ap/Makefile 2007-07-12 13:59:49.000000000 +0200
+@@ -1,3 +1,5 @@
+ 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
++obj-$(CONFIG_CPU_FREQ_AT32AP) += cpufreq.o
++obj-$(CONFIG_GPIO_DEV) += gpio-dev.o
+diff -x .git -Nur linux-2.6.22.1/arch/avr32/mach-at32ap/pio.c linux-avr32.git/arch/avr32/mach-at32ap/pio.c
+--- linux-2.6.22.1/arch/avr32/mach-at32ap/pio.c 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/arch/avr32/mach-at32ap/pio.c 2007-07-12 13:59:49.000000000 +0200
+@@ -158,6 +158,82 @@
+ dump_stack();
+ }
+
++#ifdef CONFIG_GPIO_DEV
++
++/* Gang allocators and accessors; used by the GPIO /dev driver */
++int at32_gpio_port_is_valid(unsigned int port)
+{
-+ platform_driver_unregister(&twi_driver);
++ return port < MAX_NR_PIO_DEVICES && pio_dev[port].regs != NULL;
+}
+
-+module_init(atmel_twi_init);
-+module_exit(atmel_twi_exit);
++int at32_select_gpio_pins(unsigned int port, u32 pins, u32 oe_mask)
++{
++ struct pio_device *pio;
++ u32 old, new;
+
-+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 @@
++ pio = &pio_dev[port];
++ BUG_ON(port > ARRAY_SIZE(pio_dev) || !pio->regs || (oe_mask & ~pins));
++
++ /* Try to allocate the pins */
++ do {
++ old = pio->pinmux_mask;
++ if (old & pins)
++ return -EBUSY;
++
++ new = old | pins;
++ } while (cmpxchg(&pio->pinmux_mask, old, new) != old);
++
++ /* That went well, now configure the port */
++ pio_writel(pio, OER, oe_mask);
++ pio_writel(pio, PER, pins);
++
++ return 0;
++}
++
++void at32_deselect_pins(unsigned int port, u32 pins)
++{
++ struct pio_device *pio;
++ u32 old, new;
++
++ pio = &pio_dev[port];
++ BUG_ON(port > ARRAY_SIZE(pio_dev) || !pio->regs);
++
++ /* Return to a "safe" mux configuration */
++ pio_writel(pio, PUER, pins);
++ pio_writel(pio, ODR, pins);
++
++ /* Deallocate the pins */
++ do {
++ old = pio->pinmux_mask;
++ new = old & ~pins;
++ } while (cmpxchg(&pio->pinmux_mask, old, new) != old);
++}
++
++u32 at32_gpio_get_value_multiple(unsigned int port, u32 pins)
++{
++ struct pio_device *pio;
++
++ pio = &pio_dev[port];
++ BUG_ON(port > ARRAY_SIZE(pio_dev) || !pio->regs);
++
++ return pio_readl(pio, PDSR) & pins;
++}
++
++void at32_gpio_set_value_multiple(unsigned int port, u32 value, u32 mask)
++{
++ struct pio_device *pio;
++
++ pio = &pio_dev[port];
++ BUG_ON(port > ARRAY_SIZE(pio_dev) || !pio->regs);
++
++ /* No atomic updates for now... */
++ pio_writel(pio, CODR, ~value & mask);
++ pio_writel(pio, SODR, value & mask);
++}
++
++#endif /* CONFIG_GPIO_DEV */
++
++
+ /*--------------------------------------------------------------------------*/
+
+ /* GPIO API */
+diff -x .git -Nur linux-2.6.22.1/arch/avr32/mach-at32ap/pm.h linux-avr32.git/arch/avr32/mach-at32ap/pm.h
+--- linux-2.6.22.1/arch/avr32/mach-at32ap/pm.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-avr32.git/arch/avr32/mach-at32ap/pm.h 2007-07-12 13:59:49.000000000 +0200
+@@ -0,0 +1,112 @@
++/*
++ * Register definitions for the Power Manager (PM)
++ */
++#ifndef __ARCH_AVR32_MACH_AT32AP_PM_H__
++#define __ARCH_AVR32_MACH_AT32AP_PM_H__
++
++/* PM register offsets */
++#define PM_MCCTRL 0x0000
++#define PM_CKSEL 0x0004
++#define PM_CPU_MASK 0x0008
++#define PM_HSB_MASK 0x000c
++#define PM_PBA_MASK 0x0010
++#define PM_PBB_MASK 0x0014
++#define PM_PLL0 0x0020
++#define PM_PLL1 0x0024
++#define PM_IER 0x0040
++#define PM_IDR 0x0044
++#define PM_IMR 0x0048
++#define PM_ISR 0x004c
++#define PM_ICR 0x0050
++#define PM_GCCTRL(x) (0x0060 + 4 * (x))
++#define PM_RCAUSE 0x00c0
++
++/* Bitfields in CKSEL */
++#define PM_CPUSEL_OFFSET 0
++#define PM_CPUSEL_SIZE 3
++#define PM_CPUDIV_OFFSET 7
++#define PM_CPUDIV_SIZE 1
++#define PM_HSBSEL_OFFSET 8
++#define PM_HSBSEL_SIZE 3
++#define PM_HSBDIV_OFFSET 15
++#define PM_HSBDIV_SIZE 1
++#define PM_PBASEL_OFFSET 16
++#define PM_PBASEL_SIZE 3
++#define PM_PBADIV_OFFSET 23
++#define PM_PBADIV_SIZE 1
++#define PM_PBBSEL_OFFSET 24
++#define PM_PBBSEL_SIZE 3
++#define PM_PBBDIV_OFFSET 31
++#define PM_PBBDIV_SIZE 1
++
++/* Bitfields in PLL0 */
++#define PM_PLLEN_OFFSET 0
++#define PM_PLLEN_SIZE 1
++#define PM_PLLOSC_OFFSET 1
++#define PM_PLLOSC_SIZE 1
++#define PM_PLLOPT_OFFSET 2
++#define PM_PLLOPT_SIZE 3
++#define PM_PLLDIV_OFFSET 8
++#define PM_PLLDIV_SIZE 8
++#define PM_PLLMUL_OFFSET 16
++#define PM_PLLMUL_SIZE 8
++#define PM_PLLCOUNT_OFFSET 24
++#define PM_PLLCOUNT_SIZE 6
++#define PM_PLLTEST_OFFSET 31
++#define PM_PLLTEST_SIZE 1
++
++/* Bitfields in ICR */
++#define PM_LOCK0_OFFSET 0
++#define PM_LOCK0_SIZE 1
++#define PM_LOCK1_OFFSET 1
++#define PM_LOCK1_SIZE 1
++#define PM_WAKE_OFFSET 2
++#define PM_WAKE_SIZE 1
++#define PM_CKRDY_OFFSET 5
++#define PM_CKRDY_SIZE 1
++#define PM_MSKRDY_OFFSET 6
++#define PM_MSKRDY_SIZE 1
++
++/* Bitfields in GCCTRL0 */
++#define PM_OSCSEL_OFFSET 0
++#define PM_OSCSEL_SIZE 1
++#define PM_PLLSEL_OFFSET 1
++#define PM_PLLSEL_SIZE 1
++#define PM_CEN_OFFSET 2
++#define PM_CEN_SIZE 1
++#define PM_DIVEN_OFFSET 4
++#define PM_DIVEN_SIZE 1
++#define PM_DIV_OFFSET 8
++#define PM_DIV_SIZE 8
++
++/* Bitfields in RCAUSE */
++#define PM_POR_OFFSET 0
++#define PM_POR_SIZE 1
++#define PM_EXT_OFFSET 2
++#define PM_EXT_SIZE 1
++#define PM_WDT_OFFSET 3
++#define PM_WDT_SIZE 1
++#define PM_NTAE_OFFSET 4
++#define PM_NTAE_SIZE 1
++
++/* Bit manipulation macros */
++#define PM_BIT(name) \
++ (1 << PM_##name##_OFFSET)
++#define PM_BF(name,value) \
++ (((value) & ((1 << PM_##name##_SIZE) - 1)) \
++ << PM_##name##_OFFSET)
++#define PM_BFEXT(name,value) \
++ (((value) >> PM_##name##_OFFSET) \
++ & ((1 << PM_##name##_SIZE) - 1))
++#define PM_BFINS(name,value,old)\
++ (((old) & ~(((1 << PM_##name##_SIZE) - 1) \
++ << PM_##name##_OFFSET)) \
++ | PM_BF(name,value))
++
++/* Register access macros */
++#define pm_readl(reg) \
++ __raw_readl((void __iomem *)AT32_PM_BASE + PM_##reg)
++#define pm_writel(reg,value) \
++ __raw_writel((value), (void __iomem *)AT32_PM_BASE + PM_##reg)
++
++#endif /* __ARCH_AVR32_MACH_AT32AP_PM_H__ */
+diff -x .git -Nur linux-2.6.22.1/arch/avr32/mach-at32ap/sm.h linux-avr32.git/arch/avr32/mach-at32ap/sm.h
+--- linux-2.6.22.1/arch/avr32/mach-at32ap/sm.h 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/arch/avr32/mach-at32ap/sm.h 1970-01-01 01:00:00.000000000 +0100
+@@ -1,242 +0,0 @@
+-/*
+- * Register definitions for SM
+- *
+- * System Manager
+- */
+-#ifndef __ASM_AVR32_SM_H__
+-#define __ASM_AVR32_SM_H__
+-
+-/* SM register offsets */
+-#define SM_PM_MCCTRL 0x0000
+-#define SM_PM_CKSEL 0x0004
+-#define SM_PM_CPU_MASK 0x0008
+-#define SM_PM_HSB_MASK 0x000c
+-#define SM_PM_PBA_MASK 0x0010
+-#define SM_PM_PBB_MASK 0x0014
+-#define SM_PM_PLL0 0x0020
+-#define SM_PM_PLL1 0x0024
+-#define SM_PM_VCTRL 0x0030
+-#define SM_PM_VMREF 0x0034
+-#define SM_PM_VMV 0x0038
+-#define SM_PM_IER 0x0040
+-#define SM_PM_IDR 0x0044
+-#define SM_PM_IMR 0x0048
+-#define SM_PM_ISR 0x004c
+-#define SM_PM_ICR 0x0050
+-#define SM_PM_GCCTRL 0x0060
+-#define SM_RTC_CTRL 0x0080
+-#define SM_RTC_VAL 0x0084
+-#define SM_RTC_TOP 0x0088
+-#define SM_RTC_IER 0x0090
+-#define SM_RTC_IDR 0x0094
+-#define SM_RTC_IMR 0x0098
+-#define SM_RTC_ISR 0x009c
+-#define SM_RTC_ICR 0x00a0
+-#define SM_WDT_CTRL 0x00b0
+-#define SM_WDT_CLR 0x00b4
+-#define SM_WDT_EXT 0x00b8
+-#define SM_RC_RCAUSE 0x00c0
+-#define SM_EIM_IER 0x0100
+-#define SM_EIM_IDR 0x0104
+-#define SM_EIM_IMR 0x0108
+-#define SM_EIM_ISR 0x010c
+-#define SM_EIM_ICR 0x0110
+-#define SM_EIM_MODE 0x0114
+-#define SM_EIM_EDGE 0x0118
+-#define SM_EIM_LEVEL 0x011c
+-#define SM_EIM_TEST 0x0120
+-#define SM_EIM_NMIC 0x0124
+-
+-/* Bitfields in PM_MCCTRL */
+-
+-/* Bitfields in PM_CKSEL */
+-#define SM_CPUSEL_OFFSET 0
+-#define SM_CPUSEL_SIZE 3
+-#define SM_CPUDIV_OFFSET 7
+-#define SM_CPUDIV_SIZE 1
+-#define SM_HSBSEL_OFFSET 8
+-#define SM_HSBSEL_SIZE 3
+-#define SM_HSBDIV_OFFSET 15
+-#define SM_HSBDIV_SIZE 1
+-#define SM_PBASEL_OFFSET 16
+-#define SM_PBASEL_SIZE 3
+-#define SM_PBADIV_OFFSET 23
+-#define SM_PBADIV_SIZE 1
+-#define SM_PBBSEL_OFFSET 24
+-#define SM_PBBSEL_SIZE 3
+-#define SM_PBBDIV_OFFSET 31
+-#define SM_PBBDIV_SIZE 1
+-
+-/* Bitfields in PM_CPU_MASK */
+-
+-/* Bitfields in PM_HSB_MASK */
+-
+-/* Bitfields in PM_PBA_MASK */
+-
+-/* Bitfields in PM_PBB_MASK */
+-
+-/* Bitfields in PM_PLL0 */
+-#define SM_PLLEN_OFFSET 0
+-#define SM_PLLEN_SIZE 1
+-#define SM_PLLOSC_OFFSET 1
+-#define SM_PLLOSC_SIZE 1
+-#define SM_PLLOPT_OFFSET 2
+-#define SM_PLLOPT_SIZE 3
+-#define SM_PLLDIV_OFFSET 8
+-#define SM_PLLDIV_SIZE 8
+-#define SM_PLLMUL_OFFSET 16
+-#define SM_PLLMUL_SIZE 8
+-#define SM_PLLCOUNT_OFFSET 24
+-#define SM_PLLCOUNT_SIZE 6
+-#define SM_PLLTEST_OFFSET 31
+-#define SM_PLLTEST_SIZE 1
+-
+-/* Bitfields in PM_PLL1 */
+-
+-/* Bitfields in PM_VCTRL */
+-#define SM_VAUTO_OFFSET 0
+-#define SM_VAUTO_SIZE 1
+-#define SM_PM_VCTRL_VAL_OFFSET 8
+-#define SM_PM_VCTRL_VAL_SIZE 7
+-
+-/* Bitfields in PM_VMREF */
+-#define SM_REFSEL_OFFSET 0
+-#define SM_REFSEL_SIZE 4
+-
+-/* Bitfields in PM_VMV */
+-#define SM_PM_VMV_VAL_OFFSET 0
+-#define SM_PM_VMV_VAL_SIZE 8
+-
+-/* Bitfields in PM_IER */
+-
+-/* Bitfields in PM_IDR */
+-
+-/* Bitfields in PM_IMR */
+-
+-/* Bitfields in PM_ISR */
+-
+-/* Bitfields in PM_ICR */
+-#define SM_LOCK0_OFFSET 0
+-#define SM_LOCK0_SIZE 1
+-#define SM_LOCK1_OFFSET 1
+-#define SM_LOCK1_SIZE 1
+-#define SM_WAKE_OFFSET 2
+-#define SM_WAKE_SIZE 1
+-#define SM_VOK_OFFSET 3
+-#define SM_VOK_SIZE 1
+-#define SM_VMRDY_OFFSET 4
+-#define SM_VMRDY_SIZE 1
+-#define SM_CKRDY_OFFSET 5
+-#define SM_CKRDY_SIZE 1
+-
+-/* Bitfields in PM_GCCTRL */
+-#define SM_OSCSEL_OFFSET 0
+-#define SM_OSCSEL_SIZE 1
+-#define SM_PLLSEL_OFFSET 1
+-#define SM_PLLSEL_SIZE 1
+-#define SM_CEN_OFFSET 2
+-#define SM_CEN_SIZE 1
+-#define SM_CPC_OFFSET 3
+-#define SM_CPC_SIZE 1
+-#define SM_DIVEN_OFFSET 4
+-#define SM_DIVEN_SIZE 1
+-#define SM_DIV_OFFSET 8
+-#define SM_DIV_SIZE 8
+-
+-/* Bitfields in RTC_CTRL */
+-#define SM_PCLR_OFFSET 1
+-#define SM_PCLR_SIZE 1
+-#define SM_TOPEN_OFFSET 2
+-#define SM_TOPEN_SIZE 1
+-#define SM_CLKEN_OFFSET 3
+-#define SM_CLKEN_SIZE 1
+-#define SM_PSEL_OFFSET 8
+-#define SM_PSEL_SIZE 16
+-
+-/* Bitfields in RTC_VAL */
+-#define SM_RTC_VAL_VAL_OFFSET 0
+-#define SM_RTC_VAL_VAL_SIZE 31
+-
+-/* Bitfields in RTC_TOP */
+-#define SM_RTC_TOP_VAL_OFFSET 0
+-#define SM_RTC_TOP_VAL_SIZE 32
+-
+-/* Bitfields in RTC_IER */
+-
+-/* Bitfields in RTC_IDR */
+-
+-/* Bitfields in RTC_IMR */
+-
+-/* Bitfields in RTC_ISR */
+-
+-/* Bitfields in RTC_ICR */
+-#define SM_TOPI_OFFSET 0
+-#define SM_TOPI_SIZE 1
+-
+-/* Bitfields in WDT_CTRL */
+-#define SM_KEY_OFFSET 24
+-#define SM_KEY_SIZE 8
+-
+-/* Bitfields in WDT_CLR */
+-
+-/* Bitfields in WDT_EXT */
+-
+-/* Bitfields in RC_RCAUSE */
+-#define SM_POR_OFFSET 0
+-#define SM_POR_SIZE 1
+-#define SM_BOD_OFFSET 1
+-#define SM_BOD_SIZE 1
+-#define SM_EXT_OFFSET 2
+-#define SM_EXT_SIZE 1
+-#define SM_WDT_OFFSET 3
+-#define SM_WDT_SIZE 1
+-#define SM_NTAE_OFFSET 4
+-#define SM_NTAE_SIZE 1
+-#define SM_SERP_OFFSET 5
+-#define SM_SERP_SIZE 1
+-
+-/* Bitfields in EIM_IER */
+-
+-/* Bitfields in EIM_IDR */
+-
+-/* Bitfields in EIM_IMR */
+-
+-/* Bitfields in EIM_ISR */
+-
+-/* Bitfields in EIM_ICR */
+-
+-/* Bitfields in EIM_MODE */
+-
+-/* Bitfields in EIM_EDGE */
+-#define SM_INT0_OFFSET 0
+-#define SM_INT0_SIZE 1
+-#define SM_INT1_OFFSET 1
+-#define SM_INT1_SIZE 1
+-#define SM_INT2_OFFSET 2
+-#define SM_INT2_SIZE 1
+-#define SM_INT3_OFFSET 3
+-#define SM_INT3_SIZE 1
+-
+-/* Bitfields in EIM_LEVEL */
+-
+-/* Bitfields in EIM_TEST */
+-#define SM_TESTEN_OFFSET 31
+-#define SM_TESTEN_SIZE 1
+-
+-/* Bitfields in EIM_NMIC */
+-#define SM_EN_OFFSET 0
+-#define SM_EN_SIZE 1
+-
+-/* Bit manipulation macros */
+-#define SM_BIT(name) (1 << SM_##name##_OFFSET)
+-#define SM_BF(name,value) (((value) & ((1 << SM_##name##_SIZE) - 1)) << SM_##name##_OFFSET)
+-#define SM_BFEXT(name,value) (((value) >> SM_##name##_OFFSET) & ((1 << SM_##name##_SIZE) - 1))
+-#define SM_BFINS(name,value,old) (((old) & ~(((1 << SM_##name##_SIZE) - 1) << SM_##name##_OFFSET)) | SM_BF(name,value))
+-
+-/* Register access macros */
+-#define sm_readl(port,reg) \
+- __raw_readl((port)->regs + SM_##reg)
+-#define sm_writel(port,reg,value) \
+- __raw_writel((value), (port)->regs + SM_##reg)
+-
+-#endif /* __ASM_AVR32_SM_H__ */
+diff -x .git -Nur linux-2.6.22.1/arch/avr32/Makefile linux-avr32.git/arch/avr32/Makefile
+--- linux-2.6.22.1/arch/avr32/Makefile 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/arch/avr32/Makefile 2007-06-06 11:33:46.000000000 +0200
+@@ -31,6 +31,7 @@
+ 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 -x .git -Nur linux-2.6.22.1/arch/avr32/mm/dma-coherent.c linux-avr32.git/arch/avr32/mm/dma-coherent.c
+--- linux-2.6.22.1/arch/avr32/mm/dma-coherent.c 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/arch/avr32/mm/dma-coherent.c 2007-07-12 13:59:49.000000000 +0200
+@@ -41,6 +41,13 @@
+ struct page *page, *free, *end;
+ int order;
+
++ /* Following is a work-around (a.k.a. hack) to prevent pages
++ * with __GFP_COMP being passed to split_page() which cannot
++ * handle them. The real problem is that this flag probably
++ * should be 0 on AVR32 as it is not supported on this
++ * platform--see CONFIG_HUGETLB_PAGE. */
++ gfp &= ~(__GFP_COMP);
++
+ size = PAGE_ALIGN(size);
+ order = get_order(size);
+
+diff -x .git -Nur linux-2.6.22.1/drivers/char/watchdog/at32ap700x_wdt.c linux-avr32.git/drivers/char/watchdog/at32ap700x_wdt.c
+--- linux-2.6.22.1/drivers/char/watchdog/at32ap700x_wdt.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-avr32.git/drivers/char/watchdog/at32ap700x_wdt.c 2007-07-12 13:59:59.000000000 +0200
+@@ -0,0 +1,325 @@
+/*
-+ * Bitbanging I2C bus driver using the GPIO API
++ * Watchdog driver for Atmel AT32AP700X devices
+ *
-+ * Copyright (C) 2007 Atmel Corporation
++ * 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/i2c.h>
-+#include <linux/i2c-algo-bit.h>
-+#include <linux/i2c-gpio.h>
++
+#include <linux/init.h>
++#include <linux/kernel.h>
+#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/miscdevice.h>
++#include <linux/fs.h>
+#include <linux/platform_device.h>
++#include <linux/watchdog.h>
++#include <linux/uaccess.h>
++#include <linux/io.h>
+
-+#include <asm/gpio.h>
++#define TIMEOUT_MIN 1
++#define TIMEOUT_DEFAULT CONFIG_AT32AP700X_WDT_TIMEOUT
++#define TIMEOUT_MAX 2
+
-+/* 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;
++/* Watchdog registers and write/read macro */
++#define WDT_CTRL 0x00
++#define WDT_CTRL_EN 0
++#define WDT_CTRL_PSEL 8
++#define WDT_CTRL_KEY 24
+
-+ if (state)
-+ gpio_direction_input(pdata->sda_pin);
-+ else
-+ gpio_direction_output(pdata->sda_pin, 0);
-+}
++#define WDT_CLR 0x04
++
++#define WDT_BIT(name) (1 << WDT_##name)
++#define WDT_BF(name,value) ((value) << WDT_##name)
++
++#define wdt_readl(dev,reg) \
++ __raw_readl((dev)->regs + WDT_##reg)
++#define wdt_writel(dev,reg,value) \
++ __raw_writel((value), (dev)->regs + WDT_##reg)
++
++struct wdt_at32ap700x {
++ void __iomem *regs;
++ int timeout;
++ int users;
++ struct miscdevice miscdev;
++};
++
++static struct wdt_at32ap700x *wdt;
+
+/*
-+ * 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.)
++ * Disable the watchdog.
+ */
-+static void i2c_gpio_setsda_val(void *data, int state)
++static void inline at32_wdt_stop(void)
+{
-+ struct i2c_gpio_platform_data *pdata = data;
-+
-+ gpio_set_value(pdata->sda_pin, state);
++ unsigned long psel = wdt_readl(wdt, CTRL) & WDT_BF(CTRL_PSEL, 0x0f);
++ wdt_writel(wdt, CTRL, psel | WDT_BF(CTRL_KEY, 0x55));
++ wdt_writel(wdt, CTRL, psel | WDT_BF(CTRL_KEY, 0xaa));
+}
+
-+/* Toggle SCL by changing the direction of the pin. */
-+static void i2c_gpio_setscl_dir(void *data, int state)
++/*
++ * Enable and reset the watchdog.
++ */
++static void inline at32_wdt_start(void)
+{
-+ struct i2c_gpio_platform_data *pdata = data;
++ /* 0xf is 2^16 divider = 2 sec, 0xe is 2^15 divider = 1 sec */
++ unsigned long psel = (wdt->timeout > 1) ? 0xf : 0xe;
+
-+ if (state)
-+ gpio_direction_input(pdata->scl_pin);
-+ else
-+ gpio_direction_output(pdata->scl_pin, 0);
++ wdt_writel(wdt, CTRL, WDT_BIT(CTRL_EN)
++ | WDT_BF(CTRL_PSEL, psel)
++ | WDT_BF(CTRL_KEY, 0x55));
++ wdt_writel(wdt, CTRL, WDT_BIT(CTRL_EN)
++ | WDT_BF(CTRL_PSEL, psel)
++ | WDT_BF(CTRL_KEY, 0xaa));
+}
+
+/*
-+ * 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.
++ * Pat the watchdog timer.
+ */
-+static void i2c_gpio_setscl_val(void *data, int state)
++static void inline at32_wdt_pat(void)
+{
-+ struct i2c_gpio_platform_data *pdata = data;
-+
-+ gpio_set_value(pdata->scl_pin, state);
++ wdt_writel(wdt, CLR, 0x42);
+}
+
-+int i2c_gpio_getsda(void *data)
++/*
++ * Watchdog device is opened, and watchdog starts running.
++ */
++static int at32_wdt_open(struct inode *inode, struct file *file)
+{
-+ struct i2c_gpio_platform_data *pdata = data;
++ if (test_and_set_bit(1, &wdt->users))
++ return -EBUSY;
+
-+ return gpio_get_value(pdata->sda_pin);
++ at32_wdt_start();
++ return nonseekable_open(inode, file);
+}
+
-+int i2c_gpio_getscl(void *data)
++/*
++ * Close the watchdog device. If CONFIG_WATCHDOG_NOWAYOUT is _not_ defined then
++ * the watchdog is also disabled.
++ */
++static int at32_wdt_close(struct inode *inode, struct file *file)
+{
-+ struct i2c_gpio_platform_data *pdata = data;
-+
-+ return gpio_get_value(pdata->scl_pin);
++#ifndef CONFIG_WATCHDOG_NOWAYOUT
++ at32_wdt_stop();
++#endif
++ clear_bit(1, &wdt->users);
++ return 0;
+}
+
-+static int __init i2c_gpio_probe(struct platform_device *pdev)
++/*
++ * Change the watchdog time interval.
++ */
++static int at32_wdt_settimeout(int time)
+{
-+ struct i2c_gpio_platform_data *pdata;
-+ struct i2c_algo_bit_data *bit_data;
-+ struct i2c_adapter *adap;
-+ int ret;
++ /*
++ * All counting occurs at 1 / SLOW_CLOCK (32 kHz) and max prescaler is
++ * 2 ^ 16 allowing up to 2 seconds timeout.
++ */
++ if ((time < TIMEOUT_MIN) || (time > TIMEOUT_MAX))
++ return -EINVAL;
+
-+ pdata = pdev->dev.platform_data;
-+ if (!pdata)
-+ return -ENXIO;
++ /*
++ * Set new watchdog time. It will be used when at32_wdt_start() is
++ * called.
++ */
++ wdt->timeout = time;
++ return 0;
++}
+
-+ 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;
++static struct watchdog_info at32_wdt_info = {
++ .identity = "at32ap700x watchdog",
++ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
++};
+
-+ 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;
++/*
++ * Handle commands from user-space.
++ */
++static int at32_wdt_ioctl(struct inode *inode, struct file *file,
++ unsigned int cmd, unsigned long arg)
++{
++ int ret = -ENOTTY;
++ int time;
++ void __user *argp = (void __user *)arg;
++ int __user *p = argp;
++
++ switch (cmd) {
++ case WDIOC_KEEPALIVE:
++ at32_wdt_pat();
++ ret = 0;
++ break;
++ case WDIOC_GETSUPPORT:
++ ret = copy_to_user(argp, &at32_wdt_info,
++ sizeof(at32_wdt_info)) ? -EFAULT : 0;
++ break;
++ case WDIOC_SETTIMEOUT:
++ ret = get_user(time, p);
++ if (ret)
++ break;
++ ret = at32_wdt_settimeout(time);
++ if (ret)
++ break;
++ /* Enable new time value */
++ at32_wdt_start();
++ /* fall through */
++ case WDIOC_GETTIMEOUT:
++ ret = put_user(wdt->timeout, p);
++ break;
++ case WDIOC_GETSTATUS: /* fall through */
++ case WDIOC_GETBOOTSTATUS:
++ ret = put_user(0, p);
++ break;
++ case WDIOC_SETOPTIONS:
++ ret = get_user(time, p);
++ if (ret)
++ break;
++ if (time & WDIOS_DISABLECARD)
++ at32_wdt_stop();
++ if (time & WDIOS_ENABLECARD)
++ at32_wdt_start();
++ ret = 0;
++ break;
+ }
+
-+ 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;
-+ }
++ return ret;
++}
+
-+ if (!pdata->scl_is_output_only)
-+ bit_data->getscl = i2c_gpio_getscl;
-+ bit_data->getsda = i2c_gpio_getsda;
++static ssize_t at32_wdt_write(struct file *file, const char *data, size_t len,
++ loff_t *ppos)
++{
++ at32_wdt_pat();
++ return len;
++}
+
-+ 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 */
++static const struct file_operations at32_wdt_fops = {
++ .owner = THIS_MODULE,
++ .llseek = no_llseek,
++ .ioctl = at32_wdt_ioctl,
++ .open = at32_wdt_open,
++ .release = at32_wdt_close,
++ .write = at32_wdt_write,
++};
+
-+ if (pdata->timeout)
-+ bit_data->timeout = pdata->timeout;
-+ else
-+ bit_data->timeout = HZ / 10; /* 100 ms */
++static int __init at32_wdt_probe(struct platform_device *pdev)
++{
++ struct resource *regs;
++ int ret;
++
++ if (wdt) {
++ dev_dbg(&pdev->dev, "only 1 wdt instance supported.\n");
++ return -EBUSY;
++ }
+
-+ bit_data->data = pdata;
++ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!regs) {
++ dev_dbg(&pdev->dev, "missing mmio resource\n");
++ return -ENXIO;
++ }
+
-+ 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;
++ wdt = kzalloc(sizeof(struct wdt_at32ap700x), GFP_KERNEL);
++ if (!wdt) {
++ dev_dbg(&pdev->dev, "no memory for wdt structure\n");
++ return -ENOMEM;
++ }
+
-+ ret = i2c_bit_add_bus(adap);
-+ if (ret)
-+ goto err_add_bus;
++ wdt->regs = ioremap(regs->start, regs->end - regs->start + 1);
++ if (!wdt->regs) {
++ ret = -ENOMEM;
++ dev_dbg(&pdev->dev, "could not map I/O memory\n");
++ goto err_free;
++ }
++ wdt->users = 0;
++ wdt->miscdev.minor = WATCHDOG_MINOR;
++ wdt->miscdev.name = "watchdog";
++ wdt->miscdev.fops = &at32_wdt_fops;
++
++ if (at32_wdt_settimeout(TIMEOUT_DEFAULT)) {
++ at32_wdt_settimeout(TIMEOUT_MAX);
++ dev_dbg(&pdev->dev,
++ "default timeout invalid, set to %d sec.\n",
++ TIMEOUT_MAX);
++ }
+
-+ platform_set_drvdata(pdev, adap);
++ ret = misc_register(&wdt->miscdev);
++ if (ret) {
++ dev_dbg(&pdev->dev, "failed to register wdt miscdev\n");
++ goto err_iounmap;
++ }
+
-+ 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" : "");
++ platform_set_drvdata(pdev, wdt);
++ wdt->miscdev.parent = &pdev->dev;
++ dev_info(&pdev->dev, "AT32AP700X WDT at 0x%p\n", wdt->regs);
+
+ 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:
++err_iounmap:
++ iounmap(wdt->regs);
++err_free:
++ kfree(wdt);
++ wdt = NULL;
+ return ret;
+}
+
-+static int __exit i2c_gpio_remove(struct platform_device *pdev)
++static int __exit at32_wdt_remove(struct platform_device *pdev)
+{
-+ struct i2c_gpio_platform_data *pdata;
-+ struct i2c_adapter *adap;
++ if (wdt && platform_get_drvdata(pdev) == wdt) {
++ misc_deregister(&wdt->miscdev);
++ iounmap(wdt->regs);
++ kfree(wdt);
++ wdt = NULL;
++ platform_set_drvdata(pdev, NULL);
++ }
+
-+ adap = platform_get_drvdata(pdev);
-+ pdata = pdev->dev.platform_data;
++ return 0;
++}
++
++static void at32_wdt_shutdown(struct platform_device *pdev)
++{
++ at32_wdt_stop();
++}
+
-+ i2c_del_adapter(adap);
-+ gpio_free(pdata->scl_pin);
-+ gpio_free(pdata->sda_pin);
-+ kfree(adap->algo_data);
-+ kfree(adap);
++#ifdef CONFIG_PM
++static int at32_wdt_suspend(struct platform_device *pdev, pm_message_t message)
++{
++ at32_wdt_stop();
++ return 0;
++}
+
++static int at32_wdt_resume(struct platform_device *pdev)
++{
++ if (wdt->users)
++ at32_wdt_start();
+ return 0;
+}
++#else
++#define at32_wdt_suspend NULL
++#define at32_wdt_resume NULL
++#endif
+
-+static struct platform_driver i2c_gpio_driver = {
++static struct platform_driver at32_wdt_driver = {
++ .remove = __exit_p(at32_wdt_remove),
++ .suspend = at32_wdt_suspend,
++ .resume = at32_wdt_resume,
+ .driver = {
-+ .name = "i2c-gpio",
++ .name = "at32_wdt",
+ .owner = THIS_MODULE,
+ },
-+ .remove = __exit_p(i2c_gpio_remove),
++ .shutdown = at32_wdt_shutdown,
+};
+
-+static int __init i2c_gpio_init(void)
++static int __init at32_wdt_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;
++ return platform_driver_probe(&at32_wdt_driver, at32_wdt_probe);
+}
-+module_init(i2c_gpio_init);
++module_init(at32_wdt_init);
+
-+static void __exit i2c_gpio_exit(void)
++static void __exit at32_wdt_exit(void)
+{
-+ platform_driver_unregister(&i2c_gpio_driver);
++ platform_driver_unregister(&at32_wdt_driver);
+}
-+module_exit(i2c_gpio_exit);
++module_exit(at32_wdt_exit);
+
-+MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>");
-+MODULE_DESCRIPTION("Platform-independent bitbanging I2C driver");
++MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>");
++MODULE_DESCRIPTION("Watchdog driver for Atmel AT32AP700X");
+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
++MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+diff -x .git -Nur linux-2.6.22.1/drivers/char/watchdog/Kconfig linux-avr32.git/drivers/char/watchdog/Kconfig
+--- linux-2.6.22.1/drivers/char/watchdog/Kconfig 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/drivers/char/watchdog/Kconfig 2007-07-12 13:59:59.000000000 +0200
+@@ -187,6 +187,26 @@
-+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
+ Say N if you are unsure.
+
++# AVR32 Architecture
+
-+config I2C_ATMELTWI_BAUDRATE
-+ prompt "Atmel TWI baudrate"
-+ depends on I2C_ATMELTWI
-+ int
-+ default 100000
++config AT32AP700X_WDT
++ tristate "AT32AP700x watchdog"
++ depends on WATCHDOG && CPU_AT32AP7000
+ 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
++ Watchdog timer embedded into AT32AP700x devices. This will reboot
++ your system when the timeout is reached.
++
++config AT32AP700X_WDT_TIMEOUT
++ int "Timeout value for AT32AP700x watchdog"
++ depends on AT32AP700X_WDT
++ default "2"
++ range 1 2
+ 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 @@
++ Sets the timeout value for the watchdog in AT32AP700x devices.
++ Limited by hardware to be 1 or 2 seconds.
++
++ Set to 2 seconds by default.
++
+ # X86 (i386 + ia64 + x86_64) Architecture
+
+ config ACQUIRE_WDT
+diff -x .git -Nur linux-2.6.22.1/drivers/char/watchdog/Makefile linux-avr32.git/drivers/char/watchdog/Makefile
+--- linux-2.6.22.1/drivers/char/watchdog/Makefile 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/drivers/char/watchdog/Makefile 2007-07-12 13:59:59.000000000 +0200
+@@ -36,6 +36,9 @@
+ obj-$(CONFIG_EP93XX_WATCHDOG) += ep93xx_wdt.o
+ obj-$(CONFIG_PNX4008_WATCHDOG) += pnx4008_wdt.o
+
++# AVR32 Architecture
++obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
++
+ # X86 (i386 + ia64 + x86_64) Architecture
+ obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o
+ obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o
+diff -x .git -Nur linux-2.6.22.1/drivers/i2c/busses/atmeltwi.h linux-avr32.git/drivers/i2c/busses/atmeltwi.h
+--- linux-2.6.22.1/drivers/i2c/busses/atmeltwi.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-avr32.git/drivers/i2c/busses/atmeltwi.h 2007-06-06 11:33:51.000000000 +0200
+@@ -0,0 +1,117 @@
+/*
-+ * Atmel MultiMedia Card Interface driver
++ * 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 -x .git -Nur linux-2.6.22.1/drivers/i2c/busses/i2c-atmeltwi.c linux-avr32.git/drivers/i2c/busses/i2c-atmeltwi.c
+--- linux-2.6.22.1/drivers/i2c/busses/i2c-atmeltwi.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-avr32.git/drivers/i2c/busses/i2c-atmeltwi.c 2007-07-12 13:59:59.000000000 +0200
+@@ -0,0 +1,348 @@
++/*
++ * i2c Support for Atmel's Two-Wire Interface (TWI)
+ *
-+ * Copyright (C) 2004-2006 Atmel Corporation
++ * 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 version 2 as
-+ * published by the Free Software Foundation.
++ * 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/blkdev.h>
-+#include <linux/clk.h>
-+#include <linux/device.h>
-+#include <linux/dma-mapping.h>
++
++
++#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/ioport.h>
-+#include <linux/module.h>
++#include <linux/irq.h>
+#include <linux/platform_device.h>
-+
-+#include <linux/mmc/host.h>
-+#include <linux/mmc/protocol.h>
-+
-+#include <asm/dma-controller.h>
++#include <linux/completion.h>
+#include <asm/io.h>
-+#include <asm/arch/board.h>
-+#include <asm/arch/gpio.h>
++#include <linux/time.h>
++#include "atmeltwi.h"
+
-+#include "atmel-mci.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");
+
-+#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))
++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;
+
-+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,
+};
++#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 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 -x .git -Nur linux-2.6.22.1/drivers/i2c/busses/Kconfig linux-avr32.git/drivers/i2c/busses/Kconfig
+--- linux-2.6.22.1/drivers/i2c/busses/Kconfig 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/drivers/i2c/busses/Kconfig 2007-07-12 13:59:59.000000000 +0200
+@@ -4,6 +4,26 @@
+
+ menu "I2C Hardware Bus support"
+
++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 PCI
+diff -x .git -Nur linux-2.6.22.1/drivers/i2c/busses/Makefile linux-avr32.git/drivers/i2c/busses/Makefile
+--- linux-2.6.22.1/drivers/i2c/busses/Makefile 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/drivers/i2c/busses/Makefile 2007-07-12 13:59:59.000000000 +0200
+@@ -52,6 +52,7 @@
+ obj-$(CONFIG_I2C_VOODOO3) += i2c-voodoo3.o
+ obj-$(CONFIG_SCx200_ACB) += scx200_acb.o
+ obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o
++obj-$(CONFIG_I2C_ATMELTWI) += i2c-atmeltwi.o
+
+ ifeq ($(CONFIG_I2C_DEBUG_BUS),y)
+ EXTRA_CFLAGS += -DDEBUG
+diff -x .git -Nur linux-2.6.22.1/drivers/leds/Kconfig linux-avr32.git/drivers/leds/Kconfig
+--- linux-2.6.22.1/drivers/leds/Kconfig 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/drivers/leds/Kconfig 2007-07-12 14:00:02.000000000 +0200
+@@ -95,6 +95,14 @@
+ help
+ This option enables support for the front LED on Cobalt Server
+
++config LEDS_GPIO
++ tristate "LED Support for GPIO connected LEDs"
++ depends on LEDS_CLASS && GENERIC_GPIO
++ help
++ This option enables support for the LEDs connected to GPIO
++ outputs. To be useful the particular board must have LEDs
++ and they must be connected to the GPIO lines.
++
+ comment "LED Triggers"
+
+ config LEDS_TRIGGERS
+diff -x .git -Nur linux-2.6.22.1/drivers/leds/leds-gpio.c linux-avr32.git/drivers/leds/leds-gpio.c
+--- linux-2.6.22.1/drivers/leds/leds-gpio.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-avr32.git/drivers/leds/leds-gpio.c 2007-07-12 14:00:02.000000000 +0200
+@@ -0,0 +1,199 @@
++/*
++ * LEDs driver for GPIOs
++ *
++ * Copyright (C) 2007 8D Technologies inc.
++ * Raphael Assenat <raph@8d.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ */
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/leds.h>
++#include <linux/workqueue.h>
++
++#include <asm/gpio.h>
++
++struct gpio_led_data {
++ struct led_classdev cdev;
++ unsigned gpio;
++ struct work_struct work;
++ u8 new_level;
++ u8 can_sleep;
++ u8 active_low;
++};
++
++static void gpio_led_work(struct work_struct *work)
++{
++ struct gpio_led_data *led_dat =
++ container_of(work, struct gpio_led_data, work);
++
++ gpio_set_value_cansleep(led_dat->gpio, led_dat->new_level);
++}
++
++static void gpio_led_set(struct led_classdev *led_cdev,
++ enum led_brightness value)
++{
++ struct gpio_led_data *led_dat =
++ container_of(led_cdev, struct gpio_led_data, cdev);
++ int level;
++
++ if (value == LED_OFF)
++ level = 0;
++ else
++ level = 1;
++
++ if (led_dat->active_low)
++ level = !level;
++
++ /* setting GPIOs with I2C/etc requires a preemptible task context */
++ if (led_dat->can_sleep) {
++ if (preempt_count()) {
++ led_dat->new_level = level;
++ schedule_work(&led_dat->work);
++ } else
++ gpio_set_value_cansleep(led_dat->gpio, level);
++ } else
++ gpio_set_value(led_dat->gpio, level);
++}
++
++static int __init gpio_led_probe(struct platform_device *pdev)
++{
++ struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
++ struct gpio_led *cur_led;
++ struct gpio_led_data *leds_data, *led_dat;
++ int i, ret = 0;
++
++ if (!pdata)
++ return -EBUSY;
++
++ leds_data = kzalloc(sizeof(struct gpio_led_data) * pdata->num_leds,
++ GFP_KERNEL);
++ if (!leds_data)
++ return -ENOMEM;
++
++ for (i = 0; i < pdata->num_leds; i++) {
++ cur_led = &pdata->leds[i];
++ led_dat = &leds_data[i];
++
++ led_dat->cdev.name = cur_led->name;
++ led_dat->cdev.default_trigger = cur_led->default_trigger;
++ led_dat->gpio = cur_led->gpio;
++ led_dat->can_sleep = gpio_cansleep(cur_led->gpio);
++ led_dat->active_low = cur_led->active_low;
++ led_dat->cdev.brightness_set = gpio_led_set;
++ led_dat->cdev.brightness = cur_led->active_low ? LED_FULL : LED_OFF;
++
++ ret = gpio_request(led_dat->gpio, led_dat->cdev.name);
++ if (ret < 0)
++ goto err;
++
++ gpio_direction_output(led_dat->gpio, led_dat->active_low);
++
++ ret = led_classdev_register(&pdev->dev, &led_dat->cdev);
++ if (ret < 0) {
++ gpio_free(led_dat->gpio);
++ goto err;
++ }
++
++ INIT_WORK(&led_dat->work, gpio_led_work);
++ }
++
++ platform_set_drvdata(pdev, leds_data);
++
++ return 0;
++
++err:
++ if (i > 0) {
++ for (i = i - 1; i >= 0; i--) {
++ led_classdev_unregister(&leds_data[i].cdev);
++ gpio_free(leds_data[i].gpio);
++ }
++ }
++
++ flush_scheduled_work();
++ kfree(leds_data);
++
++ return ret;
++}
++
++static int __exit gpio_led_remove(struct platform_device *pdev)
++{
++ int i;
++ struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
++ struct gpio_led_data *leds_data;
++
++ leds_data = platform_get_drvdata(pdev);
++
++ for (i = 0; i < pdata->num_leds; i++) {
++ led_classdev_unregister(&leds_data[i].cdev);
++ gpio_free(leds_data[i].gpio);
++ }
++
++ kfree(leds_data);
++
++ return 0;
++}
++
++#ifdef CONFIG_PM
++static int gpio_led_suspend(struct platform_device *pdev, pm_message_t state)
++{
++ struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
++ struct gpio_led_data *leds_data;
++ int i;
++
++ leds_data = platform_get_drvdata(pdev);
++
++ for (i = 0; i < pdata->num_leds; i++)
++ led_classdev_suspend(&leds_data[i].cdev);
++
++ return 0;
++}
++
++static int gpio_led_resume(struct platform_device *pdev)
++{
++ struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
++ struct gpio_led_data *leds_data;
++ int i;
++
++ leds_data = platform_get_drvdata(pdev);
++
++ for (i = 0; i < pdata->num_leds; i++)
++ led_classdev_resume(&leds_data[i].cdev);
++
++ return 0;
++}
++#else
++#define gpio_led_suspend NULL
++#define gpio_led_resume NULL
++#endif
++
++static struct platform_driver gpio_led_driver = {
++ .remove = __exit_p(gpio_led_remove),
++ .suspend = gpio_led_suspend,
++ .resume = gpio_led_resume,
++ .driver = {
++ .name = "leds-gpio",
++ .owner = THIS_MODULE,
++ },
++};
++
++static int __init gpio_led_init(void)
++{
++ return platform_driver_probe(&gpio_led_driver, gpio_led_probe);
++}
++
++static void __exit gpio_led_exit(void)
++{
++ platform_driver_unregister(&gpio_led_driver);
++}
++
++module_init(gpio_led_init);
++module_exit(gpio_led_exit);
++
++MODULE_AUTHOR("Raphael Assenat <raph@8d.com>");
++MODULE_DESCRIPTION("GPIO LED driver");
++MODULE_LICENSE("GPL");
+diff -x .git -Nur linux-2.6.22.1/drivers/leds/Makefile linux-avr32.git/drivers/leds/Makefile
+--- linux-2.6.22.1/drivers/leds/Makefile 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/drivers/leds/Makefile 2007-07-12 14:00:02.000000000 +0200
+@@ -16,6 +16,7 @@
+ obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o
+ obj-$(CONFIG_LEDS_H1940) += leds-h1940.o
+ obj-$(CONFIG_LEDS_COBALT) += leds-cobalt.o
++obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o
+
+ # LED Triggers
+ obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o
+diff -x .git -Nur linux-2.6.22.1/drivers/mmc/host/atmel-mci.c linux-avr32.git/drivers/mmc/host/atmel-mci.c
+--- linux-2.6.22.1/drivers/mmc/host/atmel-mci.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-avr32.git/drivers/mmc/host/atmel-mci.c 2007-07-12 14:00:03.000000000 +0200
+@@ -0,0 +1,1217 @@
++/*
++ * 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 <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, ®s_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 -x .git -Nur linux-2.6.22.1/drivers/mmc/host/atmel-mci.h linux-avr32.git/drivers/mmc/host/atmel-mci.h
+--- linux-2.6.22.1/drivers/mmc/host/atmel-mci.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-avr32.git/drivers/mmc/host/atmel-mci.h 2007-07-12 14:00:03.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 -x .git -Nur linux-2.6.22.1/drivers/mmc/host/Kconfig linux-avr32.git/drivers/mmc/host/Kconfig
+--- linux-2.6.22.1/drivers/mmc/host/Kconfig 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/drivers/mmc/host/Kconfig 2007-07-12 14:00:03.000000000 +0200
+@@ -74,6 +74,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_IMX
+ tristate "Motorola i.MX Multimedia Card Interface support"
+ depends on ARCH_IMX
+diff -x .git -Nur linux-2.6.22.1/drivers/mmc/host/Makefile linux-avr32.git/drivers/mmc/host/Makefile
+--- linux-2.6.22.1/drivers/mmc/host/Makefile 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/drivers/mmc/host/Makefile 2007-07-12 14:00:03.000000000 +0200
+@@ -14,5 +14,6 @@
+ 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
+
+diff -x .git -Nur linux-2.6.22.1/drivers/mtd/chips/cfi_cmdset_0001.c linux-avr32.git/drivers/mtd/chips/cfi_cmdset_0001.c
+--- linux-2.6.22.1/drivers/mtd/chips/cfi_cmdset_0001.c 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/drivers/mtd/chips/cfi_cmdset_0001.c 2007-07-12 14:00:03.000000000 +0200
+@@ -50,6 +50,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 *);
+@@ -156,6 +157,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)
+@@ -233,6 +275,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 -x .git -Nur linux-2.6.22.1/drivers/mtd/chips/cfi_cmdset_0002.c linux-avr32.git/drivers/mtd/chips/cfi_cmdset_0002.c
+--- linux-2.6.22.1/drivers/mtd/chips/cfi_cmdset_0002.c 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/drivers/mtd/chips/cfi_cmdset_0002.c 2007-06-06 11:33:56.000000000 +0200
+@@ -186,6 +186,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)
+@@ -218,6 +222,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
+@@ -230,7 +235,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 -x .git -Nur linux-2.6.22.1/drivers/net/Kconfig linux-avr32.git/drivers/net/Kconfig
+--- linux-2.6.22.1/drivers/net/Kconfig 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/drivers/net/Kconfig 2007-07-12 14:00:03.000000000 +0200
+@@ -314,7 +314,7 @@
+ config MACB
+ tristate "Atmel MACB support"
+ depends on NET_ETHERNET && (AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263)
+- select MII
++ select PHYLIB
+ help
+ The Atmel MACB ethernet interface is found on many AT32 and AT91
+ parts. Say Y to include support for the MACB chip.
+diff -x .git -Nur linux-2.6.22.1/drivers/net/macb.c linux-avr32.git/drivers/net/macb.c
+--- linux-2.6.22.1/drivers/net/macb.c 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/drivers/net/macb.c 2007-07-12 14:00:04.000000000 +0200
+@@ -17,13 +17,14 @@
+ #include <linux/init.h>
+ #include <linux/netdevice.h>
+ #include <linux/etherdevice.h>
+-#include <linux/mii.h>
+-#include <linux/mutex.h>
+ #include <linux/dma-mapping.h>
+-#include <linux/ethtool.h>
+ #include <linux/platform_device.h>
++#include <linux/phy.h>
+
+ #include <asm/arch/board.h>
++#if defined(CONFIG_ARCH_AT91)
++#include <asm/arch/cpu.h>
++#endif
+
+ #include "macb.h"
+
+@@ -85,172 +86,202 @@
+ memcpy(bp->dev->dev_addr, addr, sizeof(addr));
+ }
+
+-static void macb_enable_mdio(struct macb *bp)
+-{
+- unsigned long flags;
+- u32 reg;
+-
+- spin_lock_irqsave(&bp->lock, flags);
+- reg = macb_readl(bp, NCR);
+- reg |= MACB_BIT(MPE);
+- macb_writel(bp, NCR, reg);
+- macb_writel(bp, IER, MACB_BIT(MFD));
+- spin_unlock_irqrestore(&bp->lock, flags);
+-}
+-
+-static void macb_disable_mdio(struct macb *bp)
+-{
+- unsigned long flags;
+- u32 reg;
+-
+- spin_lock_irqsave(&bp->lock, flags);
+- reg = macb_readl(bp, NCR);
+- reg &= ~MACB_BIT(MPE);
+- macb_writel(bp, NCR, reg);
+- macb_writel(bp, IDR, MACB_BIT(MFD));
+- spin_unlock_irqrestore(&bp->lock, flags);
+-}
+-
+-static int macb_mdio_read(struct net_device *dev, int phy_id, int location)
++static int macb_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
+ {
+- struct macb *bp = netdev_priv(dev);
++ struct macb *bp = bus->priv;
+ int value;
+
+- mutex_lock(&bp->mdio_mutex);
+-
+- macb_enable_mdio(bp);
+ macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_SOF)
+ | MACB_BF(RW, MACB_MAN_READ)
+- | MACB_BF(PHYA, phy_id)
+- | MACB_BF(REGA, location)
++ | MACB_BF(PHYA, mii_id)
++ | MACB_BF(REGA, regnum)
+ | MACB_BF(CODE, MACB_MAN_CODE)));
+
+- wait_for_completion(&bp->mdio_complete);
++ /* wait for end of transfer */
++ while (!MACB_BFEXT(IDLE, macb_readl(bp, NSR)))
++ cpu_relax();
+
+ value = MACB_BFEXT(DATA, macb_readl(bp, MAN));
+- macb_disable_mdio(bp);
+- mutex_unlock(&bp->mdio_mutex);
+
+ return value;
+ }
+
+-static void macb_mdio_write(struct net_device *dev, int phy_id,
+- int location, int val)
++static int macb_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
++ u16 value)
+ {
+- struct macb *bp = netdev_priv(dev);
+-
+- dev_dbg(&bp->pdev->dev, "mdio_write %02x:%02x <- %04x\n",
+- phy_id, location, val);
+-
+- mutex_lock(&bp->mdio_mutex);
+- macb_enable_mdio(bp);
++ struct macb *bp = bus->priv;
+
+ macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_SOF)
+ | MACB_BF(RW, MACB_MAN_WRITE)
+- | MACB_BF(PHYA, phy_id)
+- | MACB_BF(REGA, location)
++ | MACB_BF(PHYA, mii_id)
++ | MACB_BF(REGA, regnum)
+ | MACB_BF(CODE, MACB_MAN_CODE)
+- | MACB_BF(DATA, val)));
++ | MACB_BF(DATA, value)));
++
++ /* wait for end of transfer */
++ while (!MACB_BFEXT(IDLE, macb_readl(bp, NSR)))
++ cpu_relax();
+
+- wait_for_completion(&bp->mdio_complete);
++ return 0;
++}
+
+- macb_disable_mdio(bp);
+- mutex_unlock(&bp->mdio_mutex);
++static int macb_mdio_reset(struct mii_bus *bus)
++{
++ return 0;
+ }
+
+-static int macb_phy_probe(struct macb *bp)
++static void macb_handle_link_change(struct net_device *dev)
+ {
+- int phy_address;
+- u16 phyid1, phyid2;
++ struct macb *bp = netdev_priv(dev);
++ struct phy_device *phydev = bp->phy_dev;
++ unsigned long flags;
+
+- for (phy_address = 0; phy_address < 32; phy_address++) {
+- phyid1 = macb_mdio_read(bp->dev, phy_address, MII_PHYSID1);
+- phyid2 = macb_mdio_read(bp->dev, phy_address, MII_PHYSID2);
++ int status_change = 0;
+
+- if (phyid1 != 0xffff && phyid1 != 0x0000
+- && phyid2 != 0xffff && phyid2 != 0x0000)
+- break;
++ spin_lock_irqsave(&bp->lock, flags);
++
++ if (phydev->link) {
++ if ((bp->speed != phydev->speed) ||
++ (bp->duplex != phydev->duplex)) {
++ u32 reg;
++
++ reg = macb_readl(bp, NCFGR);
++ reg &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
++
++ if (phydev->duplex)
++ reg |= MACB_BIT(FD);
++ if (phydev->speed)
++ reg |= MACB_BIT(SPD);
++
++ macb_writel(bp, NCFGR, reg);
++
++ bp->speed = phydev->speed;
++ bp->duplex = phydev->duplex;
++ status_change = 1;
++ }
+ }
+
+- if (phy_address == 32)
+- return -ENODEV;
++ if (phydev->link != bp->link) {
++ if (phydev->link)
++ netif_schedule(dev);
++ else {
++ bp->speed = 0;
++ bp->duplex = -1;
++ }
++ bp->link = phydev->link;
+
+- dev_info(&bp->pdev->dev,
+- "detected PHY at address %d (ID %04x:%04x)\n",
+- phy_address, phyid1, phyid2);
++ status_change = 1;
++ }
+
+- bp->mii.phy_id = phy_address;
+- return 0;
++ spin_unlock_irqrestore(&bp->lock, flags);
++
++ if (status_change) {
++ if (phydev->link)
++ printk(KERN_INFO "%s: link up (%d/%s)\n",
++ dev->name, phydev->speed,
++ DUPLEX_FULL == phydev->duplex ? "Full":"Half");
++ else
++ printk(KERN_INFO "%s: link down\n", dev->name);
++ }
+ }
+
+-static void macb_set_media(struct macb *bp, int media)
++/* based on au1000_eth. c*/
++static int macb_mii_probe(struct net_device *dev)
+ {
+- u32 reg;
++ struct macb *bp = netdev_priv(dev);
++ struct phy_device *phydev = NULL;
++ struct eth_platform_data *pdata;
++ int phy_addr;
+
+- spin_lock_irq(&bp->lock);
+- reg = macb_readl(bp, NCFGR);
+- reg &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
+- if (media & (ADVERTISE_100HALF | ADVERTISE_100FULL))
+- reg |= MACB_BIT(SPD);
+- if (media & ADVERTISE_FULL)
+- reg |= MACB_BIT(FD);
+- macb_writel(bp, NCFGR, reg);
+- spin_unlock_irq(&bp->lock);
++ /* find the first phy */
++ for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
++ if (bp->mii_bus.phy_map[phy_addr]) {
++ phydev = bp->mii_bus.phy_map[phy_addr];
++ break;
++ }
++ }
++
++ if (!phydev) {
++ printk (KERN_ERR "%s: no PHY found\n", dev->name);
++ return -1;
++ }
++
++ pdata = bp->pdev->dev.platform_data;
++ /* TODO : add pin_irq */
++
++ /* attach the mac to the phy */
++ if (pdata && pdata->is_rmii) {
++ phydev = phy_connect(dev, phydev->dev.bus_id,
++ &macb_handle_link_change, 0, PHY_INTERFACE_MODE_RMII);
++ } else {
++ phydev = phy_connect(dev, phydev->dev.bus_id,
++ &macb_handle_link_change, 0, PHY_INTERFACE_MODE_MII);
++ }
++
++ if (IS_ERR(phydev)) {
++ printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
++ return PTR_ERR(phydev);
++ }
++
++ /* mask with MAC supported features */
++ phydev->supported &= PHY_BASIC_FEATURES;
++
++ phydev->advertising = phydev->supported;
++
++ bp->link = 0;
++ bp->speed = 0;
++ bp->duplex = -1;
++ bp->phy_dev = phydev;
++
++ return 0;
+ }
+
+-static void macb_check_media(struct macb *bp, int ok_to_print, int init_media)
++static int macb_mii_init(struct macb *bp)
+ {
+- struct mii_if_info *mii = &bp->mii;
+- unsigned int old_carrier, new_carrier;
+- int advertise, lpa, media, duplex;
++ struct eth_platform_data *pdata;
++ int err = -ENXIO, i;
+
+- /* if forced media, go no further */
+- if (mii->force_media)
+- return;
++ /* Enable managment port */
++ macb_writel(bp, NCR, MACB_BIT(MPE));
+
+- /* check current and old link status */
+- old_carrier = netif_carrier_ok(mii->dev) ? 1 : 0;
+- new_carrier = (unsigned int) mii_link_ok(mii);
++ bp->mii_bus.name = "MACB_mii_bus",
++ bp->mii_bus.read = &macb_mdio_read,
++ bp->mii_bus.write = &macb_mdio_write,
++ bp->mii_bus.reset = &macb_mdio_reset,
++ bp->mii_bus.id = bp->pdev->id,
++ bp->mii_bus.priv = bp,
++ bp->mii_bus.dev = &bp->dev->dev;
++ pdata = bp->pdev->dev.platform_data;
+
+- /* if carrier state did not change, assume nothing else did */
+- if (!init_media && old_carrier == new_carrier)
+- return;
++ if (pdata)
++ bp->mii_bus.phy_mask = pdata->phy_mask;
+
+- /* no carrier, nothing much to do */
+- if (!new_carrier) {
+- netif_carrier_off(mii->dev);
+- printk(KERN_INFO "%s: link down\n", mii->dev->name);
+- return;
++ bp->mii_bus.irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
++ if (!bp->mii_bus.irq) {
++ err = -ENOMEM;
++ goto err_out;
+ }
+
+- /*
+- * we have carrier, see who's on the other end
+- */
+- netif_carrier_on(mii->dev);
++ for (i = 0; i < PHY_MAX_ADDR; i++)
++ bp->mii_bus.irq[i] = PHY_POLL;
+
+- /* get MII advertise and LPA values */
+- if (!init_media && mii->advertising) {
+- advertise = mii->advertising;
+- } else {
+- advertise = mii->mdio_read(mii->dev, mii->phy_id, MII_ADVERTISE);
+- mii->advertising = advertise;
+- }
+- lpa = mii->mdio_read(mii->dev, mii->phy_id, MII_LPA);
++ platform_set_drvdata(bp->dev, &bp->mii_bus);
+
+- /* figure out media and duplex from advertise and LPA values */
+- media = mii_nway_result(lpa & advertise);
+- duplex = (media & ADVERTISE_FULL) ? 1 : 0;
++ if (mdiobus_register(&bp->mii_bus))
++ goto err_out_free_mdio_irq;
+
+- if (ok_to_print)
+- printk(KERN_INFO "%s: link up, %sMbps, %s-duplex, lpa 0x%04X\n",
+- mii->dev->name,
+- media & (ADVERTISE_100FULL | ADVERTISE_100HALF) ? "100" : "10",
+- duplex ? "full" : "half", lpa);
++ if (macb_mii_probe(bp->dev) != 0) {
++ goto err_out_unregister_bus;
++ }
+
+- mii->full_duplex = duplex;
++ return 0;
+
+- /* Let the MAC know about the new link state */
+- macb_set_media(bp, media);
++err_out_unregister_bus:
++ mdiobus_unregister(&bp->mii_bus);
++err_out_free_mdio_irq:
++ kfree(bp->mii_bus.irq);
++err_out:
++ return err;
+ }
+
+ static void macb_update_stats(struct macb *bp)
+@@ -265,16 +296,6 @@
+ *p += __raw_readl(reg);
+ }
+
+-static void macb_periodic_task(struct work_struct *work)
+-{
+- struct macb *bp = container_of(work, struct macb, periodic_task.work);
+-
+- macb_update_stats(bp);
+- macb_check_media(bp, 1, 0);
+-
+- schedule_delayed_work(&bp->periodic_task, HZ);
+-}
+-
+ static void macb_tx(struct macb *bp)
+ {
+ unsigned int tail;
+@@ -519,9 +540,6 @@
+ spin_lock(&bp->lock);
+
+ while (status) {
+- if (status & MACB_BIT(MFD))
+- complete(&bp->mdio_complete);
+-
+ /* close possible race with dev_close */
+ if (unlikely(!netif_running(dev))) {
+ macb_writel(bp, IDR, ~0UL);
+@@ -535,7 +553,8 @@
+ * until we have processed the buffers
+ */
+ macb_writel(bp, IDR, MACB_RX_INT_FLAGS);
+- dev_dbg(&bp->pdev->dev, "scheduling RX softirq\n");
++ dev_dbg(&bp->pdev->dev,
++ "scheduling RX softirq\n");
+ __netif_rx_schedule(dev);
+ }
+ }
+@@ -765,7 +784,7 @@
+ macb_writel(bp, TBQP, bp->tx_ring_dma);
+
+ /* Enable TX and RX */
+- macb_writel(bp, NCR, MACB_BIT(RE) | MACB_BIT(TE));
++ macb_writel(bp, NCR, MACB_BIT(RE) | MACB_BIT(TE) | MACB_BIT(MPE));
+
+ /* Enable interrupts */
+ macb_writel(bp, IER, (MACB_BIT(RCOMP)
+@@ -776,18 +795,7 @@
+ | MACB_BIT(TCOMP)
+ | MACB_BIT(ISR_ROVR)
+ | MACB_BIT(HRESP)));
+-}
+-
+-static void macb_init_phy(struct net_device *dev)
+-{
+- struct macb *bp = netdev_priv(dev);
+
+- /* Set some reasonable default settings */
+- macb_mdio_write(dev, bp->mii.phy_id, MII_ADVERTISE,
+- ADVERTISE_CSMA | ADVERTISE_ALL);
+- macb_mdio_write(dev, bp->mii.phy_id, MII_BMCR,
+- (BMCR_SPEED100 | BMCR_ANENABLE
+- | BMCR_ANRESTART | BMCR_FULLDPLX));
+ }
+
+ static int macb_open(struct net_device *dev)
+@@ -797,6 +805,10 @@
+
+ dev_dbg(&bp->pdev->dev, "open\n");
+
++ /* if the phy is not yet register, retry later*/
++ if (!bp->phy_dev)
++ return -EAGAIN;
++
+ if (!is_valid_ether_addr(dev->dev_addr))
+ return -EADDRNOTAVAIL;
+
+@@ -810,12 +822,11 @@
+
+ macb_init_rings(bp);
+ macb_init_hw(bp);
+- macb_init_phy(dev);
+
+- macb_check_media(bp, 1, 1);
+- netif_start_queue(dev);
++ /* schedule a link state check */
++ phy_start(bp->phy_dev);
+
+- schedule_delayed_work(&bp->periodic_task, HZ);
++ netif_start_queue(dev);
+
+ return 0;
+ }
+@@ -825,10 +836,11 @@
+ struct macb *bp = netdev_priv(dev);
+ unsigned long flags;
+
+- cancel_rearming_delayed_work(&bp->periodic_task);
+-
+ netif_stop_queue(dev);
+
++ if (bp->phy_dev)
++ phy_stop(bp->phy_dev);
++
+ spin_lock_irqsave(&bp->lock, flags);
+ macb_reset_hw(bp);
+ netif_carrier_off(dev);
+@@ -845,6 +857,9 @@
+ struct net_device_stats *nstat = &bp->stats;
+ struct macb_stats *hwstat = &bp->hw_stats;
+
++ /* read stats from hardware */
++ macb_update_stats(bp);
++
+ /* Convert HW stats into netdevice stats */
+ nstat->rx_errors = (hwstat->rx_fcs_errors +
+ hwstat->rx_align_errors +
+@@ -882,18 +897,27 @@
+ static int macb_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+ {
+ struct macb *bp = netdev_priv(dev);
++ struct phy_device *phydev = bp->phy_dev;
+
+- return mii_ethtool_gset(&bp->mii, cmd);
++ if (!phydev)
++ return -ENODEV;
++
++ return phy_ethtool_gset(phydev, cmd);
+ }
+
+ static int macb_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+ {
+ struct macb *bp = netdev_priv(dev);
++ struct phy_device *phydev = bp->phy_dev;
++
++ if (!phydev)
++ return -ENODEV;
+
+- return mii_ethtool_sset(&bp->mii, cmd);
++ return phy_ethtool_sset(phydev, cmd);
+ }
+
+-static void macb_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
++static void macb_get_drvinfo(struct net_device *dev,
++ struct ethtool_drvinfo *info)
+ {
+ struct macb *bp = netdev_priv(dev);
+
+@@ -902,104 +926,34 @@
+ strcpy(info->bus_info, bp->pdev->dev.bus_id);
+ }
+
+-static int macb_nway_reset(struct net_device *dev)
+-{
+- struct macb *bp = netdev_priv(dev);
+- return mii_nway_restart(&bp->mii);
+-}
+-
+ static struct ethtool_ops macb_ethtool_ops = {
+ .get_settings = macb_get_settings,
+ .set_settings = macb_set_settings,
+ .get_drvinfo = macb_get_drvinfo,
+- .nway_reset = macb_nway_reset,
+ .get_link = ethtool_op_get_link,
+ };
+
+ static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+ {
+ struct macb *bp = netdev_priv(dev);
++ struct phy_device *phydev = bp->phy_dev;
+
+ if (!netif_running(dev))
+ return -EINVAL;
+
+- return generic_mii_ioctl(&bp->mii, if_mii(rq), cmd, NULL);
+-}
+-
+-static ssize_t macb_mii_show(const struct device *_dev, char *buf,
+- unsigned long addr)
+-{
+- struct net_device *dev = to_net_dev(_dev);
+- struct macb *bp = netdev_priv(dev);
+- ssize_t ret = -EINVAL;
+-
+- if (netif_running(dev)) {
+- int value;
+- value = macb_mdio_read(dev, bp->mii.phy_id, addr);
+- ret = sprintf(buf, "0x%04x\n", (uint16_t)value);
+- }
+-
+- return ret;
+-}
+-
+-#define MII_ENTRY(name, addr) \
+-static ssize_t show_##name(struct device *_dev, \
+- struct device_attribute *attr, \
+- char *buf) \
+-{ \
+- return macb_mii_show(_dev, buf, addr); \
+-} \
+-static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
+-
+-MII_ENTRY(bmcr, MII_BMCR);
+-MII_ENTRY(bmsr, MII_BMSR);
+-MII_ENTRY(physid1, MII_PHYSID1);
+-MII_ENTRY(physid2, MII_PHYSID2);
+-MII_ENTRY(advertise, MII_ADVERTISE);
+-MII_ENTRY(lpa, MII_LPA);
+-MII_ENTRY(expansion, MII_EXPANSION);
+-
+-static struct attribute *macb_mii_attrs[] = {
+- &dev_attr_bmcr.attr,
+- &dev_attr_bmsr.attr,
+- &dev_attr_physid1.attr,
+- &dev_attr_physid2.attr,
+- &dev_attr_advertise.attr,
+- &dev_attr_lpa.attr,
+- &dev_attr_expansion.attr,
+- NULL,
+-};
+-
+-static struct attribute_group macb_mii_group = {
+- .name = "mii",
+- .attrs = macb_mii_attrs,
+-};
+-
+-static void macb_unregister_sysfs(struct net_device *net)
+-{
+- struct device *_dev = &net->dev;
++ if (!phydev)
++ return -ENODEV;
+
+- sysfs_remove_group(&_dev->kobj, &macb_mii_group);
++ return phy_mii_ioctl(phydev, if_mii(rq), cmd);
+ }
+
+-static int macb_register_sysfs(struct net_device *net)
+-{
+- struct device *_dev = &net->dev;
+- int ret;
+-
+- ret = sysfs_create_group(&_dev->kobj, &macb_mii_group);
+- if (ret)
+- printk(KERN_WARNING
+- "%s: sysfs mii attribute registration failed: %d\n",
+- net->name, ret);
+- return ret;
+-}
+ static int __devinit macb_probe(struct platform_device *pdev)
+ {
+ struct eth_platform_data *pdata;
+ struct resource *regs;
+ struct net_device *dev;
+ struct macb *bp;
++ struct phy_device *phydev;
+ unsigned long pclk_hz;
+ u32 config;
+ int err = -ENXIO;
+@@ -1080,10 +1034,6 @@
+
+ dev->base_addr = regs->start;
+
+- INIT_DELAYED_WORK(&bp->periodic_task, macb_periodic_task);
+- mutex_init(&bp->mdio_mutex);
+- init_completion(&bp->mdio_complete);
+-
+ /* Set MII management clock divider */
+ pclk_hz = clk_get_rate(bp->pclk);
+ if (pclk_hz <= 20000000)
+@@ -1096,20 +1046,9 @@
+ config = MACB_BF(CLK, MACB_CLK_DIV64);
+ macb_writel(bp, NCFGR, config);
+
+- bp->mii.dev = dev;
+- bp->mii.mdio_read = macb_mdio_read;
+- bp->mii.mdio_write = macb_mdio_write;
+- bp->mii.phy_id_mask = 0x1f;
+- bp->mii.reg_num_mask = 0x1f;
+-
+ macb_get_hwaddr(bp);
+- err = macb_phy_probe(bp);
+- if (err) {
+- dev_err(&pdev->dev, "Failed to detect PHY, aborting.\n");
+- goto err_out_free_irq;
+- }
+-
+ pdata = pdev->dev.platform_data;
++
+ if (pdata && pdata->is_rmii)
+ #if defined(CONFIG_ARCH_AT91)
+ macb_writel(bp, USRIO, (MACB_BIT(RMII) | MACB_BIT(CLKEN)) );
+@@ -1131,9 +1070,11 @@
+ goto err_out_free_irq;
+ }
+
+- platform_set_drvdata(pdev, dev);
++ if (macb_mii_init(bp) != 0) {
++ goto err_out_unregister_netdev;
++ }
+
+- macb_register_sysfs(dev);
++ platform_set_drvdata(pdev, dev);
+
+ printk(KERN_INFO "%s: Atmel MACB at 0x%08lx irq %d "
+ "(%02x:%02x:%02x:%02x:%02x:%02x)\n",
+@@ -1141,8 +1082,15 @@
+ dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
+ dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
+
++ phydev = bp->phy_dev;
++ printk(KERN_INFO "%s: attached PHY driver [%s] "
++ "(mii_bus:phy_addr=%s, irq=%d)\n",
++ dev->name, phydev->drv->name, phydev->dev.bus_id, phydev->irq);
++
+ return 0;
+
++err_out_unregister_netdev:
++ unregister_netdev(dev);
+ err_out_free_irq:
+ free_irq(dev->irq, dev);
+ err_out_iounmap:
+@@ -1153,7 +1101,9 @@
+ clk_put(bp->hclk);
+ #endif
+ clk_disable(bp->pclk);
++#ifndef CONFIG_ARCH_AT91
+ err_out_put_pclk:
++#endif
+ clk_put(bp->pclk);
+ err_out_free_dev:
+ free_netdev(dev);
+@@ -1171,7 +1121,8 @@
+
+ if (dev) {
+ bp = netdev_priv(dev);
+- macb_unregister_sysfs(dev);
++ mdiobus_unregister(&bp->mii_bus);
++ kfree(bp->mii_bus.irq);
+ unregister_netdev(dev);
+ free_irq(dev->irq, dev);
+ iounmap(bp->regs);
+diff -x .git -Nur linux-2.6.22.1/drivers/net/macb.h linux-avr32.git/drivers/net/macb.h
+--- linux-2.6.22.1/drivers/net/macb.h 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/drivers/net/macb.h 2007-07-12 14:00:04.000000000 +0200
+@@ -383,11 +383,11 @@
+
+ unsigned int rx_pending, tx_pending;
+
+- struct delayed_work periodic_task;
+-
+- struct mutex mdio_mutex;
+- struct completion mdio_complete;
+- struct mii_if_info mii;
++ struct mii_bus mii_bus;
++ struct phy_device *phy_dev;
++ unsigned int link;
++ unsigned int speed;
++ unsigned int duplex;
+ };
+
+ #endif /* _MACB_H */
+diff -x .git -Nur linux-2.6.22.1/drivers/rtc/Kconfig linux-avr32.git/drivers/rtc/Kconfig
+--- linux-2.6.22.1/drivers/rtc/Kconfig 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/drivers/rtc/Kconfig 2007-07-12 14:00:13.000000000 +0200
+@@ -379,6 +379,13 @@
+ To compile this driver as a module, choose M here: the
+ module will be called rtc-pl031.
+
++config RTC_DRV_AT32AP700X
++ tristate "AT32AP700X series RTC"
++ depends on RTC_CLASS && PLATFORM_AT32AP
++ help
++ Driver for the internal RTC (Realtime Clock) on Atmel AVR32
++ AT32AP700x family processors.
++
+ config RTC_DRV_AT91RM9200
+ tristate "AT91RM9200"
+ depends on RTC_CLASS && ARCH_AT91RM9200
+diff -x .git -Nur linux-2.6.22.1/drivers/rtc/Makefile linux-avr32.git/drivers/rtc/Makefile
+--- linux-2.6.22.1/drivers/rtc/Makefile 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/drivers/rtc/Makefile 2007-07-12 14:00:13.000000000 +0200
+@@ -19,6 +19,7 @@
+ obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o
+ obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o
+ obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o
++obj-$(CONFIG_RTC_DRV_AT32AP700X) += rtc-at32ap700x.o
+ obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o
+ obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o
+ obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o
+diff -x .git -Nur linux-2.6.22.1/drivers/rtc/rtc-at32ap700x.c linux-avr32.git/drivers/rtc/rtc-at32ap700x.c
+--- linux-2.6.22.1/drivers/rtc/rtc-at32ap700x.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-avr32.git/drivers/rtc/rtc-at32ap700x.c 2007-07-12 14:00:13.000000000 +0200
+@@ -0,0 +1,337 @@
++/*
++ * An RTC driver for the AVR32 AT32AP700x processor series.
++ *
++ * 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/module.h>
++#include <linux/kernel.h>
++#include <linux/platform_device.h>
++#include <linux/rtc.h>
++#include <linux/io.h>
++
++/*
++ * This is a bare-bones RTC. It runs during most system sleep states, but has
++ * no battery backup and gets reset during system restart. It must be
++ * initialized from an external clock (network, I2C, etc) before it can be of
++ * much use.
++ *
++ * The alarm functionality is limited by the hardware, not supporting
++ * periodic interrupts.
++ */
++
++#define RTC_CTRL 0x00
++#define RTC_CTRL_EN 0
++#define RTC_CTRL_PCLR 1
++#define RTC_CTRL_TOPEN 2
++#define RTC_CTRL_PSEL 8
+
-+struct atmel_mci_dma {
-+ struct dma_request_sg req;
-+ unsigned short rx_periph_id;
-+ unsigned short tx_periph_id;
-+};
++#define RTC_VAL 0x04
+
-+struct atmel_mci {
-+ struct mmc_host *mmc;
-+ void __iomem *regs;
-+ struct atmel_mci_dma dma;
++#define RTC_TOP 0x08
+
-+ struct mmc_request *mrq;
-+ struct mmc_command *cmd;
-+ struct mmc_data *data;
++#define RTC_IER 0x10
++#define RTC_IER_TOPI 0
+
-+ u32 stop_cmdr;
-+ u32 stop_iflags;
++#define RTC_IDR 0x14
++#define RTC_IDR_TOPI 0
+
-+ struct tasklet_struct tasklet;
-+ unsigned long pending_events;
-+ unsigned long completed_events;
-+ u32 error_status;
++#define RTC_IMR 0x18
++#define RTC_IMR_TOPI 0
+
-+ int present;
-+ int detect_pin;
-+ int wp_pin;
++#define RTC_ISR 0x1c
++#define RTC_ISR_TOPI 0
+
-+ unsigned long bus_hz;
-+ unsigned long mapbase;
-+ struct clk *mck;
-+ struct platform_device *pdev;
++#define RTC_ICR 0x20
++#define RTC_ICR_TOPI 0
+
-+#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
-+};
++#define RTC_BIT(name) (1 << RTC_##name)
++#define RTC_BF(name, value) ((value) << RTC_##name)
+
-+/* 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");
++#define rtc_readl(dev, reg) \
++ __raw_readl((dev)->regs + RTC_##reg)
++#define rtc_writel(dev, reg, value) \
++ __raw_writel((value), (dev)->regs + RTC_##reg)
+
-+/* 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)
++struct rtc_at32ap700x {
++ struct rtc_device *rtc;
++ void __iomem *regs;
++ unsigned long alarm_time;
++ unsigned long irq;
++ /* Protect against concurrent register access. */
++ spinlock_t lock;
++};
+
-+/* 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)
++static int at32_rtc_readtime(struct device *dev, struct rtc_time *tm)
++{
++ struct rtc_at32ap700x *rtc = dev_get_drvdata(dev);
++ unsigned long now;
+
-+/* 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)
++ now = rtc_readl(rtc, VAL);
++ rtc_time_to_tm(now, tm);
+
-+/* 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)
++ return 0;
++}
+
-+/* 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)
++static int at32_rtc_settime(struct device *dev, struct rtc_time *tm)
++{
++ struct rtc_at32ap700x *rtc = dev_get_drvdata(dev);
++ unsigned long now;
++ int ret;
+
-+/* 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)
++ ret = rtc_tm_to_time(tm, &now);
++ if (ret == 0)
++ rtc_writel(rtc, VAL, now);
+
++ return ret;
++}
+
-+#ifdef CONFIG_DEBUG_FS
-+#include <linux/debugfs.h>
++static int at32_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
++{
++ struct rtc_at32ap700x *rtc = dev_get_drvdata(dev);
+
-+#define DBG_REQ_BUF_SIZE (4096 - sizeof(unsigned int))
++ rtc_time_to_tm(rtc->alarm_time, &alrm->time);
++ alrm->pending = rtc_readl(rtc, IMR) & RTC_BIT(IMR_TOPI) ? 1 : 0;
+
-+struct req_dbg_data {
-+ unsigned int nbytes;
-+ char str[DBG_REQ_BUF_SIZE];
-+};
++ return 0;
++}
+
-+static int req_dbg_open(struct inode *inode, struct file *file)
++static int at32_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
-+ 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;
++ struct rtc_at32ap700x *rtc = dev_get_drvdata(dev);
++ unsigned long rtc_unix_time;
++ unsigned long alarm_unix_time;
++ int ret;
+
-+ priv = kzalloc(DBG_REQ_BUF_SIZE, GFP_KERNEL);
-+ if (!priv)
-+ return -ENOMEM;
-+ str = priv->str;
++ rtc_unix_time = rtc_readl(rtc, VAL);
+
-+ mutex_lock(&inode->i_mutex);
-+ host = inode->i_private;
++ /* RTC does only support one alarm time, not periodic */
++ if (alrm->time.tm_mday <= 0) {
++ struct rtc_time tm;
++ unsigned long then;
+
-+ 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);
++ rtc_time_to_tm(rtc_unix_time, &tm);
++
++ alrm->time.tm_mday = tm.tm_mday;
++ alrm->time.tm_mon = tm.tm_mon;
++ alrm->time.tm_year = tm.tm_year;
++
++ rtc_tm_to_time(&alrm->time, &then);
++
++ /* check if the alarm wraps into tomorrow */
++ if (then < rtc_unix_time) {
++ rtc_time_to_tm(rtc_unix_time + 24 * 60 * 60, &tm);
++ alrm->time.tm_mday = tm.tm_mday;
++ alrm->time.tm_mon = tm.tm_mon;
++ alrm->time.tm_year = tm.tm_year;
++ }
+ }
-+ spin_unlock_irq(&host->mmc->lock);
-+ mutex_unlock(&inode->i_mutex);
+
-+ priv->nbytes = min(n, DBG_REQ_BUF_SIZE);
-+ file->private_data = priv;
++ ret = rtc_tm_to_time(&alrm->time, &alarm_unix_time);
++ if (ret)
++ return ret;
+
-+ return 0;
++ if (alarm_unix_time < rtc_unix_time)
++ return -EINVAL;
++
++ spin_lock_irq(&rtc->lock);
++ rtc->alarm_time = alarm_unix_time;
++ rtc_writel(rtc, TOP, rtc->alarm_time);
++ if (alrm->pending)
++ rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL)
++ | RTC_BIT(CTRL_TOPEN));
++ else
++ rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL)
++ & ~RTC_BIT(CTRL_TOPEN));
++ spin_unlock_irq(&rtc->lock);
++
++ return ret;
+}
+
-+static ssize_t req_dbg_read(struct file *file, char __user *buf,
-+ size_t nbytes, loff_t *ppos)
++static int at32_rtc_ioctl(struct device *dev, unsigned int cmd,
++ unsigned long arg)
+{
-+ struct req_dbg_data *priv = file->private_data;
++ struct rtc_at32ap700x *rtc = dev_get_drvdata(dev);
++ int ret = 0;
+
-+ return simple_read_from_buffer(buf, nbytes, ppos,
-+ priv->str, priv->nbytes);
++ spin_lock_irq(&rtc->lock);
++
++ switch (cmd) {
++ case RTC_AIE_ON:
++ if (rtc_readl(rtc, VAL) > rtc->alarm_time) {
++ ret = -EINVAL;
++ break;
++ }
++ rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL)
++ | RTC_BIT(CTRL_TOPEN));
++ rtc_writel(rtc, ICR, RTC_BIT(ICR_TOPI));
++ rtc_writel(rtc, IER, RTC_BIT(IER_TOPI));
++ break;
++ case RTC_AIE_OFF:
++ rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL)
++ & ~RTC_BIT(CTRL_TOPEN));
++ rtc_writel(rtc, IDR, RTC_BIT(IDR_TOPI));
++ rtc_writel(rtc, ICR, RTC_BIT(ICR_TOPI));
++ break;
++ default:
++ ret = -ENOIOCTLCMD;
++ break;
++ }
++
++ spin_unlock_irq(&rtc->lock);
++
++ return ret;
+}
+
-+static int req_dbg_release(struct inode *inode, struct file *file)
++static irqreturn_t at32_rtc_interrupt(int irq, void *dev_id)
+{
-+ kfree(file->private_data);
-+ return 0;
++ struct rtc_at32ap700x *rtc = (struct rtc_at32ap700x *)dev_id;
++ unsigned long isr = rtc_readl(rtc, ISR);
++ unsigned long events = 0;
++ int ret = IRQ_NONE;
++
++ spin_lock(&rtc->lock);
++
++ if (isr & RTC_BIT(ISR_TOPI)) {
++ rtc_writel(rtc, ICR, RTC_BIT(ICR_TOPI));
++ rtc_writel(rtc, IDR, RTC_BIT(IDR_TOPI));
++ rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL)
++ & ~RTC_BIT(CTRL_TOPEN));
++ rtc_writel(rtc, VAL, rtc->alarm_time);
++ events = RTC_AF | RTC_IRQF;
++ rtc_update_irq(rtc->rtc, 1, events);
++ ret = IRQ_HANDLED;
++ }
++
++ spin_unlock(&rtc->lock);
++
++ return ret;
+}
+
-+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 struct rtc_class_ops at32_rtc_ops = {
++ .ioctl = at32_rtc_ioctl,
++ .read_time = at32_rtc_readtime,
++ .set_time = at32_rtc_settime,
++ .read_alarm = at32_rtc_readalarm,
++ .set_alarm = at32_rtc_setalarm,
+};
+
-+static int regs_dbg_open(struct inode *inode, struct file *file)
++static int __init at32_rtc_probe(struct platform_device *pdev)
+{
-+ struct atmel_mci *host;
-+ unsigned int i;
-+ u32 *data;
-+ int ret = -ENOMEM;
++ struct resource *regs;
++ struct rtc_at32ap700x *rtc;
++ int irq = -1;
++ int ret;
+
-+ mutex_lock(&inode->i_mutex);
-+ host = inode->i_private;
-+ data = kmalloc(inode->i_size, GFP_KERNEL);
-+ if (!data)
++ rtc = kzalloc(sizeof(struct rtc_at32ap700x), GFP_KERNEL);
++ if (!rtc) {
++ dev_dbg(&pdev->dev, "out of memory\n");
++ return -ENOMEM;
++ }
++
++ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!regs) {
++ dev_dbg(&pdev->dev, "no mmio resource defined\n");
++ ret = -ENXIO;
+ 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);
++ irq = platform_get_irq(pdev, 0);
++ if (irq < 0) {
++ dev_dbg(&pdev->dev, "could not get irq\n");
++ ret = -ENXIO;
++ goto out;
++ }
+
-+ file->private_data = data;
-+ ret = 0;
++ ret = request_irq(irq, at32_rtc_interrupt, IRQF_SHARED, "rtc", rtc);
++ if (ret) {
++ dev_dbg(&pdev->dev, "could not request irq %d\n", irq);
++ goto out;
++ }
+
-+out:
-+ mutex_unlock(&inode->i_mutex);
++ rtc->irq = irq;
++ rtc->regs = ioremap(regs->start, regs->end - regs->start + 1);
++ if (!rtc->regs) {
++ ret = -ENOMEM;
++ dev_dbg(&pdev->dev, "could not map I/O memory\n");
++ goto out_free_irq;
++ }
++ spin_lock_init(&rtc->lock);
+
-+ return ret;
-+}
++ /*
++ * Maybe init RTC: count from zero at 1 Hz, disable wrap irq.
++ *
++ * Do not reset VAL register, as it can hold an old time
++ * from last JTAG reset.
++ */
++ if (!(rtc_readl(rtc, CTRL) & RTC_BIT(CTRL_EN))) {
++ rtc_writel(rtc, CTRL, RTC_BIT(CTRL_PCLR));
++ rtc_writel(rtc, IDR, RTC_BIT(IDR_TOPI));
++ rtc_writel(rtc, CTRL, RTC_BF(CTRL_PSEL, 0xe)
++ | RTC_BIT(CTRL_EN));
++ }
+
-+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;
++ rtc->rtc = rtc_device_register(pdev->name, &pdev->dev,
++ &at32_rtc_ops, THIS_MODULE);
++ if (IS_ERR(rtc->rtc)) {
++ dev_dbg(&pdev->dev, "could not register rtc device\n");
++ ret = PTR_ERR(rtc->rtc);
++ goto out_iounmap;
++ }
+
-+ 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);
++ platform_set_drvdata(pdev, rtc);
++
++ dev_info(&pdev->dev, "Atmel RTC for AT32AP700x at %08lx irq %ld\n",
++ (unsigned long)rtc->regs, rtc->irq);
++
++ return 0;
+
++out_iounmap:
++ iounmap(rtc->regs);
++out_free_irq:
++ free_irq(irq, rtc);
++out:
++ kfree(rtc);
+ return ret;
+}
+
-+static int regs_dbg_release(struct inode *inode, struct file *file)
++static int __exit at32_rtc_remove(struct platform_device *pdev)
+{
-+ kfree(file->private_data);
++ struct rtc_at32ap700x *rtc = platform_get_drvdata(pdev);
++
++ free_irq(rtc->irq, rtc);
++ iounmap(rtc->regs);
++ rtc_device_unregister(rtc->rtc);
++ kfree(rtc);
++ platform_set_drvdata(pdev, NULL);
++
+ 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 struct platform_driver at32_rtc_driver = {
++ .remove = __exit_p(at32_rtc_remove),
++ .driver = {
++ .name = "rtc-at32ap700x",
++ .owner = THIS_MODULE,
++ },
+};
+
-+static void atmci_init_debugfs(struct atmel_mci *host)
++static int __init at32_rtc_init(void)
+{
-+ 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;
++ return platform_driver_probe(&at32_rtc_driver, at32_rtc_probe);
++}
++module_init(at32_rtc_init);
+
-+ regs = debugfs_create_file("regs", 0400, root, host, ®s_dbg_fops);
-+ if (!regs)
-+ goto err_regs;
++static void __exit at32_rtc_exit(void)
++{
++ platform_driver_unregister(&at32_rtc_driver);
++}
++module_exit(at32_rtc_exit);
+
-+ res = platform_get_resource(host->pdev, IORESOURCE_MEM, 0);
-+ regs->d_inode->i_size = res->end - res->start + 1;
-+ host->debugfs_regs = regs;
++MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>");
++MODULE_DESCRIPTION("Real time clock for AVR32 AT32AP700x");
++MODULE_LICENSE("GPL");
+diff -x .git -Nur linux-2.6.22.1/drivers/serial/atmel_serial.c linux-avr32.git/drivers/serial/atmel_serial.c
+--- linux-2.6.22.1/drivers/serial/atmel_serial.c 2007-07-10 20:56:30.000000000 +0200
++++ linux-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++;
+diff -x .git -Nur linux-2.6.22.1/drivers/spi/atmel_spi.c linux-avr32.git/drivers/spi/atmel_spi.c
+--- linux-2.6.22.1/drivers/spi/atmel_spi.c 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/drivers/spi/atmel_spi.c 2007-06-06 11:33:59.000000000 +0200
+@@ -412,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;
+diff -x .git -Nur linux-2.6.22.1/drivers/usb/gadget/atmel_usba_udc.c linux-avr32.git/drivers/usb/gadget/atmel_usba_udc.c
+--- linux-2.6.22.1/drivers/usb/gadget/atmel_usba_udc.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-avr32.git/drivers/usb/gadget/atmel_usba_udc.c 2007-07-12 14:00:19.000000000 +0200
+@@ -0,0 +1,2072 @@
++/*
++ * Driver for the Atmel USBA high speed USB device controller
++ *
++ * Copyright (C) 2005-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.
++ */
++/* #define DEBUG */
+
-+ host->debugfs_req = debugfs_create_file("req", 0400, root,
-+ host, &req_dbg_fops);
-+ if (!host->debugfs_req)
-+ goto err_req;
++#include <linux/clk.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/io.h>
++#include <linux/device.h>
++#include <linux/dma-mapping.h>
++#include <linux/list.h>
++#include <linux/platform_device.h>
++#include <linux/usb/ch9.h>
++#include <linux/usb_gadget.h>
++#include <linux/delay.h>
+
-+ host->debugfs_pending_events
-+ = debugfs_create_u32("pending_events", 0400, root,
-+ (u32 *)&host->pending_events);
-+ if (!host->debugfs_pending_events)
-+ goto err_pending_events;
++#include <asm/gpio.h>
++#include <asm/arch/board.h>
+
-+ host->debugfs_completed_events
-+ = debugfs_create_u32("completed_events", 0400, root,
-+ (u32 *)&host->completed_events);
-+ if (!host->debugfs_completed_events)
-+ goto err_completed_events;
++#include "atmel_usba_udc.h"
++
++#define DMA_ADDR_INVALID (~(dma_addr_t)0)
++
++#define FIFO_IOMEM_ID 0
++#define CTRL_IOMEM_ID 1
++
++#ifdef DEBUG
++#define DBG_ERR 0x0001 /* report all error returns */
++#define DBG_HW 0x0002 /* debug hardware initialization */
++#define DBG_GADGET 0x0004 /* calls to/from gadget driver */
++#define DBG_INT 0x0008 /* interrupts */
++#define DBG_BUS 0x0010 /* report changes in bus state */
++#define DBG_QUEUE 0x0020 /* debug request queue processing */
++#define DBG_FIFO 0x0040 /* debug FIFO contents */
++#define DBG_DMA 0x0080 /* debug DMA handling */
++#define DBG_REQ 0x0100 /* print out queued request length */
++#define DBG_ALL 0xffff
++#define DBG_NONE 0x0000
++
++#define DEBUG_LEVEL (DBG_ERR)
++#define DBG(level, fmt, ...) \
++ do { \
++ if ((level) & DEBUG_LEVEL) \
++ printk(KERN_DEBUG "udc: " fmt, ## __VA_ARGS__); \
++ } while (0)
++#else
++#define DBG(level, fmt...)
++#endif
+
-+ return;
++static struct usba_udc the_udc;
+
-+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));
-+}
++#ifdef CONFIG_DEBUG_FS
++#include <linux/debugfs.h>
++#include <linux/uaccess.h>
+
-+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 int queue_dbg_open(struct inode *inode, struct file *file)
+{
++ struct usba_ep *ep = inode->i_private;
++ struct usba_request *req, *req_copy;
++ struct list_head *queue_data;
+
-+}
++ queue_data = kmalloc(sizeof(*queue_data), GFP_KERNEL);
++ if (!queue_data)
++ return -ENOMEM;
++ INIT_LIST_HEAD(queue_data);
+
-+static inline void atmci_cleanup_debugfs(struct atmel_mci *host)
-+{
++ spin_lock_irq(&ep->udc->lock);
++ list_for_each_entry(req, &ep->queue, queue) {
++ req_copy = kmalloc(sizeof(*req_copy), GFP_ATOMIC);
++ if (!req_copy)
++ goto fail;
++ memcpy(req_copy, req, sizeof(*req_copy));
++ list_add_tail(&req_copy->queue, queue_data);
++ }
++ spin_unlock_irq(&ep->udc->lock);
+
-+}
-+#endif /* CONFIG_DEBUG_FS */
++ file->private_data = queue_data;
++ return 0;
+
-+static inline unsigned int ns_to_clocks(struct atmel_mci *host,
-+ unsigned int ns)
-+{
-+ return (ns * (host->bus_hz / 1000000) + 999) / 1000;
++fail:
++ spin_unlock_irq(&ep->udc->lock);
++ list_for_each_entry_safe(req, req_copy, queue_data, queue) {
++ list_del(&req->queue);
++ kfree(req);
++ }
++ kfree(queue_data);
++ return -ENOMEM;
+}
+
-+static void atmci_set_timeout(struct atmel_mci *host,
-+ struct mmc_data *data)
++/*
++ * bbbbbbbb llllllll IZS sssss nnnn FDL\n\0
++ *
++ * b: buffer address
++ * l: buffer length
++ * I/i: interrupt/no interrupt
++ * Z/z: zero/no zero
++ * S/s: short ok/short not ok
++ * s: status
++ * n: nr_packets
++ * F/f: submitted/not submitted to FIFO
++ * D/d: using/not using DMA
++ * L/l: last transaction/not last transaction
++ */
++static ssize_t queue_dbg_read(struct file *file, char __user *buf,
++ size_t nbytes, loff_t *ppos)
+{
-+ static unsigned dtomul_to_shift[] = {
-+ 0, 4, 7, 8, 10, 12, 16, 20
-+ };
-+ unsigned timeout;
-+ unsigned dtocyc, dtomul;
++ struct list_head *queue = file->private_data;
++ struct usba_request *req, *tmp_req;
++ size_t len, remaining, actual = 0;
++ char tmpbuf[38];
+
-+ timeout = ns_to_clocks(host, data->timeout_ns) + data->timeout_clks;
++ if (!access_ok(VERIFY_WRITE, buf, nbytes))
++ return -EFAULT;
+
-+ for (dtomul = 0; dtomul < 8; dtomul++) {
-+ unsigned shift = dtomul_to_shift[dtomul];
-+ dtocyc = (timeout + (1 << shift) - 1) >> shift;
-+ if (dtocyc < 15)
++ mutex_lock(&file->f_dentry->d_inode->i_mutex);
++ list_for_each_entry_safe(req, tmp_req, queue, queue) {
++ len = snprintf(tmpbuf, sizeof(tmpbuf),
++ "%8p %08x %c%c%c %5d %c%c%c\n",
++ req->req.buf, req->req.length,
++ req->req.no_interrupt ? 'i' : 'I',
++ req->req.zero ? 'Z' : 'z',
++ req->req.short_not_ok ? 's' : 'S',
++ req->req.status,
++ req->submitted ? 'F' : 'f',
++ req->using_dma ? 'D' : 'd',
++ req->last_transaction ? 'L' : 'l');
++ len = min(len, sizeof(tmpbuf));
++ if (len > nbytes)
+ break;
-+ }
+
-+ if (dtomul >= 8) {
-+ dtomul = 7;
-+ dtocyc = 15;
++ list_del(&req->queue);
++ kfree(req);
++
++ remaining = __copy_to_user(buf, tmpbuf, len);
++ actual += len - remaining;
++ if (remaining)
++ break;
++
++ nbytes -= len;
++ buf += len;
+ }
++ mutex_unlock(&file->f_dentry->d_inode->i_mutex);
+
-+ 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 actual;
+}
+
-+/*
-+ * 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)
++static int queue_dbg_release(struct inode *inode, struct file *file)
+{
-+ 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);
++ struct list_head *queue_data = file->private_data;
++ struct usba_request *req, *tmp_req;
+
-+ 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);
++ list_for_each_entry_safe(req, tmp_req, queue_data, queue) {
++ list_del(&req->queue);
++ kfree(req);
+ }
++ kfree(queue_data);
++ return 0;
++}
+
-+ /*
-+ * 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);
++static int regs_dbg_open(struct inode *inode, struct file *file)
++{
++ struct usba_udc *udc;
++ unsigned int i;
++ u32 *data;
++ int ret = -ENOMEM;
+
-+ if (mmc->ios.bus_mode == MMC_BUSMODE_OPENDRAIN)
-+ cmdr |= MCI_BIT(OPDCMD);
++ mutex_lock(&inode->i_mutex);
++ udc = inode->i_private;
++ data = kmalloc(inode->i_size, GFP_KERNEL);
++ if (!data)
++ goto out;
+
-+ iflags = MCI_BIT(CMDRDY) | MCI_CMD_ERROR_FLAGS;
-+ if (!(cmd->flags & MMC_RSP_CRC))
-+ iflags &= ~MCI_BIT(RCRCE);
++ spin_lock_irq(&udc->lock);
++ for (i = 0; i < inode->i_size / 4; i++)
++ data[i] = __raw_readl(udc->regs + i * 4);
++ spin_unlock_irq(&udc->lock);
+
-+ 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);
++ file->private_data = data;
++ ret = 0;
+
-+ *cmd_flags = cmdr;
-+ return iflags;
++out:
++ mutex_unlock(&inode->i_mutex);
++
++ return ret;
+}
+
-+static void atmci_start_command(struct atmel_mci *host,
-+ struct mmc_command *cmd,
-+ u32 cmd_flags)
++static ssize_t regs_dbg_read(struct file *file, char __user *buf,
++ size_t nbytes, loff_t *ppos)
+{
-+ WARN_ON(host->cmd);
-+ host->cmd = cmd;
++ struct inode *inode = file->f_dentry->d_inode;
++ int ret;
+
-+ mci_writel(host, ARGR, cmd->arg);
-+ mci_writel(host, CMDR, cmd_flags);
++ 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);
+
-+ if (cmd->data)
-+ dma_start_request(host->dma.req.req.dmac,
-+ host->dma.req.req.channel);
++ return ret;
+}
+
-+/*
-+ * 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)
++static int regs_dbg_release(struct inode *inode, struct file *file)
+{
-+ struct atmel_mci *host = mmc_priv(mmc);
-+ u32 cmd_flags;
++ kfree(file->private_data);
++ return 0;
++}
+
-+ WARN_ON(host->data);
-+ host->data = data;
++const struct file_operations queue_dbg_fops = {
++ .owner = THIS_MODULE,
++ .open = queue_dbg_open,
++ .llseek = no_llseek,
++ .read = queue_dbg_read,
++ .release = queue_dbg_release,
++};
+
-+ 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;
++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,
++};
+
-+ 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);
++static void usba_ep_init_debugfs(struct usba_udc *udc,
++ struct usba_ep *ep)
++{
++ struct dentry *ep_root;
+
-+ 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;
++ ep_root = debugfs_create_dir(ep_name(ep), udc->debugfs_root);
++ if (!ep_root)
++ goto err_root;
++ ep->debugfs_dir = ep_root;
++
++ ep->debugfs_queue = debugfs_create_file("queue", 0400, ep_root,
++ ep, &queue_dbg_fops);
++ if (!ep->debugfs_queue)
++ goto err_queue;
++
++ if (ep_can_dma(ep)) {
++ ep->debugfs_dma_status
++ = debugfs_create_u32("dma_status", 0400, ep_root,
++ &ep->last_dma_status);
++ if (!ep->debugfs_dma_status)
++ goto err_dma_status;
++ }
++ if (ep_is_control(ep)) {
++ ep->debugfs_state
++ = debugfs_create_u32("state", 0400, ep_root,
++ &ep->state);
++ if (!ep->debugfs_state)
++ goto err_state;
+ }
-+ host->dma.req.sg = data->sg;
+
-+ dma_prepare_request_sg(host->dma.req.req.dmac, &host->dma.req);
++ return;
+
-+ return cmd_flags;
++err_state:
++ if (ep_can_dma(ep))
++ debugfs_remove(ep->debugfs_dma_status);
++err_dma_status:
++ debugfs_remove(ep->debugfs_queue);
++err_queue:
++ debugfs_remove(ep_root);
++err_root:
++ dev_err(&ep->udc->pdev->dev,
++ "failed to create debugfs directory for %s\n", ep_name(ep));
+}
+
-+static void atmci_request(struct mmc_host *mmc, struct mmc_request *mrq)
++static void usba_ep_cleanup_debugfs(struct usba_ep *ep)
+{
-+ struct atmel_mci *host = mmc_priv(mmc);
-+ struct mmc_data *data = mrq->data;
-+ u32 iflags;
-+ u32 cmdflags = 0;
++ debugfs_remove(ep->debugfs_queue);
++ debugfs_remove(ep->debugfs_dma_status);
++ debugfs_remove(ep->debugfs_state);
++ debugfs_remove(ep->debugfs_dir);
++ ep->debugfs_dma_status = NULL;
++ ep->debugfs_dir = NULL;
++}
+
-+ iflags = mci_readl(host, IMR);
-+ if (iflags)
-+ printk("WARNING: IMR=0x%08x\n", mci_readl(host, IMR));
++static void usba_init_debugfs(struct usba_udc *udc)
++{
++ struct dentry *root, *regs;
++ struct resource *regs_resource;
+
-+ WARN_ON(host->mrq != NULL);
-+ host->mrq = mrq;
-+ host->pending_events = 0;
-+ host->completed_events = 0;
++ root = debugfs_create_dir(udc->gadget.name, NULL);
++ if (IS_ERR(root) || !root)
++ goto err_root;
++ udc->debugfs_root = root;
+
-+ iflags = atmci_prepare_command(mmc, mrq->cmd, &cmdflags);
++ regs = debugfs_create_file("regs", 0400, root, udc, ®s_dbg_fops);
++ if (!regs)
++ goto err_regs;
+
-+ if (mrq->stop) {
-+ BUG_ON(!data);
++ regs_resource = platform_get_resource(udc->pdev, IORESOURCE_MEM,
++ CTRL_IOMEM_ID);
++ regs->d_inode->i_size = regs_resource->end - regs_resource->start + 1;
++ udc->debugfs_regs = regs;
+
-+ 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;
-+ }
++ usba_ep_init_debugfs(udc, to_usba_ep(udc->gadget.ep0));
+
-+ atmci_start_command(host, mrq->cmd, cmdflags);
-+ mci_writel(host, IER, iflags);
++ return;
++
++err_regs:
++ debugfs_remove(root);
++err_root:
++ udc->debugfs_root = NULL;
++ dev_err(&udc->pdev->dev, "debugfs is not available\n");
+}
+
-+static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
++static void usba_cleanup_debugfs(struct usba_udc *udc)
++{
++ usba_ep_cleanup_debugfs(to_usba_ep(udc->gadget.ep0));
++ debugfs_remove(udc->debugfs_regs);
++ debugfs_remove(udc->debugfs_root);
++ udc->debugfs_regs = NULL;
++ udc->debugfs_root = NULL;
++}
++#else
++static inline void usba_ep_init_debugfs(struct usba_udc *udc,
++ struct usba_ep *ep)
+{
-+ 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;
-+ }
++static inline void usba_ep_cleanup_debugfs(struct usba_ep *ep)
++{
+
-+ 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)
++static inline void usba_init_debugfs(struct usba_udc *udc)
+{
-+ 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 inline void usba_cleanup_debugfs(struct usba_udc *udc)
++{
++
++}
++#endif
+
-+static void atmci_request_end(struct mmc_host *mmc, struct mmc_request *mrq)
++static int vbus_is_present(struct usba_udc *udc)
+{
-+ struct atmel_mci *host = mmc_priv(mmc);
-+
-+ WARN_ON(host->cmd || host->data);
-+ host->mrq = NULL;
++ if (udc->vbus_pin != -1)
++ return gpio_get_value(udc->vbus_pin);
+
-+ mmc_request_done(mmc, mrq);
++ /* No Vbus detection: Assume always present */
++ return 1;
+}
+
-+static void send_stop_cmd(struct mmc_host *mmc, struct mmc_data *data,
-+ u32 flags)
++static void copy_to_fifo(void __iomem *fifo, const void *buf, int len)
+{
-+ struct atmel_mci *host = mmc_priv(mmc);
++ unsigned long tmp;
+
-+ atmci_start_command(host, data->stop, host->stop_cmdr | flags);
-+ mci_writel(host, IER, host->stop_iflags);
++ DBG(DBG_FIFO, "copy to FIFO (len %d):\n", len);
++ for (; len > 0; len -= 4, buf += 4, fifo += 4) {
++ tmp = *(unsigned long *)buf;
++ if (len >= 4) {
++ DBG(DBG_FIFO, " -> %08lx\n", tmp);
++ __raw_writel(tmp, fifo);
++ } else {
++ do {
++ DBG(DBG_FIFO, " -> %02lx\n", tmp >> 24);
++ __raw_writeb(tmp >> 24, fifo);
++ fifo++;
++ tmp <<= 8;
++ } while (--len);
++ break;
++ }
++ }
+}
+
-+static void atmci_data_complete(struct atmel_mci *host, struct mmc_data *data)
++static void copy_from_fifo(void *buf, void __iomem *fifo, int len)
+{
-+ 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));
++ union {
++ unsigned long *w;
++ unsigned char *b;
++ } p;
++ unsigned long tmp;
+
-+ /*
-+ * 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);
++ DBG(DBG_FIFO, "copy from FIFO (len %d):\n", len);
++ for (p.w = buf; len > 0; len -= 4, p.w++, fifo += 4) {
++ if (len >= 4) {
++ tmp = __raw_readl(fifo);
++ *p.w = tmp;
++ DBG(DBG_FIFO, " -> %08lx\n", tmp);
++ } else {
++ do {
++ tmp = __raw_readb(fifo);
++ *p.b = tmp;
++ DBG(DBG_FIFO, " -> %02lx\n", tmp);
++ fifo++, p.b++;
++ } while (--len);
++ }
++ }
+}
+
-+static void atmci_command_error(struct mmc_host *mmc,
-+ struct mmc_command *cmd,
-+ u32 status)
++static void next_fifo_transaction(struct usba_ep *ep,
++ struct usba_request *req)
+{
-+ pr_debug("%s: command error: status=0x%08x\n",
-+ mmc_hostname(mmc), status);
++ unsigned int transaction_len;
+
-+ 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;
++ transaction_len = req->req.length - req->req.actual;
++ req->last_transaction = 1;
++ if (transaction_len > ep->ep.maxpacket) {
++ transaction_len = ep->ep.maxpacket;
++ req->last_transaction = 0;
++ } else if (transaction_len == ep->ep.maxpacket
++ && req->req.zero) {
++ req->last_transaction = 0;
++ }
++ DBG(DBG_QUEUE, "%s: submit_transaction, req %p (length %d)%s\n",
++ ep_name(ep), req, transaction_len,
++ req->last_transaction ? ", done" : "");
++
++ copy_to_fifo(ep->fifo, req->req.buf + req->req.actual, transaction_len);
++ usba_ep_writel(ep, SET_STA, USBA_BIT(TX_PK_RDY));
++ req->req.actual += transaction_len;
+}
+
-+static void atmci_tasklet_func(unsigned long priv)
++static void submit_request(struct usba_ep *ep, struct usba_request *req)
+{
-+ 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;
++ DBG(DBG_QUEUE, "%s: submit_request: req %p (length %d)\n",
++ ep_name(ep), req, req->req.length);
+
-+ pr_debug("atmci_tasklet: pending/completed/mask %lx/%lx/%x\n",
-+ host->pending_events, host->completed_events,
-+ mci_readl(host, IMR));
++ req->req.actual = 0;
++ req->submitted = 1;
+
-+ if (mci_clear_cmd_error_is_pending(host)) {
-+ struct mmc_command *cmd;
++ if (req->using_dma) {
++ if (req->req.length == 0) {
++ usba_ep_writel(ep, CTL_ENB, USBA_BIT(TX_PK_RDY));
++ return;
++ }
+
-+ mci_set_cmd_error_complete(host);
-+ mci_clear_cmd_pending(host);
-+ cmd = host->mrq->cmd;
++ if (req->req.zero)
++ usba_ep_writel(ep, CTL_ENB, USBA_BIT(SHORT_PACKET));
++ else
++ usba_ep_writel(ep, CTL_DIS, USBA_BIT(SHORT_PACKET));
+
-+ if (cmd->data) {
-+ dma_stop_request(host->dma.req.req.dmac,
-+ host->dma.req.req.channel);
-+ host->data = NULL;
++ usba_dma_writel(ep, ADDRESS, req->req.dma);
++ usba_dma_writel(ep, CONTROL, req->ctrl);
++ } else {
++ next_fifo_transaction(ep, req);
++ if (req->last_transaction) {
++ usba_ep_writel(ep, CTL_DIS, USBA_BIT(TX_PK_RDY));
++ usba_ep_writel(ep, CTL_ENB, USBA_BIT(TX_COMPLETE));
++ } else {
++ usba_ep_writel(ep, CTL_DIS, USBA_BIT(TX_COMPLETE));
++ usba_ep_writel(ep, CTL_ENB, USBA_BIT(TX_PK_RDY));
+ }
-+
-+ 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);
++}
++
++static void submit_next_request(struct usba_ep *ep)
++{
++ struct usba_request *req;
++
++ if (list_empty(&ep->queue)) {
++ usba_ep_writel(ep, CTL_DIS, (USBA_BIT(TX_PK_RDY)
++ | USBA_BIT(RX_BK_RDY)));
++ return;
+ }
-+ 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;
++ req = list_entry(ep->queue.next, struct usba_request, queue);
++ if (!req->submitted)
++ submit_request(ep, req);
++}
+
-+ printk(KERN_DEBUG "%s: dma error after %u bytes xfered\n",
-+ mmc_hostname(mmc), host->data->bytes_xfered);
++static void send_status(struct usba_udc *udc, struct usba_ep *ep)
++{
++ ep->state = STATUS_STAGE_IN;
++ usba_ep_writel(ep, SET_STA, USBA_BIT(TX_PK_RDY));
++ usba_ep_writel(ep, CTL_ENB, USBA_BIT(TX_COMPLETE));
++}
+
-+ if (data->stop
-+ && !mci_set_stop_sent_is_completed(host))
-+ /* TODO: Check if card is still present */
-+ send_stop_cmd(host->mmc, data, 0);
++static void receive_data(struct usba_ep *ep)
++{
++ struct usba_udc *udc = ep->udc;
++ struct usba_request *req;
++ unsigned long status;
++ unsigned int bytecount, nr_busy;
++ int is_complete = 0;
+
-+ atmci_data_complete(host, data);
-+ }
-+ if (mci_clear_data_error_is_pending(host)) {
-+ u32 status = host->error_status;
++ status = usba_ep_readl(ep, STA);
++ nr_busy = USBA_BFEXT(BUSY_BANKS, status);
+
-+ mci_set_data_error_complete(host);
-+ mci_clear_data_pending(host);
++ DBG(DBG_QUEUE, "receive data: nr_busy=%u\n", nr_busy);
+
-+ dma_stop_request(host->dma.req.req.dmac,
-+ host->dma.req.req.channel);
++ while (nr_busy > 0) {
++ if (list_empty(&ep->queue)) {
++ usba_ep_writel(ep, CTL_DIS, USBA_BIT(RX_BK_RDY));
++ break;
++ }
++ req = list_entry(ep->queue.next,
++ struct usba_request, queue);
+
-+ printk(KERN_DEBUG "%s: data error: status=0x%08x\n",
-+ mmc_hostname(host->mmc), status);
++ bytecount = USBA_BFEXT(BYTE_COUNT, 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;
++ if (status & (1 << 31))
++ is_complete = 1;
++ if (req->req.actual + bytecount >= req->req.length) {
++ is_complete = 1;
++ bytecount = req->req.length - req->req.actual;
+ }
-+ 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);
++ copy_from_fifo(req->req.buf + req->req.actual,
++ ep->fifo, bytecount);
++ req->req.actual += bytecount;
+
-+ 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));
++ usba_ep_writel(ep, CLR_STA, USBA_BIT(RX_BK_RDY));
++
++ if (is_complete) {
++ DBG(DBG_QUEUE, "%s: request done\n", ep_name(ep));
++ req->req.status = 0;
++ list_del_init(&req->queue);
++ usba_ep_writel(ep, CTL_DIS, USBA_BIT(RX_BK_RDY));
++ req->req.complete(&ep->ep, &req->req);
+ }
+
-+ /* 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;
-+ }
++ status = usba_ep_readl(ep, STA);
++ nr_busy = USBA_BFEXT(BUSY_BANKS, status);
+
-+ host->cmd = NULL;
-+ atmci_request_end(mmc, mrq);
++ if (is_complete && ep_is_control(ep)) {
++ send_status(udc, ep);
++ break;
+ }
-+ mmc_detect_change(host->mmc, msecs_to_jiffies(100));
+ }
+}
+
-+static void atmci_cmd_interrupt(struct mmc_host *mmc, u32 status)
++static void request_complete(struct usba_ep *ep,
++ struct usba_request *req,
++ int status)
+{
-+ struct atmel_mci *host = mmc_priv(mmc);
-+ struct mmc_command *cmd = host->cmd;
++ struct usba_udc *udc = ep->udc;
+
-+ /*
-+ * 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);
++ WARN_ON(!list_empty(&req->queue));
+
-+ mci_writel(host, IDR, MCI_BIT(CMDRDY) | MCI_CMD_ERROR_FLAGS);
-+ host->cmd = NULL;
++ if (req->req.status == -EINPROGRESS)
++ req->req.status = status;
+
-+ if (mci_stop_sent_is_complete(host))
-+ mci_set_stop_pending(host);
-+ else
-+ mci_set_cmd_pending(host);
++ if (req->mapped) {
++ dma_unmap_single(
++ &udc->pdev->dev, req->req.dma, req->req.length,
++ ep_is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
++ req->req.dma = DMA_ADDR_INVALID;
++ req->mapped = 0;
++ }
+
-+ tasklet_schedule(&host->tasklet);
++ DBG(DBG_GADGET | DBG_REQ,
++ "%s: req %p complete: status %d, actual %u\n",
++ ep_name(ep), req, req->req.status, req->req.actual);
++ req->req.complete(&ep->ep, &req->req);
+}
+
-+static void atmci_xfer_complete(struct dma_request *_req)
++static void request_complete_list(struct usba_ep *ep,
++ struct list_head *list,
++ int status)
+{
-+ struct dma_request_sg *req = to_dma_request_sg(_req);
-+ struct atmel_mci_dma *dma;
-+ struct atmel_mci *host;
-+ struct mmc_data *data;
++ struct usba_request *req, *tmp_req;
+
-+ dma = container_of(req, struct atmel_mci_dma, req);
-+ host = container_of(dma, struct atmel_mci, dma);
-+ data = host->data;
++ list_for_each_entry_safe(req, tmp_req, list, queue) {
++ list_del_init(&req->queue);
++ request_complete(ep, req, status);
++ }
++}
+
-+ if (data->stop && !mci_set_stop_sent_is_completed(host))
-+ send_stop_cmd(host->mmc, data, 0);
++static int usba_ep_enable(struct usb_ep *_ep,
++ const struct usb_endpoint_descriptor *desc)
++{
++ struct usba_ep *ep = to_usba_ep(_ep);
++ struct usba_udc *udc = ep->udc;
++ unsigned long flags, ept_cfg, maxpacket;
+
-+ if (data->flags & MMC_DATA_READ) {
-+ mci_writel(host, IDR, MCI_DATA_ERROR_FLAGS);
-+ mci_set_data_pending(host);
-+ tasklet_schedule(&host->tasklet);
++ DBG(DBG_GADGET, "%s: ep_enable: desc=%p\n", ep_name(ep), desc);
++
++ maxpacket = le16_to_cpu(desc->wMaxPacketSize);
++
++ if (ep->index == 0
++ || desc->bDescriptorType != USB_DT_ENDPOINT
++ || ((desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK)
++ != ep->index)
++ || maxpacket == 0
++ || maxpacket > ep->fifo_size) {
++ DBG(DBG_ERR, "ep_enable: Invalid argument");
++ return -EINVAL;
++ }
++
++ ep->is_isoc = 0;
++ ep->is_in = 0;
++
++ if ((desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
++ == USB_ENDPOINT_XFER_ISOC) {
++ if (!ep->can_isoc) {
++ DBG(DBG_ERR, "ep_enable: %s is not isoc capable\n",
++ ep_name(ep));
++ return -EINVAL;
++ }
++ ep->is_isoc = 1;
++ }
++
++ if (maxpacket <= 8)
++ ept_cfg = USBA_BF(EPT_SIZE, USBA_EPT_SIZE_8);
++ else
++ /* LSB is bit 1, not 0 */
++ ept_cfg = USBA_BF(EPT_SIZE, fls(maxpacket - 1) - 3);
++ DBG(DBG_HW, "%s: EPT_SIZE = %lu (maxpacket = %lu)\n",
++ ep_name(ep), ept_cfg, maxpacket);
++
++ if ((desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) {
++ ep->is_in = 1;
++ ept_cfg |= USBA_BIT(EPT_DIR);
++ }
++
++ switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
++ case USB_ENDPOINT_XFER_CONTROL:
++ ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_CONTROL);
++ break;
++ case USB_ENDPOINT_XFER_ISOC:
++ ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_ISO);
++ break;
++ case USB_ENDPOINT_XFER_BULK:
++ ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_BULK);
++ break;
++ case USB_ENDPOINT_XFER_INT:
++ ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_INT);
++ break;
++ }
++ ept_cfg |= USBA_BF(BK_NUMBER, ep->nr_banks);
++
++ spin_lock_irqsave(&ep->udc->lock, flags);
++
++ if (ep->desc) {
++ spin_unlock_irqrestore(&ep->udc->lock, flags);
++ DBG(DBG_ERR, "ep%d already enabled\n", ep->index);
++ return -EBUSY;
++ }
++
++ ep->desc = desc;
++ ep->ep.maxpacket = maxpacket;
++
++ usba_ep_writel(ep, CFG, ept_cfg);
++ usba_ep_writel(ep, CTL_ENB, USBA_BIT(EPT_ENABLE));
++
++ if (ep_can_dma(ep)) {
++ u32 ctrl;
++
++ usba_writel(udc, INT_ENB,
++ (usba_readl(udc, INT_ENB)
++ | USBA_BF(EPT_INT, 1 << ep->index)
++ | USBA_BF(DMA_INT, 1 << ep->index)));
++ ctrl = USBA_BIT(AUTO_VALID) | USBA_BIT(INTDIS_DMA);
++ usba_ep_writel(ep, CTL_ENB, ctrl);
+ } 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));
++ usba_writel(udc, INT_ENB,
++ (usba_readl(udc, INT_ENB)
++ | USBA_BF(EPT_INT, 1 << ep->index)));
++ }
++
++ spin_unlock_irqrestore(&udc->lock, flags);
++
++ DBG(DBG_HW, "EPT_CFG%d after init: %#08lx\n", ep->index,
++ (unsigned long)usba_ep_readl(ep, CFG));
++ DBG(DBG_HW, "INT_ENB after init: %#08lx\n",
++ (unsigned long)usba_readl(udc, INT_ENB));
++
++ return 0;
++}
++
++static int usba_ep_disable(struct usb_ep *_ep)
++{
++ struct usba_ep *ep = to_usba_ep(_ep);
++ struct usba_udc *udc = ep->udc;
++ LIST_HEAD(req_list);
++ unsigned long flags;
++
++ DBG(DBG_GADGET, "ep_disable: %s\n", ep_name(ep));
++
++ spin_lock_irqsave(&udc->lock, flags);
++
++ if (!ep->desc) {
++ spin_unlock_irqrestore(&udc->lock, flags);
++ DBG(DBG_ERR, "ep_disable: %s not enabled\n",
++ ep_name(ep));
++ return -EINVAL;
++ }
++ ep->desc = NULL;
++
++ list_splice_init(&ep->queue, &req_list);
++ if (ep_can_dma(ep)) {
++ usba_dma_writel(ep, CONTROL, 0);
++ usba_dma_writel(ep, ADDRESS, 0);
++ usba_dma_readl(ep, STATUS);
+ }
++ usba_ep_writel(ep, CTL_DIS, USBA_BIT(EPT_ENABLE));
++ usba_writel(udc, INT_ENB, (usba_readl(udc, INT_ENB)
++ & ~USBA_BF(EPT_INT, 1 << ep->index)));
++
++ spin_unlock_irqrestore(&udc->lock, flags);
++
++ request_complete_list(ep, &req_list, -ESHUTDOWN);
++
++ return 0;
+}
+
-+static void atmci_dma_error(struct dma_request *_req)
++static struct usb_request *
++usba_ep_alloc_request(struct usb_ep *_ep, unsigned gfp_flags)
+{
-+ struct dma_request_sg *req = to_dma_request_sg(_req);
-+ struct atmel_mci_dma *dma;
-+ struct atmel_mci *host;
++ struct usba_request *req;
+
-+ dma = container_of(req, struct atmel_mci_dma, req);
-+ host = container_of(dma, struct atmel_mci, dma);
++ DBG(DBG_GADGET, "ep_alloc_request: %p, 0x%x\n", _ep, gfp_flags);
+
-+ mci_writel(host, IDR, (MCI_BIT(NOTBUSY)
-+ | MCI_DATA_ERROR_FLAGS));
++ req = kzalloc(sizeof(*req), gfp_flags);
++ if (!req)
++ return NULL;
+
-+ mci_set_dma_error_pending(host);
-+ tasklet_schedule(&host->tasklet);
++ INIT_LIST_HEAD(&req->queue);
++ req->req.dma = DMA_ADDR_INVALID;
++
++ return &req->req;
+}
+
-+static irqreturn_t atmci_interrupt(int irq, void *dev_id)
++static void
++usba_ep_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
-+ struct mmc_host *mmc = dev_id;
-+ struct atmel_mci *host = mmc_priv(mmc);
-+ u32 status, mask, pending;
++ struct usba_request *req = to_usba_req(_req);
+
-+ spin_lock(&mmc->lock);
++ DBG(DBG_GADGET, "ep_free_request: %p, %p\n", _ep, _req);
+
-+ status = mci_readl(host, SR);
-+ mask = mci_readl(host, IMR);
-+ pending = status & mask;
++ kfree(req);
++}
+
-+ 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);
-+ }
++static void *usba_ep_alloc_buffer(struct usb_ep *_ep, unsigned bytes,
++ dma_addr_t *dma, unsigned gfp_flags)
++{
++ void *buf;
+
-+ status = mci_readl(host, SR);
-+ mask = mci_readl(host, IMR);
-+ pending = status & mask;
-+ } while (pending);
++ if (bytes < L1_CACHE_BYTES)
++ bytes = L1_CACHE_BYTES;
+
-+ spin_unlock(&mmc->lock);
++ buf = kmalloc(bytes, gfp_flags);
+
-+ return IRQ_HANDLED;
++ /*
++ * Seems like we have to map the buffer any chance we get.
++ * ether.c wants us to initialize the dma member of a
++ * different request than the one receiving the buffer, so one
++ * never knows...
++ *
++ * Ah, screw it. The ether driver is probably wrong, and this
++ * is not the right place to do the mapping. The driver
++ * shouldn't mess with our DMA mappings anyway.
++ */
++ *dma = DMA_ADDR_INVALID;
++
++ return buf;
+}
+
-+static irqreturn_t atmci_detect_change(int irq, void *dev_id)
++static void usba_ep_free_buffer(struct usb_ep *_ep, void *buf,
++ dma_addr_t dma, unsigned bytes)
+{
-+ 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;
++ DBG(DBG_GADGET, "ep_free_buffer: %s, buf %p (size %u)\n",
++ _ep->name, buf, bytes);
++ kfree(buf);
+}
+
-+static int __devinit atmci_probe(struct platform_device *pdev)
++static int queue_dma(struct usba_udc *udc, struct usba_ep *ep,
++ struct usba_request *req, gfp_t gfp_flags)
+{
-+ struct mci_platform_data *board;
-+ struct atmel_mci *host;
-+ struct mmc_host *mmc;
-+ struct resource *regs;
-+ int irq;
++ unsigned long flags;
+ 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;
++ DBG(DBG_DMA, "%s: req l/%u d/%08x %c%c%c\n",
++ ep_name(ep), req->req.length, req->req.dma,
++ req->req.zero ? 'Z' : 'z',
++ req->req.short_not_ok ? 'S' : 's',
++ req->req.no_interrupt ? 'I' : 'i');
+
-+ board = pdev->dev.platform_data;
++ if (req->req.length > 0x10000) {
++ /* Lengths from 0 to 65536 (inclusive) are supported */
++ DBG(DBG_ERR, "invalid request length %u\n", req->req.length);
++ return -EINVAL;
++ }
+
-+ mmc = mmc_alloc_host(sizeof(struct atmel_mci), &pdev->dev);
-+ if (!mmc)
-+ return -ENOMEM;
++ req->using_dma = 1;
+
-+ host = mmc_priv(mmc);
-+ host->pdev = pdev;
-+ host->mmc = mmc;
-+ if (board) {
-+ host->detect_pin = board->detect_pin;
-+ host->wp_pin = board->wp_pin;
++ if (req->req.dma == DMA_ADDR_INVALID) {
++ req->req.dma = dma_map_single(
++ &udc->pdev->dev, req->req.buf, req->req.length,
++ ep_is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
++ req->mapped = 1;
+ } else {
-+ host->detect_pin = -1;
-+ host->detect_pin = -1;
++ dma_sync_single_for_device(
++ &udc->pdev->dev, req->req.dma, req->req.length,
++ ep_is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
++ req->mapped = 0;
+ }
+
-+ host->mck = clk_get(&pdev->dev, "mci_clk");
-+ if (IS_ERR(host->mck)) {
-+ ret = PTR_ERR(host->mck);
-+ goto out_free_host;
++ req->ctrl = (USBA_BF(DMA_BUF_LEN, req->req.length)
++ | USBA_BIT(DMA_CH_EN) | USBA_BIT(DMA_END_BUF_IE)
++ | USBA_BIT(DMA_END_TR_EN) | USBA_BIT(DMA_END_TR_IE));
++
++ if (ep_is_in(ep))
++ req->ctrl |= USBA_BIT(DMA_END_BUF_EN);
++
++ /*
++ * Add this request to the queue and submit for DMA if
++ * possible. Check if we're still alive first -- we may have
++ * received a reset since last time we checked.
++ */
++ ret = -ESHUTDOWN;
++ spin_lock_irqsave(&udc->lock, flags);
++ if (ep->desc) {
++ if (list_empty(&ep->queue))
++ submit_request(ep, req);
++
++ list_add_tail(&req->queue, &ep->queue);
++ ret = 0;
+ }
-+ clk_enable(host->mck);
++ spin_unlock_irqrestore(&udc->lock, flags);
+
-+ ret = -ENOMEM;
-+ host->regs = ioremap(regs->start, regs->end - regs->start + 1);
-+ if (!host->regs)
-+ goto out_disable_clk;
++ return ret;
++}
+
-+ host->bus_hz = clk_get_rate(host->mck);
-+ host->mapbase = regs->start;
++static int usba_ep_queue(struct usb_ep *_ep, struct usb_request *_req,
++ gfp_t gfp_flags)
++{
++ struct usba_request *req = to_usba_req(_req);
++ struct usba_ep *ep = to_usba_ep(_ep);
++ struct usba_udc *udc = ep->udc;
++ unsigned long flags;
++ int ret;
+
-+ 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;
++ DBG(DBG_GADGET | DBG_QUEUE | DBG_REQ,
++ "%s: queue req %p, len %u\n", ep_name(ep), req, _req->length);
+
-+ tasklet_init(&host->tasklet, atmci_tasklet_func, (unsigned long)mmc);
++ if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN
++ || !ep->desc)
++ return -ESHUTDOWN;
+
-+ ret = request_irq(irq, atmci_interrupt, 0, "mmci", mmc);
-+ if (ret)
-+ goto out_unmap;
++ req->submitted = 0;
++ req->using_dma = 0;
++ req->last_transaction = 0;
+
-+ /* 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;
-+ }
++ _req->status = -EINPROGRESS;
++ _req->actual = 0;
++
++ if (ep_can_dma(ep))
++ return queue_dma(udc, ep, req, gfp_flags);
++
++ /* May have received a reset since last time we checked */
++ ret = -ESHUTDOWN;
++ spin_lock_irqsave(&udc->lock, flags);
++ if (ep->desc) {
++ list_add_tail(&req->queue, &ep->queue);
++
++ if (ep_is_in(ep)
++ || (ep_is_control(ep)
++ && (ep->state == DATA_STAGE_IN
++ || ep->state == STATUS_STAGE_IN)))
++ usba_ep_writel(ep, CTL_ENB, USBA_BIT(TX_PK_RDY));
++ else
++ usba_ep_writel(ep, CTL_ENB, USBA_BIT(RX_BK_RDY));
++ ret = 0;
+ }
++ spin_unlock_irqrestore(&udc->lock, flags);
+
-+ /* 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;
++ return ret;
++}
++
++static void usba_update_req(struct usba_ep *ep, struct usba_request *req,
++ u32 status)
++{
++ req->req.actual = req->req.length - USBA_BFEXT(DMA_BUF_LEN, status);
++}
++
++static int stop_dma(struct usba_ep *ep, u32 *pstatus)
++{
++ unsigned int timeout;
++ u32 status;
++
++ /*
++ * Stop the DMA controller. When writing both CH_EN
++ * and LINK to 0, the other bits are not affected.
++ */
++ usba_dma_writel(ep, CONTROL, 0);
++
++ /* Wait for the FIFO to empty */
++ for (timeout = 40; timeout; --timeout) {
++ status = usba_dma_readl(ep, STATUS);
++ if (!(status & USBA_BIT(DMA_CH_EN)))
++ break;
++ udelay(1);
+ }
-+ 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;
++
++ if (pstatus)
++ *pstatus = status;
++
++ if (timeout == 0) {
++ dev_err(&ep->udc->pdev->dev,
++ "%s: timed out waiting for DMA FIFO to empty\n",
++ ep_name(ep));
++ return -ETIMEDOUT;
+ }
-+ 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));
++ return 0;
++}
+
-+ platform_set_drvdata(pdev, host);
++static int usba_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
++{
++ struct usba_ep *ep = to_usba_ep(_ep);
++ struct usba_udc *udc = ep->udc;
++ struct usba_request *req = to_usba_req(_req);
++ unsigned long flags;
++ u32 status;
+
-+ mmc_add_host(mmc);
++ DBG(DBG_GADGET | DBG_QUEUE, "ep_dequeue: %s, req %p\n",
++ ep_name(ep), req);
+
-+ 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;
++ spin_lock_irqsave(&udc->lock, flags);
++
++ if (req->using_dma) {
++ /*
++ * If this request is currently being transferred,
++ * stop the DMA controller and reset the FIFO.
++ */
++ if (ep->queue.next == &req->queue) {
++ status = usba_dma_readl(ep, STATUS);
++ if (status & USBA_BIT(DMA_CH_EN))
++ stop_dma(ep, &status);
++
++#ifdef CONFIG_DEBUG_FS
++ ep->last_dma_status = status;
++#endif
++
++ usba_writel(udc, EPT_RST,
++ 1 << ep_index(ep));
++
++ usba_update_req(ep, req, status);
+ }
+ }
+
-+ printk(KERN_INFO "%s: Atmel MCI controller at 0x%08lx irq %d\n",
-+ mmc_hostname(mmc), host->mapbase, irq);
++ /*
++ * Errors should stop the queue from advancing until the
++ * completion function returns.
++ */
++ list_del_init(&req->queue);
++ spin_unlock_irqrestore(&udc->lock, flags);
+
-+ atmci_init_debugfs(host);
++ request_complete(ep, req, -ECONNRESET);
+
-+ return 0;
++ /* Process the next request if any */
++ spin_lock_irqsave(&udc->lock, flags);
++ submit_next_request(ep);
++ spin_unlock_irqrestore(&udc->lock, flags);
+
-+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;
++ return 0;
+}
+
-+static int __devexit atmci_remove(struct platform_device *pdev)
++static int usba_ep_set_halt(struct usb_ep *_ep, int value)
+{
-+ struct atmel_mci *host = platform_get_drvdata(pdev);
-+
-+ platform_set_drvdata(pdev, NULL);
++ struct usba_ep *ep = to_usba_ep(_ep);
++ struct usba_udc *udc = ep->udc;
++ unsigned long flags;
++ int ret = 0;
+
-+ if (host) {
-+ atmci_cleanup_debugfs(host);
++ DBG(DBG_GADGET, "endpoint %s: %s HALT\n", ep_name(ep),
++ value ? "set" : "clear");
+
-+ 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);
-+ }
++ if (!ep->desc) {
++ DBG(DBG_ERR, "Attempted to halt uninitialized ep %s\n",
++ ep_name(ep));
++ return -ENODEV;
++ }
++ if (ep_is_isochronous(ep)) {
++ DBG(DBG_ERR, "Attempted to halt isochronous ep %s\n",
++ ep_name(ep));
++ return -ENOTTY;
++ }
+
-+ mmc_remove_host(host->mmc);
++ spin_lock_irqsave(&udc->lock, flags);
+
-+ mci_writel(host, IDR, ~0UL);
-+ mci_writel(host, CR, MCI_BIT(MCIDIS));
-+ mci_readl(host, SR);
++ /*
++ * We can't halt IN endpoints while there are still data to be
++ * transferred
++ */
++ if (!list_empty(&ep->queue)
++ || ((value && ep_is_in(ep)
++ && (usba_ep_readl(ep, STA)
++ & USBA_BF(BUSY_BANKS, -1L))))) {
++ ret = -EAGAIN;
++ } else {
++ if (value)
++ usba_ep_writel(ep, SET_STA, USBA_BIT(FORCE_STALL));
++ else
++ usba_ep_writel(ep, CLR_STA, (USBA_BIT(FORCE_STALL)
++ | USBA_BIT(TOGGLE_SEQ)));
++ usba_ep_readl(ep, STA);
++ }
+
-+ dma_release_channel(host->dma.req.req.dmac,
-+ host->dma.req.req.channel);
++ spin_unlock_irqrestore(&udc->lock, flags);
+
-+ if (host->wp_pin >= 0)
-+ gpio_free(host->wp_pin);
++ return ret;
++}
+
-+ free_irq(platform_get_irq(pdev, 0), host->mmc);
-+ iounmap(host->regs);
++static int usba_ep_fifo_status(struct usb_ep *_ep)
++{
++ struct usba_ep *ep = to_usba_ep(_ep);
+
-+ clk_disable(host->mck);
-+ clk_put(host->mck);
++ return USBA_BFEXT(BYTE_COUNT, usba_ep_readl(ep, STA));
++}
+
-+ mmc_free_host(host->mmc);
-+ }
-+ return 0;
++static void usba_ep_fifo_flush(struct usb_ep *_ep)
++{
++ struct usba_ep *ep = to_usba_ep(_ep);
++ struct usba_udc *udc = ep->udc;
++
++ usba_writel(udc, EPT_RST, 1 << ep->index);
+}
+
-+static struct platform_driver atmci_driver = {
-+ .probe = atmci_probe,
-+ .remove = __devexit_p(atmci_remove),
-+ .driver = {
-+ .name = DRIVER_NAME,
-+ },
++struct usb_ep_ops usba_ep_ops = {
++ .enable = usba_ep_enable,
++ .disable = usba_ep_disable,
++ .alloc_request = usba_ep_alloc_request,
++ .free_request = usba_ep_free_request,
++ .alloc_buffer = usba_ep_alloc_buffer,
++ .free_buffer = usba_ep_free_buffer,
++ .queue = usba_ep_queue,
++ .dequeue = usba_ep_dequeue,
++ .set_halt = usba_ep_set_halt,
++ .fifo_status = usba_ep_fifo_status,
++ .fifo_flush = usba_ep_fifo_flush,
+};
+
-+static int __init atmci_init(void)
++static int usba_udc_get_frame(struct usb_gadget *gadget)
+{
-+ return platform_driver_register(&atmci_driver);
-+}
++ struct usba_udc *udc = to_usba_udc(gadget);
+
-+static void __exit atmci_exit(void)
-+{
-+ platform_driver_unregister(&atmci_driver);
++ return USBA_BFEXT(FRAME_NUMBER, usba_readl(udc, FNUM));
+}
+
-+module_init(atmci_init);
-+module_exit(atmci_exit);
++struct usb_gadget_ops usba_udc_ops = {
++ .get_frame = usba_udc_get_frame,
++};
+
-+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__
++#define EP(nam, type, idx, dma, isoc) \
++{ \
++ .ep = { \
++ .ops = &usba_ep_ops, \
++ .name = nam, \
++ .maxpacket = type##_FIFO_SIZE, \
++ }, \
++ .udc = &the_udc, \
++ .queue = LIST_HEAD_INIT(usba_ep[idx].queue), \
++ .fifo_size = type##_FIFO_SIZE, \
++ .nr_banks = type##_NR_BANKS, \
++ .index = idx, \
++ .can_dma = dma, \
++ .can_isoc = isoc, \
++}
++
++static struct usba_ep usba_ep[] = {
++ EP("ep0", EP0, 0, 0, 0),
++ EP("ep1in-bulk", BULK, 1, 1, 0),
++ EP("ep2out-bulk", BULK, 2, 1, 0),
++ EP("ep3in-iso", ISO, 3, 1, 1),
++ EP("ep4out-iso", ISO, 4, 1, 1),
++ EP("ep5in-int", INT, 5, 1, 0),
++ EP("ep6out-int", INT, 6, 1, 0),
++};
++#undef EP
++
++static struct usb_endpoint_descriptor usba_ep0_desc = {
++ .bLength = USB_DT_ENDPOINT_SIZE,
++ .bDescriptorType = USB_DT_ENDPOINT,
++ .bEndpointAddress = 0,
++ .bmAttributes = USB_ENDPOINT_XFER_CONTROL,
++ .wMaxPacketSize = __constant_cpu_to_le16(64),
++ /* FIXME: I have no idea what to put here */
++ .bInterval = 1,
++};
+
-+/* 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
++static void nop_release(struct device *dev)
++{
+
-+/* 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
++static struct usba_udc the_udc = {
++ .gadget = {
++ .ops = &usba_udc_ops,
++ .ep0 = &usba_ep[0].ep,
++ .ep_list = LIST_HEAD_INIT(the_udc.gadget.ep_list),
++ .is_dualspeed = 1,
++ .name = "atmel_usba_udc",
++ .dev = {
++ .bus_id = "gadget",
++ .release = nop_release,
++ },
++ },
+
-+/* Bitfields in DTOR */
-+#define MCI_DTOCYC_OFFSET 0
-+#define MCI_DTOCYC_SIZE 4
-+#define MCI_DTOMUL_OFFSET 4
-+#define MCI_DTOMUL_SIZE 3
++ .lock = SPIN_LOCK_UNLOCKED,
++};
+
-+/* Bitfields in SDCR */
-+#define MCI_SDCSEL_OFFSET 0
-+#define MCI_SDCSEL_SIZE 4
-+#define MCI_SDCBUS_OFFSET 7
-+#define MCI_SDCBUS_SIZE 1
++/*
++ * Called with interrupts disabled and udc->lock held.
++ */
++static void reset_all_endpoints(struct usba_udc *udc)
++{
++ struct usba_ep *ep;
++ struct usba_request *req, *tmp_req;
+
-+/* Bitfields in ARGR */
-+#define MCI_ARG_OFFSET 0
-+#define MCI_ARG_SIZE 32
++ usba_writel(udc, EPT_RST, ~0UL);
+
-+/* 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
++ ep = to_usba_ep(udc->gadget.ep0);
++ list_for_each_entry_safe(req, tmp_req, &ep->queue, queue) {
++ list_del_init(&req->queue);
++ request_complete(ep, req, -ECONNRESET);
++ }
+
-+/* Bitfields in BLKR */
-+#define MCI_BCNT_OFFSET 0
-+#define MCI_BCNT_SIZE 16
++ list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) {
++ if (ep->desc)
++ usba_ep_disable(&ep->ep);
++ }
++}
+
-+/* Bitfields in RSPRn */
-+#define MCI_RSP_OFFSET 0
-+#define MCI_RSP_SIZE 32
++static struct usba_ep *get_ep_by_addr(struct usba_udc *udc, u16 wIndex)
++{
++ struct usba_ep *ep;
+
-+/* 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
++ if ((wIndex & USB_ENDPOINT_NUMBER_MASK) == 0)
++ return to_usba_ep(udc->gadget.ep0);
+
-+/* 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
++ list_for_each_entry (ep, &udc->gadget.ep_list, ep.ep_list) {
++ u8 bEndpointAddress;
+
-+/* Constants for RSPTYP */
-+#define MCI_RSPTYP_NO_RESP 0
-+#define MCI_RSPTYP_48_BIT 1
-+#define MCI_RSPTYP_136_BIT 2
++ if (!ep->desc)
++ continue;
++ bEndpointAddress = ep->desc->bEndpointAddress;
++ if ((wIndex ^ bEndpointAddress) & USB_DIR_IN)
++ continue;
++ if ((wIndex & USB_ENDPOINT_NUMBER_MASK)
++ == (bEndpointAddress & USB_ENDPOINT_NUMBER_MASK))
++ return ep;
++ }
+
-+/* 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
++ return NULL;
++}
+
-+/* Constants for TRCMD */
-+#define MCI_TRCMD_NO_TRANS 0
-+#define MCI_TRCMD_START_TRANS 1
-+#define MCI_TRCMD_STOP_TRANS 2
++/* Called with interrupts disabled and udc->lock held */
++static inline void set_protocol_stall(struct usba_udc *udc,
++ struct usba_ep *ep)
++{
++ usba_ep_writel(ep, SET_STA, USBA_BIT(FORCE_STALL));
++ ep->state = WAIT_FOR_SETUP;
++}
+
-+/* Constants for TRTYP */
-+#define MCI_TRTYP_BLOCK 0
-+#define MCI_TRTYP_MULTI_BLOCK 1
-+#define MCI_TRTYP_STREAM 2
++static inline int is_stalled(struct usba_udc *udc, struct usba_ep *ep)
++{
++ if (usba_ep_readl(ep, STA) & USBA_BIT(FORCE_STALL))
++ return 1;
++ return 0;
++}
+
-+/* 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))
++static inline void set_address(struct usba_udc *udc, unsigned int addr)
++{
++ u32 regval;
+
-+/* 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)
++ DBG(DBG_BUS, "setting address %u...\n", addr);
++ regval = usba_readl(udc, CTRL);
++ regval = USBA_BFINS(DEV_ADDR, addr, regval);
++ usba_writel(udc, CTRL, regval);
++}
+
-+#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.
++static int do_test_mode(struct usba_udc *udc)
++{
++ static const char test_packet_buffer[] = {
++ /* JKJKJKJK * 9 */
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ /* JJKKJJKK * 8 */
++ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
++ /* JJKKJJKK * 8 */
++ 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
++ /* JJJJJJJKKKKKKK * 8 */
++ 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
++ /* JJJJJJJK * 8 */
++ 0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD,
++ /* {JKKKKKKK * 10}, JK */
++ 0xFC, 0x7E, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD, 0x7E
++ };
++ struct device *dev = &udc->pdev->dev;
++ struct usba_ep *ep;
++ int test_mode;
++
++ test_mode = udc->test_mode;
+
-+ If unsure, say N.
++ /* Start from a clean slate */
++ reset_all_endpoints(udc);
+
- 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)
++ switch (test_mode) {
++ case 0x0100:
++ /* Test_J */
++ usba_writel(udc, TST, USBA_BIT(TST_J_MODE));
++ dev_info(dev, "Entering Test_J mode...\n");
++ break;
++ case 0x0200:
++ /* Test_K */
++ usba_writel(udc, TST, USBA_BIT(TST_K_MODE));
++ dev_info(dev, "Entering Test_K mode...\n");
++ break;
++ case 0x0300:
++ /*
++ * Test_SE0_NAK: Force high-speed mode and set up ep0
++ * for Bulk IN transfers
++ */
++ ep = &usba_ep[0];
++ usba_writel(udc, TST,
++ USBA_BF(SPEED_CFG, USBA_SPEED_CFG_FORCE_HIGH));
++ usba_ep_writel(ep, CFG,
++ USBA_BF(EPT_SIZE, USBA_EPT_SIZE_64)
++ | USBA_BIT(EPT_DIR)
++ | USBA_BF(EPT_TYPE, USBA_EPT_TYPE_BULK)
++ | USBA_BF(BK_NUMBER, 1));
++ if (!(usba_ep_readl(ep, CFG) & USBA_BIT(EPT_MAPPED))) {
++ set_protocol_stall(udc, ep);
++ dev_err(dev, "Test_SE0_NAK: ep0 not mapped\n");
++ } else {
++ usba_ep_writel(ep, CTL_ENB, USBA_BIT(EPT_ENABLE));
++ dev_info(dev, "Entering Test_SE0_NAK mode...\n");
++ }
++ break;
++ case 0x0400:
++ /* Test_Packet */
++ ep = &usba_ep[0];
++ usba_ep_writel(ep, CFG,
++ USBA_BF(EPT_SIZE, USBA_EPT_SIZE_64)
++ | USBA_BIT(EPT_DIR)
++ | USBA_BF(EPT_TYPE, USBA_EPT_TYPE_BULK)
++ | USBA_BF(BK_NUMBER, 1));
++ if (!(usba_ep_readl(ep, CFG) & USBA_BIT(EPT_MAPPED))) {
++ set_protocol_stall(udc, ep);
++ dev_err(dev, "Test_Packet: ep0 not mapped\n");
++ } else {
++ usba_ep_writel(ep, CTL_ENB, USBA_BIT(EPT_ENABLE));
++ usba_writel(udc, TST, USBA_BIT(TST_PKT_MODE));
++ copy_to_fifo(ep->fifo, test_packet_buffer,
++ sizeof(test_packet_buffer));
++ usba_ep_writel(ep, SET_STA, USBA_BIT(TX_PK_RDY));
++ dev_info(dev, "Entering Test_Packet mode...\n");
++ }
++ break;
++ default:
++ dev_err(dev, "Invalid test mode: 0x%04x\n", test_mode);
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++/* Avoid overly long expressions */
++static inline bool feature_is_dev_remote_wakeup(struct usb_ctrlrequest *crq)
+{
-+ 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;
++ if (crq->wValue == __constant_cpu_to_le16(USB_DEVICE_REMOTE_WAKEUP))
++ return true;
++ return false;
++}
+
-+ /* Reverse byteswapping */
-+ extp->FeatureSupport = cpu_to_le32(extp->FeatureSupport);
-+ extp->BlkStatusRegMask = cpu_to_le16(extp->BlkStatusRegMask);
-+ extp->ProtRegAddr = cpu_to_le16(extp->ProtRegAddr);
++static inline bool feature_is_dev_test_mode(struct usb_ctrlrequest *crq)
++{
++ if (crq->wValue == __constant_cpu_to_le16(USB_DEVICE_TEST_MODE))
++ return true;
++ return false;
++}
+
-+ memcpy(&atmel_pri, extp, sizeof(atmel_pri));
-+ memset((char *)extp + 5, 0, sizeof(*extp) - 5);
++static inline bool feature_is_ep_halt(struct usb_ctrlrequest *crq)
++{
++ if (crq->wValue == __constant_cpu_to_le16(USB_ENDPOINT_HALT))
++ return true;
++ return false;
++}
+
-+ printk(KERN_ERR "atmel Features: %02x\n", atmel_pri.Features);
++static int handle_ep0_setup(struct usba_udc *udc, struct usba_ep *ep,
++ struct usb_ctrlrequest *crq)
++{
++ switch (crq->bRequest) {
++ case USB_REQ_GET_STATUS: {
++ u16 status;
+
-+ 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);
++ if (crq->bRequestType == (USB_DIR_IN | USB_RECIP_DEVICE)) {
++ /* Self-powered, no remote wakeup */
++ status = __constant_cpu_to_le16(1 << 0);
++ } else if (crq->bRequestType
++ == (USB_DIR_IN | USB_RECIP_INTERFACE)) {
++ status = __constant_cpu_to_le16(0);
++ } else if (crq->bRequestType
++ == (USB_DIR_IN | USB_RECIP_ENDPOINT)) {
++ struct usba_ep *target;
+
-+ extp->FeatureSupport = features;
++ target = get_ep_by_addr(udc, le16_to_cpu(crq->wIndex));
++ if (!target)
++ goto stall;
+
-+ /* burst write mode not supported */
-+ cfi->cfiq->BufWriteTimeoutTyp = 0;
-+ cfi->cfiq->BufWriteTimeoutMax = 0;
-+}
++ status = 0;
++ if (is_stalled(udc, target))
++ status |= __constant_cpu_to_le16(1);
++ } else {
++ goto delegate;
++ }
+
- #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;
++ /* Write directly to the FIFO. No queueing is done. */
++ if (crq->wLength != __constant_cpu_to_le16(sizeof(status)))
++ goto stall;
++ ep->state = DATA_STAGE_IN;
++ __raw_writew(status, ep->fifo);
++ usba_ep_writel(ep, SET_STA, USBA_BIT(TX_PK_RDY));
++ break;
++ }
+
-+ /* 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;
++ case USB_REQ_CLEAR_FEATURE: {
++ if (crq->bRequestType == USB_RECIP_DEVICE) {
++ if (feature_is_dev_remote_wakeup(crq)) {
++ /* TODO: Handle REMOTE_WAKEUP */
+ } 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;
++ /* Can't CLEAR_FEATURE TEST_MODE */
++ goto stall;
++ }
++ } else if (crq->bRequestType == USB_RECIP_ENDPOINT) {
++ struct usba_ep *target;
++
++ if (!feature_is_ep_halt(crq)
++ || crq->wLength != __constant_cpu_to_le16(0))
++ goto stall;
++ target = get_ep_by_addr(udc, le16_to_cpu(crq->wIndex));
++ if (!target)
++ goto stall;
++
++ usba_ep_writel(target, CLR_STA,
++ (USBA_BIT(FORCE_STALL)
++ | USBA_BIT(TOGGLE_SEQ)));
++ } else {
++ goto delegate;
+ }
-
- // 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>
++ send_status(udc, ep);
++ break;
++ }
+
-+#include <asm/arch/board.h>
-+#include <asm/arch/cpu.h>
-+#include <asm/arch/gpio.h>
++ case USB_REQ_SET_FEATURE: {
++ if (crq->bRequestType == USB_RECIP_DEVICE) {
++ if (feature_is_dev_test_mode(crq)) {
++ send_status(udc, ep);
++ ep->state = STATUS_STAGE_TEST;
++ udc->test_mode = le16_to_cpu(crq->wIndex);
++ return 0;
++ } else if (feature_is_dev_remote_wakeup(crq)) {
++ /* TODO: Handle REMOTE_WAKEUP */
++ } else {
++ goto stall;
++ }
++ } else if (crq->bRequestType == USB_RECIP_ENDPOINT) {
++ struct usba_ep *target;
+
-+#include <video/atmel_lcdc.h>
++ if (!feature_is_ep_halt(crq)
++ || crq->wLength != __constant_cpu_to_le16(0))
++ goto stall;
+
-+#define lcdc_readl(sinfo, reg) __raw_readl((sinfo)->mmio+(reg))
-+#define lcdc_writel(sinfo, reg, val) __raw_writel((val), (sinfo)->mmio+(reg))
++ target = get_ep_by_addr(udc, le16_to_cpu(crq->wIndex));
++ if (!target)
++ goto stall;
+
-+/* configurable parameters */
-+#define ATMEL_LCDC_CVAL_DEFAULT 0xc8
-+#define ATMEL_LCDC_DMA_BURST_LEN 8
++ usba_ep_writel(target, SET_STA, USBA_BIT(FORCE_STALL));
++ } else
++ goto delegate;
+
-+#if defined(CONFIG_ARCH_AT91SAM9263)
-+#define ATMEL_LCDC_FIFO_SIZE 2048
-+#else
-+#define ATMEL_LCDC_FIFO_SIZE 512
-+#endif
++ send_status(udc, ep);
++ break;
++ }
+
-+#if defined(CONFIG_ARCH_AT91)
-+#define ATMEL_LCDFB_FBINFO_DEFAULT FBINFO_DEFAULT
++ case USB_REQ_SET_ADDRESS:
++ if (crq->bRequestType != (USB_DIR_OUT | USB_RECIP_DEVICE))
++ goto delegate;
+
-+static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
-+ struct fb_var_screeninfo *var)
-+{
++ set_address(udc, le16_to_cpu(crq->wValue));
++ send_status(udc, ep);
++ ep->state = STATUS_STAGE_ADDR;
++ break;
++
++ default:
++delegate:
++ return udc->driver->setup(&udc->gadget, crq);
++ }
+
++ return 0;
++
++stall:
++ printk(KERN_ERR
++ "udc: %s: Invalid setup request: %02x.%02x v%04x i%04x l%d, "
++ "halting endpoint...\n",
++ ep_name(ep), crq->bRequestType, crq->bRequest,
++ le16_to_cpu(crq->wValue), le16_to_cpu(crq->wIndex),
++ le16_to_cpu(crq->wLength));
++ set_protocol_stall(udc, ep);
++ return -1;
+}
-+#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)
++static void usba_control_irq(struct usba_udc *udc, struct usba_ep *ep)
+{
-+ u32 dma2dcfg;
-+ u32 pixeloff;
++ struct usba_request *req;
++ u32 epstatus;
++ u32 epctrl;
++
++restart:
++ epstatus = usba_ep_readl(ep, STA);
++ epctrl = usba_ep_readl(ep, CTL);
++
++ DBG(DBG_INT, "%s [%d]: s/%08x c/%08x\n",
++ ep_name(ep), ep->state, epstatus, epctrl);
++
++ req = NULL;
++ if (!list_empty(&ep->queue))
++ req = list_entry(ep->queue.next,
++ struct usba_request, queue);
++
++ if ((epctrl & USBA_BIT(TX_PK_RDY))
++ && !(epstatus & USBA_BIT(TX_PK_RDY))) {
++ if (req->submitted)
++ next_fifo_transaction(ep, req);
++ else
++ submit_request(ep, req);
++
++ if (req->last_transaction) {
++ usba_ep_writel(ep, CTL_DIS, USBA_BIT(TX_PK_RDY));
++ usba_ep_writel(ep, CTL_ENB, USBA_BIT(TX_COMPLETE));
++ }
++ goto restart;
++ }
++ if ((epstatus & epctrl) & USBA_BIT(TX_COMPLETE)) {
++ usba_ep_writel(ep, CLR_STA, USBA_BIT(TX_COMPLETE));
++
++ switch (ep->state) {
++ case DATA_STAGE_IN:
++ usba_ep_writel(ep, CTL_ENB, USBA_BIT(RX_BK_RDY));
++ usba_ep_writel(ep, CTL_DIS, USBA_BIT(TX_COMPLETE));
++ ep->state = STATUS_STAGE_OUT;
++ break;
++ case STATUS_STAGE_ADDR:
++ /* Activate our new address */
++ usba_writel(udc, CTRL, (usba_readl(udc, CTRL)
++ | USBA_BIT(FADDR_EN)));
++ usba_ep_writel(ep, CTL_DIS, USBA_BIT(TX_COMPLETE));
++ ep->state = WAIT_FOR_SETUP;
++ break;
++ case STATUS_STAGE_IN:
++ if (req) {
++ list_del_init(&req->queue);
++ request_complete(ep, req, 0);
++ submit_next_request(ep);
++ }
++ usba_ep_writel(ep, CTL_DIS, USBA_BIT(TX_COMPLETE));
++ ep->state = WAIT_FOR_SETUP;
++ break;
++ case STATUS_STAGE_TEST:
++ usba_ep_writel(ep, CTL_DIS, USBA_BIT(TX_COMPLETE));
++ ep->state = WAIT_FOR_SETUP;
++ if (do_test_mode(udc))
++ set_protocol_stall(udc, ep);
++ break;
++ default:
++ printk(KERN_ERR
++ "udc: %s: TXCOMP: Invalid endpoint state %d, "
++ "halting endpoint...\n",
++ ep_name(ep), ep->state);
++ set_protocol_stall(udc, ep);
++ break;
++ }
++
++ goto restart;
++ }
++ if ((epstatus & epctrl) & USBA_BIT(RX_BK_RDY)) {
++ switch (ep->state) {
++ case STATUS_STAGE_OUT:
++ usba_ep_writel(ep, CLR_STA, USBA_BIT(RX_BK_RDY));
++ usba_ep_writel(ep, CTL_DIS, USBA_BIT(RX_BK_RDY));
++
++ if (req) {
++ list_del_init(&req->queue);
++ request_complete(ep, req, 0);
++ }
++ ep->state = WAIT_FOR_SETUP;
++ break;
++
++ case DATA_STAGE_OUT:
++ receive_data(ep);
++ break;
++
++ default:
++ usba_ep_writel(ep, CLR_STA, USBA_BIT(RX_BK_RDY));
++ usba_ep_writel(ep, CTL_DIS, USBA_BIT(RX_BK_RDY));
++ printk(KERN_ERR
++ "udc: %s: RXRDY: Invalid endpoint state %d, "
++ "halting endpoint...\n",
++ ep_name(ep), ep->state);
++ set_protocol_stall(udc, ep);
++ break;
++ }
+
-+ pixeloff = (var->xoffset * var->bits_per_pixel) & 0x1f;
++ goto restart;
++ }
++ if (epstatus & USBA_BIT(RX_SETUP)) {
++ union {
++ struct usb_ctrlrequest crq;
++ unsigned long data[2];
++ } crq;
++ unsigned int pkt_len;
++ int ret;
++
++ if (ep->state != WAIT_FOR_SETUP) {
++ /*
++ * Didn't expect a SETUP packet at this
++ * point. Clean up any pending requests (which
++ * may be successful).
++ */
++ int status = -EPROTO;
+
-+ dma2dcfg = ((var->xres_virtual - var->xres) * var->bits_per_pixel) / 8;
-+ dma2dcfg |= pixeloff << ATMEL_LCDC_PIXELOFF_OFFSET;
-+ lcdc_writel(sinfo, ATMEL_LCDC_DMA2DCFG, dma2dcfg);
++ /*
++ * RXRDY and TXCOMP are dropped when SETUP
++ * packets arrive. Just pretend we received
++ * the status packet.
++ */
++ if (ep->state == STATUS_STAGE_OUT
++ || ep->state == STATUS_STAGE_IN) {
++ usba_ep_writel(ep, CTL_DIS,
++ USBA_BIT(RX_BK_RDY));
++ status = 0;
++ }
+
-+ /* Update configuration */
-+ lcdc_writel(sinfo, ATMEL_LCDC_DMACON,
-+ lcdc_readl(sinfo, ATMEL_LCDC_DMACON)
-+ | ATMEL_LCDC_DMAUPDT);
-+}
-+#endif
++ if (req) {
++ list_del_init(&req->queue);
++ request_complete(ep, req, status);
++ }
++ }
+
++ pkt_len = USBA_BFEXT(BYTE_COUNT, usba_ep_readl(ep, STA));
++ DBG(DBG_HW, "Packet length: %u\n", pkt_len);
++ if (pkt_len != sizeof(crq)) {
++ printk(KERN_WARNING
++ "udc: Invalid packet length %u (expected %lu)\n",
++ pkt_len, sizeof(crq));
++ set_protocol_stall(udc, ep);
++ return;
++ }
+
-+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,
-+};
++ DBG(DBG_FIFO, "Copying ctrl request from 0x%p:\n", ep->fifo);
++ copy_from_fifo(crq.data, ep->fifo, sizeof(crq));
+
++ /* Free up one bank in the FIFO so that we can
++ * generate or receive a reply right away. */
++ usba_ep_writel(ep, CLR_STA, USBA_BIT(RX_SETUP));
+
-+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;
++ /* printk(KERN_DEBUG "setup: %d: %02x.%02x\n",
++ ep->state, crq.crq.bRequestType,
++ crq.crq.bRequest); */
+
-+ dma_addr = (fix->smem_start + var->yoffset * fix->line_length
-+ + var->xoffset * var->bits_per_pixel / 8);
++ if (crq.crq.bRequestType & USB_DIR_IN) {
++ /*
++ * The USB 2.0 spec states that "if wLength is
++ * zero, there is no data transfer phase."
++ * However, testusb #14 seems to actually
++ * expect a data phase even if wLength = 0...
++ */
++ ep->state = DATA_STAGE_IN;
++ } else {
++ if (crq.crq.wLength != __constant_cpu_to_le16(0))
++ ep->state = DATA_STAGE_OUT;
++ else
++ ep->state = STATUS_STAGE_IN;
++ }
+
-+ dma_addr &= ~3UL;
++ ret = -1;
++ if (ep->index == 0)
++ ret = handle_ep0_setup(udc, ep, &crq.crq);
++ else
++ ret = udc->driver->setup(&udc->gadget, &crq.crq);
+
-+ /* Set framebuffer DMA base address and pixel offset */
-+ lcdc_writel(sinfo, ATMEL_LCDC_DMABADDR1, dma_addr);
++ DBG(DBG_BUS, "req %02x.%02x, length %d, state %d, ret %d\n",
++ crq.crq.bRequestType, crq.crq.bRequest,
++ le16_to_cpu(crq.crq.wLength), ep->state, ret);
+
-+ atmel_lcdfb_update_dma2d(sinfo, var);
++ if (ret < 0) {
++ /* Let the host know that we failed */
++ set_protocol_stall(udc, ep);
++ }
++ }
+}
+
-+static inline void atmel_lcdfb_free_video_memory(struct atmel_lcdfb_info *sinfo)
++static void usba_ep_irq(struct usba_udc *udc, struct usba_ep *ep)
+{
-+ struct fb_info *info = sinfo->info;
++ struct usba_request *req;
++ u32 epstatus;
++ u32 epctrl;
+
-+ dma_free_writecombine(info->device, info->fix.smem_len,
-+ info->screen_base, info->fix.smem_start);
-+}
++ epstatus = usba_ep_readl(ep, STA);
++ epctrl = usba_ep_readl(ep, CTL);
+
-+/**
-+ * 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;
++ DBG(DBG_INT, "%s: interrupt, status: 0x%08x\n",
++ ep_name(ep), epstatus);
+
-+ info->fix.smem_len = (var->xres_virtual * var->yres_virtual
-+ * ((var->bits_per_pixel + 7) / 8));
++ while ((epctrl & USBA_BIT(TX_PK_RDY))
++ && !(epstatus & USBA_BIT(TX_PK_RDY))) {
++ DBG(DBG_BUS, "%s: TX PK ready\n", ep_name(ep));
+
-+ info->screen_base = dma_alloc_writecombine(info->device, info->fix.smem_len,
-+ (dma_addr_t *)&info->fix.smem_start, GFP_KERNEL);
++ if (list_empty(&ep->queue)) {
++ dev_warn(&udc->pdev->dev, "ep_irq: queue empty\n");
++ usba_ep_writel(ep, CTL_DIS, USBA_BIT(TX_PK_RDY));
++ return;
++ }
+
-+ if (!info->screen_base) {
-+ return -ENOMEM;
-+ }
++ req = list_entry(ep->queue.next, struct usba_request, queue);
++
++ if (req->using_dma) {
++ /* Send a zero-length packet */
++ usba_ep_writel(ep, SET_STA,
++ USBA_BIT(TX_PK_RDY));
++ usba_ep_writel(ep, CTL_DIS,
++ USBA_BIT(TX_PK_RDY));
++ list_del_init(&req->queue);
++ submit_next_request(ep);
++ request_complete(ep, req, 0);
++ } else {
++ if (req->submitted)
++ next_fifo_transaction(ep, req);
++ else
++ submit_request(ep, req);
+
-+ return 0;
++ if (req->last_transaction) {
++ list_del_init(&req->queue);
++ submit_next_request(ep);
++ request_complete(ep, req, 0);
++ }
++ }
++
++ epstatus = usba_ep_readl(ep, STA);
++ epctrl = usba_ep_readl(ep, CTL);
++ }
++ if ((epstatus & epctrl) & USBA_BIT(RX_BK_RDY)) {
++ DBG(DBG_BUS, "%s: RX data ready\n", ep_name(ep));
++ receive_data(ep);
++ usba_ep_writel(ep, CLR_STA, USBA_BIT(RX_BK_RDY));
++ }
+}
+
-+/**
-+ * 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)
++static void usba_dma_irq(struct usba_udc *udc, struct usba_ep *ep)
+{
-+ struct device *dev = info->device;
-+ struct atmel_lcdfb_info *sinfo = info->par;
-+ unsigned long clk_value_khz;
++ struct usba_request *req;
++ u32 status, control, pending;
+
-+ clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000;
++ status = usba_dma_readl(ep, STATUS);
++ control = usba_dma_readl(ep, CONTROL);
++#ifdef CONFIG_DEBUG_FS
++ ep->last_dma_status = status;
++#endif
++ pending = status & control;
++ DBG(DBG_INT | DBG_DMA, "dma irq, s/%#08x, c/%#08x\n",
++ status, control);
+
-+ 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 (status & USBA_BIT(DMA_CH_EN)) {
++ dev_err(&udc->pdev->dev,
++ "DMA_CH_EN is set after transfer is finished!\n");
++ dev_err(&udc->pdev->dev,
++ "status=%#08x, pending=%#08x, control=%#08x\n",
++ status, pending, control);
+
-+ 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;
++ /*
++ * try to pretend nothing happened. We might have to
++ * do something here...
++ */
+ }
+
-+ /* Force same alignment for each line */
-+ var->xres = (var->xres + 3) & ~3UL;
-+ var->xres_virtual = (var->xres_virtual + 3) & ~3UL;
++ if (list_empty(&ep->queue))
++ /* Might happen if a reset comes along at the right moment */
++ return;
+
-+ 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;
++ if (pending & (USBA_BIT(DMA_END_TR_ST) | USBA_BIT(DMA_END_BUF_ST))) {
++ req = list_entry(ep->queue.next, struct usba_request, queue);
++ usba_update_req(ep, req, status);
+
-+ 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;
++ list_del_init(&req->queue);
++ submit_next_request(ep);
++ request_complete(ep, req, 0);
+ }
-+
-+ 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)
++static irqreturn_t usba_udc_irq(int irq, void *devid)
+{
-+ struct atmel_lcdfb_info *sinfo = info->par;
-+ unsigned long value;
-+ unsigned long clk_value_khz;
++ struct usba_udc *udc = devid;
++ u32 status;
++ u32 dma_status;
++ u32 ep_status;
++
++ spin_lock(&udc->lock);
+
-+ 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);
++ status = usba_readl(udc, INT_STA);
++ DBG(DBG_INT, "irq, status=%#08x\n", status);
+
-+ /* Turn off the LCD controller and the DMA controller */
-+ lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET);
++ if (status & USBA_BIT(DET_SUSPEND)) {
++ usba_writel(udc, INT_CLR, USBA_BIT(DET_SUSPEND));
++ DBG(DBG_BUS, "Suspend detected\n");
++ if (udc->gadget.speed != USB_SPEED_UNKNOWN
++ && udc->driver && udc->driver->suspend)
++ udc->driver->suspend(&udc->gadget);
++ }
+
-+ lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0);
++ if (status & USBA_BIT(WAKE_UP)) {
++ usba_writel(udc, INT_CLR, USBA_BIT(WAKE_UP));
++ DBG(DBG_BUS, "Wake Up CPU detected\n");
++ }
+
-+ if (info->var.bits_per_pixel <= 8)
-+ info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-+ else
-+ info->fix.visual = FB_VISUAL_TRUECOLOR;
++ if (status & USBA_BIT(END_OF_RESUME)) {
++ usba_writel(udc, INT_CLR, USBA_BIT(END_OF_RESUME));
++ DBG(DBG_BUS, "Resume detected\n");
++ if (udc->gadget.speed != USB_SPEED_UNKNOWN
++ && udc->driver && udc->driver->resume)
++ udc->driver->resume(&udc->gadget);
++ }
+
-+ info->fix.line_length = info->var.xres_virtual * (info->var.bits_per_pixel / 8);
++ dma_status = USBA_BFEXT(DMA_INT, status);
++ if (dma_status) {
++ int i;
+
-+ /* Re-initialize the DMA engine... */
-+ dev_dbg(info->device, " * update DMA engine\n");
-+ atmel_lcdfb_update_dma(info, &info->var);
++ for (i = 1; i < USBA_NR_ENDPOINTS; i++)
++ if (dma_status & (1 << i))
++ usba_dma_irq(udc, &usba_ep[i]);
++ }
+
-+ /* ...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);
++ ep_status = USBA_BFEXT(EPT_INT, status);
++ if (ep_status) {
++ int i;
+
-+ /* Now, the LCDC core... */
++ for (i = 0; i < USBA_NR_ENDPOINTS; i++)
++ if (ep_status & (1 << i)) {
++ if (ep_is_control(&usba_ep[i]))
++ usba_control_irq(udc, &usba_ep[i]);
++ else
++ usba_ep_irq(udc, &usba_ep[i]);
++ }
++ }
+
-+ /* Set pixel clock */
-+ clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000;
++ if (status & USBA_BIT(END_OF_RESET)) {
++ struct usba_ep *ep0;
+
-+ value = clk_value_khz / PICOS2KHZ(info->var.pixclock);
++ usba_writel(udc, INT_CLR, USBA_BIT(END_OF_RESET));
++ reset_all_endpoints(udc);
+
-+ if (clk_value_khz % PICOS2KHZ(info->var.pixclock))
-+ value++;
++ if (status & USBA_BIT(HIGH_SPEED)) {
++ DBG(DBG_BUS, "High-speed bus reset detected\n");
++ udc->gadget.speed = USB_SPEED_HIGH;
++ } else {
++ DBG(DBG_BUS, "Full-speed bus reset detected\n");
++ udc->gadget.speed = USB_SPEED_FULL;
++ }
+
-+ value = (value / 2) - 1;
++ ep0 = &usba_ep[0];
++ ep0->desc = &usba_ep0_desc;
++ ep0->state = WAIT_FOR_SETUP;
++ usba_ep_writel(ep0, CFG,
++ (USBA_BF(EPT_SIZE, EP0_EPT_SIZE)
++ | USBA_BF(EPT_TYPE, USBA_EPT_TYPE_CONTROL)
++ | USBA_BF(BK_NUMBER, USBA_BK_NUMBER_ONE)));
++ usba_ep_writel(ep0, CTL_ENB,
++ USBA_BIT(EPT_ENABLE) | USBA_BIT(RX_SETUP));
++ usba_writel(udc, INT_ENB, (usba_readl(udc, INT_ENB)
++ | USBA_BF(EPT_INT, 1)
++ | USBA_BIT(DET_SUSPEND)
++ | USBA_BIT(END_OF_RESUME)));
++
++ if (!(usba_ep_readl(ep0, CFG) & USBA_BIT(EPT_MAPPED)))
++ dev_warn(&udc->pdev->dev,
++ "WARNING: EP0 configuration is invalid!\n");
++ }
+
-+ 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");
++ spin_unlock(&udc->lock);
+
-+ return 0;
++ return IRQ_HANDLED;
+}
+
-+static inline unsigned int chan_to_field(unsigned int chan, const struct fb_bitfield *bf)
++static irqreturn_t usba_vbus_irq(int irq, void *devid)
+{
-+ chan &= 0xffff;
-+ chan >>= 16 - bf->length;
-+ return chan << bf->offset;
++ struct usba_udc *udc = devid;
++ int vbus;
++
++ /* debounce */
++ udelay(10);
++
++ spin_lock(&udc->lock);
++ vbus = gpio_get_value(udc->vbus_pin);
++ if (vbus != udc->vbus_prev) {
++ if (vbus) {
++ usba_writel(udc, CTRL, USBA_BIT(EN_USBA));
++ usba_writel(udc, INT_ENB, USBA_BIT(END_OF_RESET));
++ } else {
++ udc->gadget.speed = USB_SPEED_UNKNOWN;
++ reset_all_endpoints(udc);
++ usba_writel(udc, CTRL, 0);
++ if (udc->driver)
++ udc->driver->disconnect(&udc->gadget);
++ }
++ udc->vbus_prev = vbus;
++ }
++ spin_unlock(&udc->lock);
++
++ return IRQ_HANDLED;
+}
+
-+/**
-+ * 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)
++int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+{
-+ struct atmel_lcdfb_info *sinfo = info->par;
-+ unsigned int val;
-+ u32 *pal;
-+ int ret = 1;
++ struct usba_udc *udc = &the_udc;
++ unsigned long flags;
++ int ret;
+
-+ if (info->var.grayscale)
-+ red = green = blue = (19595 * red + 38470 * green
-+ + 7471 * blue) >> 16;
++ if (!udc->pdev)
++ return -ENODEV;
+
-+ switch (info->fix.visual) {
-+ case FB_VISUAL_TRUECOLOR:
-+ if (regno < 16) {
-+ pal = info->pseudo_palette;
++ spin_lock_irqsave(&udc->lock, flags);
++ if (udc->driver) {
++ spin_unlock_irqrestore(&udc->lock, flags);
++ return -EBUSY;
++ }
+
-+ val = chan_to_field(red, &info->var.red);
-+ val |= chan_to_field(green, &info->var.green);
-+ val |= chan_to_field(blue, &info->var.blue);
++ udc->driver = driver;
++ udc->gadget.dev.driver = &driver->driver;
++ spin_unlock_irqrestore(&udc->lock, flags);
+
-+ pal[regno] = val;
-+ ret = 0;
-+ }
-+ break;
++ clk_enable(udc->pclk);
++ clk_enable(udc->hclk);
+
-+ case FB_VISUAL_PSEUDOCOLOR:
-+ if (regno < 256) {
-+ val = ((red >> 11) & 0x001f);
-+ val |= ((green >> 6) & 0x03e0);
-+ val |= ((blue >> 1) & 0x7c00);
++ ret = driver->bind(&udc->gadget);
++ if (ret) {
++ DBG(DBG_ERR, "Could not bind to driver %s: error %d\n",
++ driver->driver.name, ret);
++ goto err_driver_bind;
++ }
+
-+ /*
-+ * TODO: intensity bit. Maybe something like
-+ * ~(red[10] ^ green[10] ^ blue[10]) & 1
-+ */
++ DBG(DBG_GADGET, "registered driver `%s'\n", driver->driver.name);
+
-+ lcdc_writel(sinfo, ATMEL_LCDC_LUT(regno), val);
-+ ret = 0;
++ udc->vbus_prev = 0;
++ if (udc->vbus_pin != -1) {
++ ret = request_irq(gpio_to_irq(udc->vbus_pin),
++ usba_vbus_irq, 0, "atmel_usba_udc", udc);
++ if (ret) {
++ gpio_free(udc->vbus_pin);
++ udc->vbus_pin = -1;
++ dev_warn(&udc->pdev->dev,
++ "failed to request vbus irq; "
++ "assuming always on\n");
+ }
-+ 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);
++ /* If Vbus is present, enable the controller and wait for reset */
++ spin_lock_irqsave(&udc->lock, flags);
++ if (vbus_is_present(udc) && udc->vbus_prev == 0) {
++ usba_writel(udc, CTRL, USBA_BIT(EN_USBA));
++ usba_writel(udc, INT_ENB, USBA_BIT(END_OF_RESET));
++ }
++ spin_unlock_irqrestore(&udc->lock, flags);
+
+ 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,
-+};
++err_driver_bind:
++ udc->driver = NULL;
++ udc->gadget.dev.driver = NULL;
++ return ret;
++}
++EXPORT_SYMBOL(usb_gadget_register_driver);
+
-+static irqreturn_t atmel_lcdfb_interrupt(int irq, void *dev_id)
++int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+{
-+ struct fb_info *info = dev_id;
-+ struct atmel_lcdfb_info *sinfo = info->par;
-+ u32 status;
++ struct usba_udc *udc = &the_udc;
++ unsigned long flags;
+
-+ status = lcdc_readl(sinfo, ATMEL_LCDC_ISR);
-+ lcdc_writel(sinfo, ATMEL_LCDC_IDR, status);
-+ return IRQ_HANDLED;
-+}
++ if (!udc->pdev)
++ return -ENODEV;
++ if (driver != udc->driver)
++ return -EINVAL;
+
-+static int __init atmel_lcdfb_init_fbinfo(struct atmel_lcdfb_info *sinfo)
-+{
-+ struct fb_info *info = sinfo->info;
-+ int ret = 0;
++ if (udc->vbus_pin != -1)
++ free_irq(gpio_to_irq(udc->vbus_pin), udc);
+
-+ memset_io(info->screen_base, 0, info->fix.smem_len);
-+ info->var.activate |= FB_ACTIVATE_FORCE | FB_ACTIVATE_NOW;
++ spin_lock_irqsave(&udc->lock, flags);
++ udc->gadget.speed = USB_SPEED_UNKNOWN;
++ reset_all_endpoints(udc);
++ spin_unlock_irqrestore(&udc->lock, flags);
+
-+ 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);
++ /* This will also disable the DP pullup */
++ usba_writel(udc, CTRL, 0);
+
-+ /* Allocate colormap */
-+ ret = fb_alloc_cmap(&info->cmap, 256, 0);
-+ if (ret < 0)
-+ dev_err(info->device, "Alloc color map failed\n");
++ driver->unbind(&udc->gadget);
++ udc->gadget.dev.driver = NULL;
++ udc->driver = NULL;
+
-+ return ret;
-+}
++ clk_disable(udc->hclk);
++ clk_disable(udc->pclk);
+
-+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);
-+}
++ DBG(DBG_GADGET, "unregistered driver `%s'\n", driver->driver.name);
+
-+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);
++ return 0;
+}
++EXPORT_SYMBOL(usb_gadget_unregister_driver);
+
-+
-+static int __init atmel_lcdfb_probe(struct platform_device *pdev)
++static int __devinit usba_udc_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;
++ struct usba_platform_data *pdata = pdev->dev.platform_data;
++ struct resource *regs, *fifo;
++ struct clk *pclk, *hclk;
++ struct usba_udc *udc = &the_udc;
++ int irq, ret, i;
+
-+ dev_dbg(dev, "%s BEGIN\n", __func__);
++ regs = platform_get_resource(pdev, IORESOURCE_MEM, CTRL_IOMEM_ID);
++ fifo = platform_get_resource(pdev, IORESOURCE_MEM, FIFO_IOMEM_ID);
++ if (!regs || !fifo)
++ return -ENXIO;
+
-+ ret = -ENOMEM;
-+ info = framebuffer_alloc(sizeof(struct atmel_lcdfb_info), dev);
-+ if (!info) {
-+ dev_err(dev, "cannot allocate memory\n");
-+ goto out;
++ irq = platform_get_irq(pdev, 0);
++ if (irq < 0)
++ return irq;
++
++ pclk = clk_get(&pdev->dev, "pclk");
++ if (IS_ERR(pclk))
++ return PTR_ERR(pclk);
++ hclk = clk_get(&pdev->dev, "hclk");
++ if (IS_ERR(hclk)) {
++ ret = PTR_ERR(hclk);
++ goto err_get_hclk;
+ }
+
-+ sinfo = info->par;
++ udc->pdev = pdev;
++ udc->pclk = pclk;
++ udc->hclk = hclk;
++ udc->vbus_pin = -1;
+
-+ 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;
-+ }
++ ret = -ENOMEM;
++ udc->regs = ioremap(regs->start, regs->end - regs->start + 1);
++ if (!udc->regs) {
++ dev_err(&pdev->dev, "Unable to map I/O memory, aborting.\n");
++ goto err_map_regs;
+ }
-+ sinfo->lcdc_clk = clk_get(dev, "lcdc_clk");
-+ if (IS_ERR(sinfo->lcdc_clk)) {
-+ ret = PTR_ERR(sinfo->lcdc_clk);
-+ goto put_bus_clk;
++ dev_info(&pdev->dev, "MMIO registers at 0x%08lx mapped at %p\n",
++ (unsigned long)regs->start, udc->regs);
++ udc->fifo = ioremap(fifo->start, fifo->end - fifo->start + 1);
++ if (!udc->fifo) {
++ dev_err(&pdev->dev, "Unable to map FIFO, aborting.\n");
++ goto err_map_fifo;
+ }
-+ atmel_lcdfb_start_clock(sinfo);
++ dev_info(&pdev->dev, "FIFO at 0x%08lx mapped at %p\n",
++ (unsigned long)fifo->start, udc->fifo);
+
-+ 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;
-+ }
++ device_initialize(&udc->gadget.dev);
++ udc->gadget.dev.parent = &pdev->dev;
++ udc->gadget.dev.dma_mask = pdev->dev.dma_mask;
+
++ platform_set_drvdata(pdev, udc);
+
-+ 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;
-+ }
++ /* Make sure we start from a clean slate */
++ clk_enable(pclk);
++ usba_writel(udc, CTRL, 0);
++ clk_disable(pclk);
+
-+ 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;
-+ }
-+ }
++ INIT_LIST_HEAD(&usba_ep[0].ep.ep_list);
++ usba_ep[0].ep_regs = udc->regs + USBA_EPT_BASE(0);
++ usba_ep[0].dma_regs = udc->regs + USBA_DMA_BASE(0);
++ usba_ep[0].fifo = udc->fifo + USBA_FIFO_BASE(0);
++ for (i = 1; i < ARRAY_SIZE(usba_ep); i++) {
++ struct usba_ep *ep = &usba_ep[i];
+
-+ /* LCDC registers */
-+ info->fix.mmio_start = regs->start;
-+ info->fix.mmio_len = regs->end - regs->start + 1;
++ ep->ep_regs = udc->regs + USBA_EPT_BASE(i);
++ ep->dma_regs = udc->regs + USBA_DMA_BASE(i);
++ ep->fifo = udc->fifo + USBA_FIFO_BASE(i);
+
-+ if (!request_mem_region(info->fix.mmio_start,
-+ info->fix.mmio_len, pdev->name)) {
-+ ret = -EBUSY;
-+ goto free_fb;
++ list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
+ }
+
-+ 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;
++ ret = request_irq(irq, usba_udc_irq, IRQF_SAMPLE_RANDOM,
++ "atmel_usba_udc", udc);
++ if (ret) {
++ dev_err(&pdev->dev, "Cannot request irq %d (error %d)\n",
++ irq, ret);
++ goto err_request_irq;
+ }
++ udc->irq = irq;
+
-+ /* interrupt */
-+ ret = request_irq(sinfo->irq_base, atmel_lcdfb_interrupt, 0, pdev->name, info);
++ ret = device_add(&udc->gadget.dev);
+ if (ret) {
-+ dev_err(dev, "request_irq failed: %d\n", ret);
-+ goto unmap_mmio;
++ dev_dbg(&pdev->dev, "Could not add gadget: %d\n", ret);
++ goto err_device_add;
+ }
+
-+ ret = atmel_lcdfb_init_fbinfo(sinfo);
-+ if (ret < 0) {
-+ dev_err(dev, "init fbinfo failed: %d\n", ret);
-+ goto unregister_irqs;
-+ }
++ if (pdata && pdata->vbus_pin != GPIO_PIN_NONE)
++ if (!gpio_request(pdata->vbus_pin, "atmel_usba_udc"))
++ udc->vbus_pin = pdata->vbus_pin;
+
-+ /*
-+ * This makes sure that our colour bitfield
-+ * descriptors are correctly initialised.
-+ */
-+ atmel_lcdfb_check_var(&info->var, info);
++ usba_init_debugfs(udc);
++ for (i = 1; i < ARRAY_SIZE(usba_ep); i++)
++ usba_ep_init_debugfs(udc, &usba_ep[i]);
+
-+ ret = fb_set_var(info, &info->var);
-+ if (ret) {
-+ dev_warn(dev, "unable to set display parameters\n");
-+ goto free_cmap;
-+ }
++ return 0;
+
-+ dev_set_drvdata(dev, info);
++err_device_add:
++ free_irq(irq, udc);
++err_request_irq:
++ iounmap(udc->fifo);
++err_map_fifo:
++ iounmap(udc->regs);
++err_map_regs:
++ clk_put(hclk);
++err_get_hclk:
++ clk_put(pclk);
+
-+ /*
-+ * 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;
-+ }
++ platform_set_drvdata(pdev, NULL);
++
++ return ret;
++}
++
++static int __devexit usba_udc_remove(struct platform_device *pdev)
++{
++ struct usba_udc *udc;
++ int i;
++
++ udc = platform_get_drvdata(pdev);
++
++ for (i = 1; i < ARRAY_SIZE(usba_ep); i++)
++ usba_ep_cleanup_debugfs(&usba_ep[i]);
++ usba_cleanup_debugfs(udc);
+
-+ /* Power up the LCDC screen */
-+ if (sinfo->atmel_lcdfb_power_control)
-+ sinfo->atmel_lcdfb_power_control(1);
++ if (udc->vbus_pin != -1)
++ gpio_free(udc->vbus_pin);
+
-+ 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);
++ free_irq(udc->irq, udc);
++ iounmap(udc->fifo);
++ iounmap(udc->regs);
++ clk_put(udc->hclk);
++ clk_put(udc->pclk);
++
++ device_unregister(&udc->gadget.dev);
+
+ return 0;
++}
+
++static struct platform_driver udc_driver = {
++ .probe = usba_udc_probe,
++ .remove = __devexit_p(usba_udc_remove),
++ .driver = {
++ .name = "atmel_usba_udc",
++ },
++};
+
-+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 __init udc_init(void)
++{
++ return platform_driver_register(&udc_driver);
+}
++module_init(udc_init);
+
-+static int __exit atmel_lcdfb_remove(struct platform_device *pdev)
++static void __exit udc_exit(void)
+{
-+ struct device *dev = &pdev->dev;
-+ struct fb_info *info = dev_get_drvdata(dev);
-+ struct atmel_lcdfb_info *sinfo = info->par;
++ platform_driver_unregister(&udc_driver);
++}
++module_exit(udc_exit);
+
-+ if (!sinfo)
-+ return 0;
++MODULE_DESCRIPTION("Atmel USBA UDC driver");
++MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>");
++MODULE_LICENSE("GPL");
+diff -x .git -Nur linux-2.6.22.1/drivers/usb/gadget/atmel_usba_udc.h linux-avr32.git/drivers/usb/gadget/atmel_usba_udc.h
+--- linux-2.6.22.1/drivers/usb/gadget/atmel_usba_udc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-avr32.git/drivers/usb/gadget/atmel_usba_udc.h 2007-07-12 14:00:19.000000000 +0200
+@@ -0,0 +1,402 @@
++/*
++ * Driver for the Atmel USBA high speed USB device controller
++ *
++ * Copyright (C) 2005-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_USB_GADGET_USBA_UDC_H__
++#define __LINUX_USB_GADGET_USBA_UDC_H__
++
++/* USB register offsets */
++#define USBA_CTRL 0x0000
++#define USBA_FNUM 0x0004
++#define USBA_INT_ENB 0x0010
++#define USBA_INT_STA 0x0014
++#define USBA_INT_CLR 0x0018
++#define USBA_EPT_RST 0x001c
++#define USBA_TST_SOF_CNT 0x00d0
++#define USBA_TST_CNT_A 0x00d4
++#define USBA_TST_CNT_B 0x00d8
++#define USBA_TST_MODE_REG 0x00dc
++#define USBA_TST 0x00e0
++
++/* USB endpoint register offsets */
++#define USBA_EPT_CFG 0x0000
++#define USBA_EPT_CTL_ENB 0x0004
++#define USBA_EPT_CTL_DIS 0x0008
++#define USBA_EPT_CTL 0x000c
++#define USBA_EPT_SET_STA 0x0014
++#define USBA_EPT_CLR_STA 0x0018
++#define USBA_EPT_STA 0x001c
++
++/* USB DMA register offsets */
++#define USBA_DMA_NXT_DSC 0x0000
++#define USBA_DMA_ADDRESS 0x0004
++#define USBA_DMA_CONTROL 0x0008
++#define USBA_DMA_STATUS 0x000c
++
++/* Bitfields in CTRL */
++#define USBA_DEV_ADDR_OFFSET 0
++#define USBA_DEV_ADDR_SIZE 7
++#define USBA_FADDR_EN_OFFSET 7
++#define USBA_FADDR_EN_SIZE 1
++#define USBA_EN_USBA_OFFSET 8
++#define USBA_EN_USBA_SIZE 1
++#define USBA_DETACH_OFFSET 9
++#define USBA_DETACH_SIZE 1
++#define USBA_REMOTE_WAKE_UP_OFFSET 10
++#define USBA_REMOTE_WAKE_UP_SIZE 1
++
++/* Bitfields in FNUM */
++#define USBA_MICRO_FRAME_NUM_OFFSET 0
++#define USBA_MICRO_FRAME_NUM_SIZE 3
++#define USBA_FRAME_NUMBER_OFFSET 3
++#define USBA_FRAME_NUMBER_SIZE 11
++#define USBA_FRAME_NUM_ERROR_OFFSET 31
++#define USBA_FRAME_NUM_ERROR_SIZE 1
++
++/* Bitfields in INT_ENB/INT_STA/INT_CLR */
++#define USBA_HIGH_SPEED_OFFSET 0
++#define USBA_HIGH_SPEED_SIZE 1
++#define USBA_DET_SUSPEND_OFFSET 1
++#define USBA_DET_SUSPEND_SIZE 1
++#define USBA_MICRO_SOF_OFFSET 2
++#define USBA_MICRO_SOF_SIZE 1
++#define USBA_SOF_OFFSET 3
++#define USBA_SOF_SIZE 1
++#define USBA_END_OF_RESET_OFFSET 4
++#define USBA_END_OF_RESET_SIZE 1
++#define USBA_WAKE_UP_OFFSET 5
++#define USBA_WAKE_UP_SIZE 1
++#define USBA_END_OF_RESUME_OFFSET 6
++#define USBA_END_OF_RESUME_SIZE 1
++#define USBA_UPSTREAM_RESUME_OFFSET 7
++#define USBA_UPSTREAM_RESUME_SIZE 1
++#define USBA_EPT_INT_OFFSET 8
++#define USBA_EPT_INT_SIZE 16
++#define USBA_DMA_INT_OFFSET 24
++#define USBA_DMA_INT_SIZE 8
++
++/* Bitfields in EPT_RST */
++#define USBA_RST_OFFSET 0
++#define USBA_RST_SIZE 16
++
++/* Bitfields in TST_SOF_CNT */
++#define USBA_SOF_CNT_MAX_OFFSET 0
++#define USBA_SOF_CNT_MAX_SIZE 7
++#define USBA_SOF_CNT_LOAD_OFFSET 7
++#define USBA_SOF_CNT_LOAD_SIZE 1
++
++/* Bitfields in TST_CNT_A */
++#define USBA_CNT_A_MAX_OFFSET 0
++#define USBA_CNT_A_MAX_SIZE 7
++#define USBA_CNT_A_LOAD_OFFSET 7
++#define USBA_CNT_A_LOAD_SIZE 1
++
++/* Bitfields in TST_CNT_B */
++#define USBA_CNT_B_MAX_OFFSET 0
++#define USBA_CNT_B_MAX_SIZE 7
++#define USBA_CNT_B_LOAD_OFFSET 7
++#define USBA_CNT_B_LOAD_SIZE 1
++
++/* Bitfields in TST_MODE_REG */
++#define USBA_TST_MODE_OFFSET 0
++#define USBA_TST_MODE_SIZE 6
++
++/* Bitfields in USBA_TST */
++#define USBA_SPEED_CFG_OFFSET 0
++#define USBA_SPEED_CFG_SIZE 2
++#define USBA_TST_J_MODE_OFFSET 2
++#define USBA_TST_J_MODE_SIZE 1
++#define USBA_TST_K_MODE_OFFSET 3
++#define USBA_TST_K_MODE_SIZE 1
++#define USBA_TST_PKT_MODE_OFFSET 4
++#define USBA_TST_PKT_MODE_SIZE 1
++#define USBA_OPMODE2_OFFSET 5
++#define USBA_OPMODE2_SIZE 1
++
++/* Bitfields in EPT_CFG */
++#define USBA_EPT_SIZE_OFFSET 0
++#define USBA_EPT_SIZE_SIZE 3
++#define USBA_EPT_DIR_OFFSET 3
++#define USBA_EPT_DIR_SIZE 1
++#define USBA_EPT_TYPE_OFFSET 4
++#define USBA_EPT_TYPE_SIZE 2
++#define USBA_BK_NUMBER_OFFSET 6
++#define USBA_BK_NUMBER_SIZE 2
++#define USBA_NB_TRANS_OFFSET 8
++#define USBA_NB_TRANS_SIZE 2
++#define USBA_EPT_MAPPED_OFFSET 31
++#define USBA_EPT_MAPPED_SIZE 1
++
++/* Bitfields in EPT_CTL/EPT_CTL_ENB/EPT_CTL_DIS */
++#define USBA_EPT_ENABLE_OFFSET 0
++#define USBA_EPT_ENABLE_SIZE 1
++#define USBA_AUTO_VALID_OFFSET 1
++#define USBA_AUTO_VALID_SIZE 1
++#define USBA_INTDIS_DMA_OFFSET 3
++#define USBA_INTDIS_DMA_SIZE 1
++#define USBA_NYET_DIS_OFFSET 4
++#define USBA_NYET_DIS_SIZE 1
++#define USBA_DATAX_RX_OFFSET 6
++#define USBA_DATAX_RX_SIZE 1
++#define USBA_MDATA_RX_OFFSET 7
++#define USBA_MDATA_RX_SIZE 1
++/* Bits 8-15 and 31 enable interrupts for respective bits in EPT_STA */
++#define USBA_BUSY_BANK_IE_OFFSET 18
++#define USBA_BUSY_BANK_IE_SIZE 1
++
++/* Bitfields in EPT_SET_STA/EPT_CLR_STA/EPT_STA */
++#define USBA_FORCE_STALL_OFFSET 5
++#define USBA_FORCE_STALL_SIZE 1
++#define USBA_TOGGLE_SEQ_OFFSET 6
++#define USBA_TOGGLE_SEQ_SIZE 2
++#define USBA_ERR_OVFLW_OFFSET 8
++#define USBA_ERR_OVFLW_SIZE 1
++#define USBA_RX_BK_RDY_OFFSET 9
++#define USBA_RX_BK_RDY_SIZE 1
++#define USBA_KILL_BANK_OFFSET 9
++#define USBA_KILL_BANK_SIZE 1
++#define USBA_TX_COMPLETE_OFFSET 10
++#define USBA_TX_COMPLETE_SIZE 1
++#define USBA_TX_PK_RDY_OFFSET 11
++#define USBA_TX_PK_RDY_SIZE 1
++#define USBA_ISO_ERR_TRANS_OFFSET 11
++#define USBA_ISO_ERR_TRANS_SIZE 1
++#define USBA_RX_SETUP_OFFSET 12
++#define USBA_RX_SETUP_SIZE 1
++#define USBA_ISO_ERR_FLOW_OFFSET 12
++#define USBA_ISO_ERR_FLOW_SIZE 1
++#define USBA_STALL_SENT_OFFSET 13
++#define USBA_STALL_SENT_SIZE 1
++#define USBA_ISO_ERR_CRC_OFFSET 13
++#define USBA_ISO_ERR_CRC_SIZE 1
++#define USBA_ISO_ERR_NBTRANS_OFFSET 13
++#define USBA_ISO_ERR_NBTRANS_SIZE 1
++#define USBA_NAK_IN_OFFSET 14
++#define USBA_NAK_IN_SIZE 1
++#define USBA_ISO_ERR_FLUSH_OFFSET 14
++#define USBA_ISO_ERR_FLUSH_SIZE 1
++#define USBA_NAK_OUT_OFFSET 15
++#define USBA_NAK_OUT_SIZE 1
++#define USBA_CURRENT_BANK_OFFSET 16
++#define USBA_CURRENT_BANK_SIZE 2
++#define USBA_BUSY_BANKS_OFFSET 18
++#define USBA_BUSY_BANKS_SIZE 2
++#define USBA_BYTE_COUNT_OFFSET 20
++#define USBA_BYTE_COUNT_SIZE 11
++#define USBA_SHORT_PACKET_OFFSET 31
++#define USBA_SHORT_PACKET_SIZE 1
++
++/* Bitfields in DMA_CONTROL */
++#define USBA_DMA_CH_EN_OFFSET 0
++#define USBA_DMA_CH_EN_SIZE 1
++#define USBA_DMA_LINK_OFFSET 1
++#define USBA_DMA_LINK_SIZE 1
++#define USBA_DMA_END_TR_EN_OFFSET 2
++#define USBA_DMA_END_TR_EN_SIZE 1
++#define USBA_DMA_END_BUF_EN_OFFSET 3
++#define USBA_DMA_END_BUF_EN_SIZE 1
++#define USBA_DMA_END_TR_IE_OFFSET 4
++#define USBA_DMA_END_TR_IE_SIZE 1
++#define USBA_DMA_END_BUF_IE_OFFSET 5
++#define USBA_DMA_END_BUF_IE_SIZE 1
++#define USBA_DMA_DESC_LOAD_IE_OFFSET 6
++#define USBA_DMA_DESC_LOAD_IE_SIZE 1
++#define USBA_DMA_BURST_LOCK_OFFSET 7
++#define USBA_DMA_BURST_LOCK_SIZE 1
++#define USBA_DMA_BUF_LEN_OFFSET 16
++#define USBA_DMA_BUF_LEN_SIZE 16
++
++/* Bitfields in DMA_STATUS */
++#define USBA_DMA_CH_ACTIVE_OFFSET 1
++#define USBA_DMA_CH_ACTIVE_SIZE 1
++#define USBA_DMA_END_TR_ST_OFFSET 4
++#define USBA_DMA_END_TR_ST_SIZE 1
++#define USBA_DMA_END_BUF_ST_OFFSET 5
++#define USBA_DMA_END_BUF_ST_SIZE 1
++#define USBA_DMA_DESC_LOAD_ST_OFFSET 6
++#define USBA_DMA_DESC_LOAD_ST_SIZE 1
++
++/* Constants for SPEED_CFG */
++#define USBA_SPEED_CFG_NORMAL 0
++#define USBA_SPEED_CFG_FORCE_HIGH 2
++#define USBA_SPEED_CFG_FORCE_FULL 3
++
++/* Constants for EPT_SIZE */
++#define USBA_EPT_SIZE_8 0
++#define USBA_EPT_SIZE_16 1
++#define USBA_EPT_SIZE_32 2
++#define USBA_EPT_SIZE_64 3
++#define USBA_EPT_SIZE_128 4
++#define USBA_EPT_SIZE_256 5
++#define USBA_EPT_SIZE_512 6
++#define USBA_EPT_SIZE_1024 7
++
++/* Constants for EPT_TYPE */
++#define USBA_EPT_TYPE_CONTROL 0
++#define USBA_EPT_TYPE_ISO 1
++#define USBA_EPT_TYPE_BULK 2
++#define USBA_EPT_TYPE_INT 3
++
++/* Constants for BK_NUMBER */
++#define USBA_BK_NUMBER_ZERO 0
++#define USBA_BK_NUMBER_ONE 1
++#define USBA_BK_NUMBER_DOUBLE 2
++#define USBA_BK_NUMBER_TRIPLE 3
+
-+ 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);
++/* Bit manipulation macros */
++#define USBA_BIT(name) \
++ (1 << USBA_##name##_OFFSET)
++#define USBA_BF(name, value) \
++ (((value) & ((1 << USBA_##name##_SIZE) - 1)) \
++ << USBA_##name##_OFFSET)
++#define USBA_BFEXT(name, value) \
++ (((value) >> USBA_##name##_OFFSET) \
++ & ((1 << USBA_##name##_SIZE) - 1))
++#define USBA_BFINS(name, value, old) \
++ (((old) & ~(((1 << USBA_##name##_SIZE) - 1) \
++ << USBA_##name##_OFFSET)) \
++ | USBA_BF(name, value))
++
++/* Register access macros */
++#define usba_readl(udc, reg) \
++ __raw_readl((udc)->regs + USBA_##reg)
++#define usba_writel(udc, reg, value) \
++ __raw_writel((value), (udc)->regs + USBA_##reg)
++#define usba_ep_readl(ep, reg) \
++ __raw_readl((ep)->ep_regs + USBA_EPT_##reg)
++#define usba_ep_writel(ep, reg, value) \
++ __raw_writel((value), (ep)->ep_regs + USBA_EPT_##reg)
++#define usba_dma_readl(ep, reg) \
++ __raw_readl((ep)->dma_regs + USBA_DMA_##reg)
++#define usba_dma_writel(ep, reg, value) \
++ __raw_writel((value), (ep)->dma_regs + USBA_DMA_##reg)
++
++/* Calculate base address for a given endpoint or DMA controller */
++#define USBA_EPT_BASE(x) (0x100 + (x) * 0x20)
++#define USBA_DMA_BASE(x) (0x300 + (x) * 0x10)
++#define USBA_FIFO_BASE(x) ((x) << 16)
++
++/* Synth parameters */
++#define USBA_NR_ENDPOINTS 7
++
++#define EP0_FIFO_SIZE 64
++#define EP0_EPT_SIZE USBA_EPT_SIZE_64
++#define EP0_NR_BANKS 1
++#define BULK_FIFO_SIZE 512
++#define BULK_EPT_SIZE USBA_EPT_SIZE_512
++#define BULK_NR_BANKS 2
++#define ISO_FIFO_SIZE 1024
++#define ISO_EPT_SIZE USBA_EPT_SIZE_1024
++#define ISO_NR_BANKS 3
++#define INT_FIFO_SIZE 64
++#define INT_EPT_SIZE USBA_EPT_SIZE_64
++#define INT_NR_BANKS 3
++
++enum usba_ctrl_state {
++ WAIT_FOR_SETUP,
++ DATA_STAGE_IN,
++ DATA_STAGE_OUT,
++ STATUS_STAGE_IN,
++ STATUS_STAGE_OUT,
++ STATUS_STAGE_ADDR,
++ STATUS_STAGE_TEST,
++};
++/*
++ EP_STATE_IDLE,
++ EP_STATE_SETUP,
++ EP_STATE_IN_DATA,
++ EP_STATE_OUT_DATA,
++ EP_STATE_SET_ADDR_STATUS,
++ EP_STATE_RX_STATUS,
++ EP_STATE_TX_STATUS,
++ EP_STATE_HALT,
++*/
++
++struct usba_dma_desc {
++ dma_addr_t next;
++ dma_addr_t addr;
++ u32 ctrl;
++};
++
++struct usba_ep {
++ int state;
++ void __iomem *ep_regs;
++ void __iomem *dma_regs;
++ void __iomem *fifo;
++ struct usb_ep ep;
++ struct usba_udc *udc;
++
++ struct list_head queue;
++ const struct usb_endpoint_descriptor *desc;
++
++ u16 fifo_size;
++ u8 nr_banks;
++ u8 index;
++ unsigned int can_dma:1;
++ unsigned int can_isoc:1;
++ unsigned int is_isoc:1;
++ unsigned int is_in:1;
++
++#ifdef CONFIG_DEBUG_FS
++ u32 last_dma_status;
++ struct dentry *debugfs_dir;
++ struct dentry *debugfs_queue;
++ struct dentry *debugfs_dma_status;
++ struct dentry *debugfs_state;
++#endif
++};
++
++struct usba_request {
++ struct usb_request req;
++ struct list_head queue;
++
++ u32 ctrl;
++
++ unsigned int submitted:1;
++ unsigned int last_transaction:1;
++ unsigned int using_dma:1;
++ unsigned int mapped:1;
++};
++
++struct usba_udc {
++ /* Protect hw registers from concurrent modifications */
++ spinlock_t lock;
++
++ void __iomem *regs;
++ void __iomem *fifo;
++
++ struct usb_gadget gadget;
++ struct usb_gadget_driver *driver;
++ struct platform_device *pdev;
++ int irq;
++ int vbus_pin;
++ struct clk *pclk;
++ struct clk *hclk;
++
++ int test_mode;
++ int vbus_prev;
++
++#ifdef CONFIG_DEBUG_FS
++ struct dentry *debugfs_root;
++ struct dentry *debugfs_regs;
++#endif
++};
++
++#define to_usba_ep(x) container_of((x), struct usba_ep, ep)
++#define to_usba_req(x) container_of((x), struct usba_request, req)
++#define to_usba_udc(x) container_of((x), struct usba_udc, gadget)
++
++#define ep_index(ep) ((ep)->index)
++#define ep_can_dma(ep) ((ep)->can_dma)
++#define ep_is_in(ep) ((ep)->is_in)
++#define ep_is_isochronous(ep) ((ep)->is_isoc)
++#define ep_is_control(ep) (ep_index(ep) == 0)
++#define ep_name(ep) ((ep)->ep.name)
++#define ep_is_idle(ep) ((ep)->state == EP_STATE_IDLE)
++
++#endif /* __LINUX_USB_GADGET_USBA_UDC_H */
+diff -x .git -Nur linux-2.6.22.1/drivers/usb/gadget/ether.c linux-avr32.git/drivers/usb/gadget/ether.c
+--- linux-2.6.22.1/drivers/usb/gadget/ether.c 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/drivers/usb/gadget/ether.c 2007-07-12 14:00:19.000000000 +0200
+@@ -277,7 +277,7 @@
+ #define DEV_CONFIG_CDC
+ #endif
+
+-#ifdef CONFIG_USB_GADGET_HUSB2DEV
++#ifdef CONFIG_USB_GADGET_ATMEL_USBA
+ #define DEV_CONFIG_CDC
+ #endif
+
+diff -x .git -Nur linux-2.6.22.1/drivers/usb/gadget/gadget_chips.h linux-avr32.git/drivers/usb/gadget/gadget_chips.h
+--- linux-2.6.22.1/drivers/usb/gadget/gadget_chips.h 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/drivers/usb/gadget/gadget_chips.h 2007-07-12 14:00:19.000000000 +0200
+@@ -75,10 +75,10 @@
+ #define gadget_is_pxa27x(g) 0
+ #endif
+
+-#ifdef CONFIG_USB_GADGET_HUSB2DEV
+-#define gadget_is_husb2dev(g) !strcmp("husb2_udc", (g)->name)
++#ifdef CONFIG_USB_GADGET_ATMEL_USBA
++#define gadget_is_atmel_usba(g) !strcmp("atmel_usba_udc", (g)->name)
+ #else
+-#define gadget_is_husb2dev(g) 0
++#define gadget_is_atmel_usba(g) 0
+ #endif
+
+ #ifdef CONFIG_USB_GADGET_S3C2410
+@@ -181,7 +181,7 @@
+ return 0x16;
+ else if (gadget_is_mpc8272(gadget))
+ return 0x17;
+- else if (gadget_is_husb2dev(gadget))
++ else if (gadget_is_atmel_usba(gadget))
+ return 0x18;
+ else if (gadget_is_fsl_usb2(gadget))
+ return 0x19;
+diff -x .git -Nur linux-2.6.22.1/drivers/usb/gadget/inode.c linux-avr32.git/drivers/usb/gadget/inode.c
+--- linux-2.6.22.1/drivers/usb/gadget/inode.c 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/drivers/usb/gadget/inode.c 2007-07-12 14:00:19.000000000 +0200
+@@ -37,7 +37,7 @@
+ #include <linux/device.h>
+ #include <linux/moduleparam.h>
+
+-#include <linux/usb_gadgetfs.h>
++#include <linux/usb/gadgetfs.h>
+ #include <linux/usb_gadget.h>
+
+
+diff -x .git -Nur linux-2.6.22.1/drivers/usb/gadget/Kconfig linux-avr32.git/drivers/usb/gadget/Kconfig
+--- linux-2.6.22.1/drivers/usb/gadget/Kconfig 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/drivers/usb/gadget/Kconfig 2007-07-12 14:00:19.000000000 +0200
+@@ -175,6 +175,19 @@
+ default USB_GADGET
+ select USB_GADGET_SELECTED
+
++config USB_GADGET_ATMEL_USBA
++ boolean "Atmel USBA"
++ select USB_GADGET_DUALSPEED
++ depends on AVR32
++ help
++ USBA is the integrated high-speed USB Device controller on
++ the AT32AP700x processors from Atmel.
++
++config USB_ATMEL_USBA
++ tristate
++ depends on USB_GADGET_ATMEL_USBA
++ default USB_GADGET
++ select USB_GADGET_SELECTED
+
+ config USB_GADGET_OMAP
+ boolean "OMAP USB Device Controller"
+diff -x .git -Nur linux-2.6.22.1/drivers/usb/gadget/Makefile linux-avr32.git/drivers/usb/gadget/Makefile
+--- linux-2.6.22.1/drivers/usb/gadget/Makefile 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/drivers/usb/gadget/Makefile 2007-07-12 14:00:19.000000000 +0200
+@@ -8,6 +8,7 @@
+ obj-$(CONFIG_USB_OMAP) += omap_udc.o
+ obj-$(CONFIG_USB_LH7A40X) += lh7a40x_udc.o
+ obj-$(CONFIG_USB_AT91) += at91_udc.o
++obj-$(CONFIG_USB_ATMEL_USBA) += atmel_usba_udc.o
+ obj-$(CONFIG_USB_FSL_USB2) += fsl_usb2_udc.o
+
+ #
+diff -x .git -Nur linux-2.6.22.1/drivers/video/atmel_lcdfb.c linux-avr32.git/drivers/video/atmel_lcdfb.c
+--- linux-2.6.22.1/drivers/video/atmel_lcdfb.c 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/drivers/video/atmel_lcdfb.c 2007-07-12 14:00:20.000000000 +0200
+@@ -37,7 +37,9 @@
+ #endif
+
+ #if defined(CONFIG_ARCH_AT91)
+-#define ATMEL_LCDFB_FBINFO_DEFAULT FBINFO_DEFAULT
++#define ATMEL_LCDFB_FBINFO_DEFAULT (FBINFO_DEFAULT \
++ | FBINFO_PARTIAL_PAN_OK \
++ | FBINFO_HWACCEL_YPAN)
+
+ static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
+ struct fb_var_screeninfo *var)
+@@ -74,11 +76,34 @@
+ .type = FB_TYPE_PACKED_PIXELS,
+ .visual = FB_VISUAL_TRUECOLOR,
+ .xpanstep = 0,
+- .ypanstep = 0,
++ .ypanstep = 1,
+ .ywrapstep = 0,
+ .accel = FB_ACCEL_NONE,
+ };
+
++static unsigned long compute_hozval(unsigned long xres, unsigned long lcdcon2)
++{
++ unsigned long value;
++
++ if (!(cpu_is_at91sam9261() || cpu_is_at32ap7000()))
++ return xres;
++
++ value = xres;
++ if ((lcdcon2 & ATMEL_LCDC_DISTYPE) != ATMEL_LCDC_DISTYPE_TFT) {
++ /* STN display */
++ if ((lcdcon2 & ATMEL_LCDC_DISTYPE) == ATMEL_LCDC_DISTYPE_STNCOLOR) {
++ value *= 3;
++ }
++ if ( (lcdcon2 & ATMEL_LCDC_IFWIDTH) == ATMEL_LCDC_IFWIDTH_4
++ || ( (lcdcon2 & ATMEL_LCDC_IFWIDTH) == ATMEL_LCDC_IFWIDTH_8
++ && (lcdcon2 & ATMEL_LCDC_SCANMOD) == ATMEL_LCDC_SCANMOD_DUAL ))
++ value = DIV_ROUND_UP(value, 4);
++ else
++ value = DIV_ROUND_UP(value, 8);
++ }
++
++ return value;
++}
+
+ static void atmel_lcdfb_update_dma(struct fb_info *info,
+ struct fb_var_screeninfo *var)
+@@ -181,6 +206,7 @@
+ var->xoffset = var->yoffset = 0;
+
+ switch (var->bits_per_pixel) {
++ case 1:
+ case 2:
+ case 4:
+ case 8:
+@@ -195,8 +221,11 @@
+ var->blue.offset = 10;
+ var->red.length = var->green.length = var->blue.length = 5;
+ break;
+- case 24:
+ case 32:
++ var->transp.offset = 24;
++ var->transp.length = 8;
++ /* fall through */
++ case 24:
+ var->red.offset = 0;
+ var->green.offset = 8;
+ var->blue.offset = 16;
+@@ -228,8 +257,10 @@
+ static int atmel_lcdfb_set_par(struct fb_info *info)
+ {
+ struct atmel_lcdfb_info *sinfo = info->par;
++ unsigned long hozval_linesz;
+ unsigned long value;
+ unsigned long clk_value_khz;
++ unsigned long bits_per_line;
+
+ dev_dbg(info->device, "%s:\n", __func__);
+ dev_dbg(info->device, " * resolution: %ux%u (%ux%u virtual)\n",
+@@ -241,12 +272,15 @@
+
+ lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0);
+
+- if (info->var.bits_per_pixel <= 8)
++ if (info->var.bits_per_pixel == 1)
++ info->fix.visual = FB_VISUAL_MONO01;
++ else 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);
++ bits_per_line = info->var.xres_virtual * info->var.bits_per_pixel;
++ info->fix.line_length = DIV_ROUND_UP(bits_per_line, 8);
+
+ /* Re-initialize the DMA engine... */
+ dev_dbg(info->device, " * update DMA engine\n");
+@@ -262,18 +296,21 @@
+ /* 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 = DIV_ROUND_UP(clk_value_khz, PICOS2KHZ(info->var.pixclock));
+
+ value = (value / 2) - 1;
++ dev_dbg(info->device, " * programming CLKVAL = 0x%08lx\n", value);
+
+ if (value <= 0) {
+ dev_notice(info->device, "Bypassing pixel clock divider\n");
+ lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1, ATMEL_LCDC_BYPASS);
+- } else
+ } else {
-+ atmel_lcdfb_free_video_memory(sinfo);
+ lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1, value << ATMEL_LCDC_CLKVAL_OFFSET);
++ info->var.pixclock = KHZ2PICOS(clk_value_khz / (2 * (value + 1)));
++ dev_dbg(info->device, " updated pixclk: %lu KHz\n",
++ PICOS2KHZ(info->var.pixclock));
+ }
+
-+ 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);
-+}
+
+ /* Initialize control register 2 */
+ value = sinfo->default_lcdcon2;
+@@ -311,9 +348,14 @@
+ dev_dbg(info->device, " * LCDTIM2 = %08lx\n", value);
+ lcdc_writel(sinfo, ATMEL_LCDC_TIM2, value);
+
++ /* Horizontal value (aka line size) */
++ hozval_linesz = compute_hozval(info->var.xres,
++ lcdc_readl(sinfo, ATMEL_LCDC_LCDCON2));
+
-+static void __exit atmel_lcdfb_exit(void)
-+{
-+ platform_driver_unregister(&atmel_lcdfb_driver);
-+}
+ /* Display size */
+- value = (info->var.xres - 1) << ATMEL_LCDC_HOZVAL_OFFSET;
++ value = (hozval_linesz - 1) << ATMEL_LCDC_HOZVAL_OFFSET;
+ value |= info->var.yres - 1;
++ dev_dbg(info->device, " * LCDFRMCFG = %08lx\n", value);
+ lcdc_writel(sinfo, ATMEL_LCDC_LCDFRMCFG, value);
+
+ /* FIFO Threshold: Use formula from data sheet */
+@@ -421,6 +463,15 @@
+ ret = 0;
+ }
+ break;
+
-+module_init(atmel_lcdfb_init);
-+module_exit(atmel_lcdfb_exit);
++ case FB_VISUAL_MONO01:
++ if (regno < 2) {
++ val = (regno == 0) ? 0x00 : 0x1F;
++ lcdc_writel(sinfo, ATMEL_LCDC_LUT(regno), val);
++ ret = 0;
++ }
++ break;
+
-+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
+ }
+
+ return ret;
+diff -x .git -Nur linux-2.6.22.1/drivers/video/backlight/Kconfig linux-avr32.git/drivers/video/backlight/Kconfig
+--- linux-2.6.22.1/drivers/video/backlight/Kconfig 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/drivers/video/backlight/Kconfig 2007-07-12 14:00:20.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.
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
+diff -x .git -Nur linux-2.6.22.1/drivers/video/backlight/ltv350qv.c linux-avr32.git/drivers/video/backlight/ltv350qv.c
+--- linux-2.6.22.1/drivers/video/backlight/ltv350qv.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-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
+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
+diff -x .git -Nur linux-2.6.22.1/drivers/video/backlight/ltv350qv.h linux-avr32.git/drivers/video/backlight/ltv350qv.h
+--- linux-2.6.22.1/drivers/video/backlight/ltv350qv.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-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
+#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
+diff -x .git -Nur linux-2.6.22.1/drivers/video/backlight/Makefile linux-avr32.git/drivers/video/backlight/Makefile
+--- linux-2.6.22.1/drivers/video/backlight/Makefile 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/drivers/video/backlight/Makefile 2007-07-12 14:00:20.000000000 +0200
@@ -1,6 +1,8 @@
# Backlight & LCD drivers
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"
+diff -x .git -Nur linux-2.6.22.1/drivers/video/Kconfig linux-avr32.git/drivers/video/Kconfig
+--- linux-2.6.22.1/drivers/video/Kconfig 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/drivers/video/Kconfig 2007-07-12 14:00:20.000000000 +0200
+@@ -849,6 +849,16 @@
+ 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_ATMEL_STN
++ bool "Use a STN display with AT91/AT32 LCD Controller"
+ depends on FB_ATMEL && ARCH_AT91SAM9261
++ default n
+ 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.
++ Say Y if you want to connect a STN LCD display to the AT91/AT32 LCD
++ Controller. Say N if you want to connect a TFT.
++
++ If unsure, say N.
+
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
+diff -x .git -Nur linux-2.6.22.1/include/asm-arm/arch-at91/board.h linux-avr32.git/include/asm-arm/arch-at91/board.h
+--- linux-2.6.22.1/include/asm-arm/arch-at91/board.h 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/include/asm-arm/arch-at91/board.h 2007-07-12 14:00:26.000000000 +0200
+@@ -64,6 +64,7 @@
+
+ /* Ethernet (EMAC & MACB) */
+ struct at91_eth_data {
++ u32 phy_mask;
+ u8 phy_irq_pin; /* PHY IRQ */
+ u8 is_rmii; /* using RMII interface? */
+ };
+diff -x .git -Nur linux-2.6.22.1/include/asm-avr32/arch-at32ap/board.h linux-avr32.git/include/asm-avr32/arch-at32ap/board.h
+--- linux-2.6.22.1/include/asm-avr32/arch-at32ap/board.h 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/include/asm-avr32/arch-at32ap/board.h 2007-07-12 14:00:26.000000000 +0200
@@ -6,6 +6,8 @@
#include <linux/types.h>
/* Add basic devices: system manager, interrupt controller, portmuxes, etc. */
void at32_add_system_devices(void);
-@@ -30,11 +32,22 @@
+@@ -21,6 +23,7 @@
+ struct platform_device *at32_add_device_usart(unsigned int id);
+
+ struct eth_platform_data {
++ u32 phy_mask;
+ u8 is_rmii;
+ };
+ struct platform_device *
+@@ -30,9 +33,41 @@
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);
++};
++struct platform_device *
+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 usba_platform_data {
++ int vbus_pin;
++};
+struct platform_device *
-+at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data,
-+ unsigned long fbmem_start, unsigned long fbmem_len);
++at32_add_device_usba(unsigned int id, struct usba_platform_data *data);
+
+ 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>
++/* depending on what's hooked up, not all SSC pins will be used */
++#define ATMEL_SSC_TK 0x01
++#define ATMEL_SSC_TF 0x02
++#define ATMEL_SSC_TD 0x04
++#define ATMEL_SSC_TX (ATMEL_SSC_TK | ATMEL_SSC_TF | ATMEL_SSC_TD)
+
-+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
++#define ATMEL_SSC_RK 0x10
++#define ATMEL_SSC_RF 0x20
++#define ATMEL_SSC_RD 0x40
++#define ATMEL_SSC_RX (ATMEL_SSC_RK | ATMEL_SSC_RF | ATMEL_SSC_RD)
+
-+/* Bit manipulation macros */
-+#define TIMER_BIT(name) (1 << TIMER_##name)
-+#define TIMER_BF(name,value) ((value) << TIMER_##name)
++struct platform_device *
++at32_add_device_ssc(unsigned int id, unsigned int flags);
+
-+/* 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
+ #endif /* __ASM_ARCH_BOARD_H */
+diff -x .git -Nur linux-2.6.22.1/include/asm-avr32/arch-at32ap/portmux.h linux-avr32.git/include/asm-avr32/arch-at32ap/portmux.h
+--- linux-2.6.22.1/include/asm-avr32/arch-at32ap/portmux.h 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/include/asm-avr32/arch-at32ap/portmux.h 2007-07-12 14:00:26.000000000 +0200
+@@ -25,4 +25,16 @@
+ void at32_select_gpio(unsigned int pin, unsigned long flags);
+ void at32_reserve_pin(unsigned int pin);
+
++#ifdef CONFIG_GPIO_DEV
++
++/* Gang allocators and accessors; used by the GPIO /dev driver */
++int at32_gpio_port_is_valid(unsigned int port);
++int at32_select_gpio_pins(unsigned int port, u32 pins, u32 oe_mask);
++void at32_deselect_pins(unsigned int port, u32 pins);
++
++u32 at32_gpio_get_value_multiple(unsigned int port, u32 pins);
++void at32_gpio_set_value_multiple(unsigned int port, u32 value, u32 mask);
++
++#endif /* CONFIG_GPIO_DEV */
++
+ #endif /* __ASM_ARCH_PORTMUX_H__ */
+diff -x .git -Nur linux-2.6.22.1/include/asm-avr32/arch-at32ap/sm.h linux-avr32.git/include/asm-avr32/arch-at32ap/sm.h
+--- linux-2.6.22.1/include/asm-avr32/arch-at32ap/sm.h 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/include/asm-avr32/arch-at32ap/sm.h 1970-01-01 01:00:00.000000000 +0100
+@@ -1,27 +0,0 @@
+-/*
+- * AT32 System Manager interface.
+- *
+- * Copyright (C) 2006 Atmel Corporation
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-#ifndef __ASM_AVR32_AT32_SM_H__
+-#define __ASM_AVR32_AT32_SM_H__
+-
+-struct irq_chip;
+-struct platform_device;
+-
+-struct at32_sm {
+- spinlock_t lock;
+- void __iomem *regs;
+- struct irq_chip *eim_chip;
+- unsigned int eim_first_irq;
+- struct platform_device *pdev;
+-};
+-
+-extern struct platform_device at32_sm_device;
+-extern struct at32_sm system_manager;
+-
+-#endif /* __ASM_AVR32_AT32_SM_H__ */
+diff -x .git -Nur linux-2.6.22.1/include/asm-avr32/dma-controller.h linux-avr32.git/include/asm-avr32/dma-controller.h
+--- linux-2.6.22.1/include/asm-avr32/dma-controller.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-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
+ 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)
++static inline int
++dma_prepare_request_cyclic(struct dma_controller *dmac,
++ struct dma_request_cyclic *req)
+{
-+ return 0;
++ return dmac->prepare_request_cyclic(dmac, req);
+}
-+static inline int unregister_page_fault_notifier(struct notifier_block *nb)
++
++static inline int
++dma_prepare_request_memcpy(struct dma_controller *dmac,
++ struct dma_request_memcpy *req)
+{
-+ return 0;
++ return dmac->prepare_request_memcpy(dmac, req);
+}
+
- #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>
++static inline int
++dma_start_request(struct dma_controller *dmac,
++ unsigned int channel)
++{
++ return dmac->start_request(dmac, channel);
++}
+
- 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
++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 -x .git -Nur linux-2.6.22.1/include/asm-avr32/unaligned.h linux-avr32.git/include/asm-avr32/unaligned.h
+--- linux-2.6.22.1/include/asm-avr32/unaligned.h 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/include/asm-avr32/unaligned.h 2007-07-12 14:00:26.000000000 +0200
+@@ -7,19 +7,10 @@
* words, but halfwords must be halfword-aligned, and doublewords must
* be word-aligned.
-- *
+ *
- * TODO: Make all this CPU-specific and optimize.
++ * However, swapped word loads must be word-aligned so we can't
++ * optimize word loads in general.
*/
-#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) \
+-
+-#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
++#include <asm-generic/unaligned.h>
#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
+diff -x .git -Nur linux-2.6.22.1/include/linux/leds.h linux-avr32.git/include/linux/leds.h
+--- linux-2.6.22.1/include/linux/leds.h 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/include/linux/leds.h 2007-07-12 14:00:30.000000000 +0200
+@@ -110,4 +110,18 @@
+ #define ledtrig_ide_activity() do {} while(0)
+ #endif
-+#include <asm/types.h>
++/* For the leds-gpio driver */
++struct gpio_led {
++ const char *name;
++ char *default_trigger;
++ unsigned gpio;
++ u8 active_low;
++};
+
- /*
- * 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 gpio_led_platform_data {
++ int num_leds;
++ struct gpio_led *leds;
++};
+
- 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>
+ #endif /* __LINUX_LEDS_H_INCLUDED */
+diff -x .git -Nur linux-2.6.22.1/include/linux/usb/gadgetfs.h linux-avr32.git/include/linux/usb/gadgetfs.h
+--- linux-2.6.22.1/include/linux/usb/gadgetfs.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-avr32.git/include/linux/usb/gadgetfs.h 2007-07-12 14:00:31.000000000 +0200
+@@ -0,0 +1,81 @@
++#ifndef __LINUX_USB_GADGETFS_H
++#define __LINUX_USB_GADGETFS_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>
++#include <asm/ioctl.h>
++
++#include <linux/usb/ch9.h>
++
++/*
++ * Filesystem based user-mode API to USB Gadget controller hardware
++ *
++ * Other than ep0 operations, most things are done by read() and write()
++ * on endpoint files found in one directory. They are configured by
++ * writing descriptors, and then may be used for normal stream style
++ * i/o requests. When ep0 is configured, the device can enumerate;
++ * when it's closed, the device disconnects from usb. Operations on
++ * ep0 require ioctl() operations.
++ *
++ * Configuration and device descriptors get written to /dev/gadget/$CHIP,
++ * which may then be used to read usb_gadgetfs_event structs. The driver
++ * may activate endpoints as it handles SET_CONFIGURATION setup events,
++ * or earlier; writing endpoint descriptors to /dev/gadget/$ENDPOINT
++ * then performing data transfers by reading or writing.
++ */
++
++/*
++ * Events are delivered on the ep0 file descriptor, when the user mode driver
++ * reads from this file descriptor after writing the descriptors. Don't
++ * stop polling this descriptor.
++ */
++
++enum usb_gadgetfs_event_type {
++ GADGETFS_NOP = 0,
++
++ GADGETFS_CONNECT,
++ GADGETFS_DISCONNECT,
++ GADGETFS_SETUP,
++ GADGETFS_SUSPEND,
++ // and likely more !
++};
++
++/* NOTE: this structure must stay the same size and layout on
++ * both 32-bit and 64-bit kernels.
++ */
++struct usb_gadgetfs_event {
++ union {
++ // NOP, DISCONNECT, SUSPEND: nothing
++ // ... some hardware can't report disconnection
++
++ // CONNECT: just the speed
++ enum usb_device_speed speed;
++
++ // SETUP: packet; DATA phase i/o precedes next event
++ // (setup.bmRequestType & USB_DIR_IN) flags direction
++ // ... includes SET_CONFIGURATION, SET_INTERFACE
++ struct usb_ctrlrequest setup;
++ } u;
++ enum usb_gadgetfs_event_type type;
++};
++
++
++/* endpoint ioctls */
++
++/* IN transfers may be reported to the gadget driver as complete
++ * when the fifo is loaded, before the host reads the data;
++ * OUT transfers may be reported to the host's "client" driver as
++ * complete when they're sitting in the FIFO unread.
++ * THIS returns how many bytes are "unclaimed" in the endpoint fifo
++ * (needed for precise fault handling, when the hardware allows it)
++ */
++#define GADGETFS_FIFO_STATUS _IO('g',1)
++
++/* discards any unclaimed data in the fifo. */
++#define GADGETFS_FIFO_FLUSH _IO('g',2)
++
++/* resets endpoint halt+toggle; used to implement set_interface.
++ * some hardware (like pxa2xx) can't support this.
++ */
++#define GADGETFS_CLEAR_HALT _IO('g',3)
+
- 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)
++#endif /* __LINUX_USB_GADGETFS_H */
+diff -x .git -Nur linux-2.6.22.1/include/linux/usb/Kbuild linux-avr32.git/include/linux/usb/Kbuild
+--- linux-2.6.22.1/include/linux/usb/Kbuild 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/include/linux/usb/Kbuild 2007-07-12 14:00:31.000000000 +0200
+@@ -1,5 +1,6 @@
+ unifdef-y += audio.h
+ unifdef-y += cdc.h
+ unifdef-y += ch9.h
++unifdef-y += gadgetfs.h
+ unifdef-y += midi.h
+
+diff -x .git -Nur linux-2.6.22.1/include/linux/usb_gadgetfs.h linux-avr32.git/include/linux/usb_gadgetfs.h
+--- linux-2.6.22.1/include/linux/usb_gadgetfs.h 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/include/linux/usb_gadgetfs.h 1970-01-01 01:00:00.000000000 +0100
+@@ -1,75 +0,0 @@
-
- /* 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)
+-#include <asm/types.h>
+-#include <asm/ioctl.h>
-
- /*
- * 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 <linux/usb/ch9.h>
-
- #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)
+-/*
+- * Filesystem based user-mode API to USB Gadget controller hardware
+- *
+- * Almost everything can be done with only read and write operations,
+- * on endpoint files found in one directory. They are configured by
+- * writing descriptors, and then may be used for normal stream style
+- * i/o requests. When ep0 is configured, the device can enumerate;
+- * when it's closed, the device disconnects from usb.
+- *
+- * Configuration and device descriptors get written to /dev/gadget/$CHIP,
+- * which may then be used to read usb_gadgetfs_event structs. The driver
+- * may activate endpoints as it handles SET_CONFIGURATION setup events,
+- * or earlier; writing endpoint descriptors to /dev/gadget/$ENDPOINT
+- * then performing data transfers by reading or writing.
+- */
-
- /* 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)
+-/*
+- * Events are delivered on the ep0 file descriptor, if the user mode driver
+- * reads from this file descriptor after writing the descriptors. Don't
+- * stop polling this descriptor, if you write that kind of driver.
+- */
-
- /*
- * 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)
+-enum usb_gadgetfs_event_type {
+- GADGETFS_NOP = 0,
-
- 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)
+- GADGETFS_CONNECT,
+- GADGETFS_DISCONNECT,
+- GADGETFS_SETUP,
+- GADGETFS_SUSPEND,
+- // and likely more !
+-};
-
- #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
+-struct usb_gadgetfs_event {
+- enum usb_gadgetfs_event_type type;
+- union {
+- // NOP, DISCONNECT, SUSPEND: nothing
+- // ... some hardware can't report disconnection
+-
+- // CONNECT: just the speed
+- enum usb_device_speed speed;
+-
+- // SETUP: packet; DATA phase i/o precedes next event
+- // (setup.bmRequestType & USB_DIR_IN) flags direction
+- // ... includes SET_CONFIGURATION, SET_INTERFACE
+- struct usb_ctrlrequest setup;
+- } u;
+-};
+-
+-
+-/* endpoint ioctls */
+-
+-/* IN transfers may be reported to the gadget driver as complete
+- * when the fifo is loaded, before the host reads the data;
+- * OUT transfers may be reported to the host's "client" driver as
+- * complete when they're sitting in the FIFO unread.
+- * THIS returns how many bytes are "unclaimed" in the endpoint fifo
+- * (needed for precise fault handling, when the hardware allows it)
+- */
+-#define GADGETFS_FIFO_STATUS _IO('g',1)
+-
+-/* discards any unclaimed data in the fifo. */
+-#define GADGETFS_FIFO_FLUSH _IO('g',2)
+-
+-/* resets endpoint halt+toggle; used to implement set_interface.
+- * some hardware (like pxa2xx) can't support this.
+- */
+-#define GADGETFS_CLEAR_HALT _IO('g',3)
+-
+-
+diff -x .git -Nur linux-2.6.22.1/init/do_mounts.c linux-avr32.git/init/do_mounts.c
+--- linux-2.6.22.1/init/do_mounts.c 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/init/do_mounts.c 2007-07-12 14:00:31.000000000 +0200
+@@ -25,6 +25,7 @@
+ int root_mountflags = MS_RDONLY | MS_SILENT;
+ char * __initdata root_device_name;
+ static char __initdata saved_root_name[64];
++int __initdata root_wait;
-+#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
+ dev_t ROOT_DEV;
- #include <asm/page.h>
-+#include <asm/types.h>
+@@ -216,6 +217,14 @@
- 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__
+ __setup("root=", root_dev_setup);
-+#include <asm/types.h>
++static int __init rootwait_setup(char *line)
++{
++ root_wait = simple_strtol(line,NULL,0);
++ return 1;
++}
+
- 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>
++__setup("rootwait=", rootwait_setup);
+
- 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
+ static char * __initdata root_mount_data;
+ static int __init root_data_setup(char *str)
+ {
+@@ -438,11 +447,24 @@
+ root_device_name += 5;
+ }
-+#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;
+- is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;
+-
+ if (initrd_load())
+ goto out;
+
++ /* wait for any asynchronous scanning to complete */
++ if ((ROOT_DEV == 0) && root_wait) {
++ printk(KERN_INFO "Waiting for root device %s...\n",
++ saved_root_name);
++ do {
++ while (driver_probe_done() != 0)
++ msleep(100);
++ ROOT_DEV = name_to_dev_t(saved_root_name);
++ if (ROOT_DEV == 0)
++ msleep(100);
++ } while (ROOT_DEV == 0);
++ }
+
-+ 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];
-+};
++ is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;
+
-+#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/
+ if (is_floppy && rd_doload && rd_load_disk(0))
+ ROOT_DEV = Root_RAM0;
+
+diff -x .git -Nur linux-2.6.22.1/MAINTAINERS linux-avr32.git/MAINTAINERS
+--- linux-2.6.22.1/MAINTAINERS 2007-07-10 20:56:30.000000000 +0200
++++ linux-avr32.git/MAINTAINERS 2007-07-12 13:59:48.000000000 +0200
+@@ -674,6 +674,13 @@
+ M: hskinnemoen@atmel.com
S: Supported
-+GENERIC GPIO I2C DRIVER
++ATMEL USBA UDC DRIVER
+P: Haavard Skinnemoen
+M: hskinnemoen@atmel.com
++L: kernel@avr32linux.org
++W: http://avr32linux.org/twiki/bin/view/Main/AtmelUsbDeviceDriver
+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
+ ATMEL WIRELESS DRIVER
+ P: Simon Kelley
+ M: simon@thekelleys.org.uk
+diff -x .git -Nur linux-2.6.22.1/scripts/checkstack.pl linux-avr32.git/scripts/checkstack.pl
+--- linux-2.6.22.1/scripts/checkstack.pl 2007-07-10 20:56:30.000000000 +0200
++++ linux-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>