diff options
Diffstat (limited to 'toolchain/kernel-headers')
| -rw-r--r-- | toolchain/kernel-headers/kernel-headers-new.makefile | 4 | ||||
| -rw-r--r-- | toolchain/kernel-headers/linux-2.6.22.1-003-atmel.3-avr32-updates.patch | 14820 | 
2 files changed, 4 insertions, 14820 deletions
diff --git a/toolchain/kernel-headers/kernel-headers-new.makefile b/toolchain/kernel-headers/kernel-headers-new.makefile index 75bcce48e..fd5dc344f 100644 --- a/toolchain/kernel-headers/kernel-headers-new.makefile +++ b/toolchain/kernel-headers/kernel-headers-new.makefile @@ -63,6 +63,10 @@ ifeq ($(BR2_KERNEL_HEADERS_LZMA),y)  	toolchain/patch-kernel.sh $(LINUX_HEADERS_UNPACK_DIR) toolchain/kernel-headers/lzma \  		linux-$(LINUX_HEADERS_VERSION)-\*.patch{,.gz,.bz2}  endif +ifneq ($(LINUX26_HEADERS_PATCH_DIR),) +	toolchain/patch-kernel.sh $(LINUX_HEADERS_UNPACK_DIR) $(LINUX26_HEADERS_PATCH_DIR) \ +		linux-$(LINUX_HEADERS_VERSION)-\*.patch{,.gz,.bz2} +endif  ifeq ($(BR2_PACKAGE_OPENSWAN),y)  	toolchain/patch-kernel.sh $(LINUX_HEADERS_UNPACK_DIR) package/openswan \  		linux-$(LINUX_HEADERS_VERSION)-\*.patch{,.gz,.bz2} diff --git a/toolchain/kernel-headers/linux-2.6.22.1-003-atmel.3-avr32-updates.patch b/toolchain/kernel-headers/linux-2.6.22.1-003-atmel.3-avr32-updates.patch deleted file mode 100644 index 9da7547b3..000000000 --- a/toolchain/kernel-headers/linux-2.6.22.1-003-atmel.3-avr32-updates.patch +++ /dev/null @@ -1,14820 +0,0 @@ -diff --git a/MAINTAINERS b/MAINTAINERS -index df40a4e..3c5cfef 100644 ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -674,6 +674,13 @@ P:	Haavard Skinnemoen - M:	hskinnemoen@atmel.com - S:	Supported -  -+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 -+ - ATMEL WIRELESS DRIVER - P:	Simon Kelley - M:	simon@thekelleys.org.uk -diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig -index 3ec7658..ec6c7c5 100644 ---- a/arch/avr32/Kconfig -+++ b/arch/avr32/Kconfig -@@ -113,6 +113,13 @@ config BOARD_ATNGW100 - 	bool "ATNGW100 Network Gateway" - endchoice -  -+if BOARD_ATSTK1000 -+source "arch/avr32/boards/atstk1000/Kconfig" -+endif -+if BOARD_ATNGW100 -+source "arch/avr32/boards/atngw100/Kconfig" -+endif -+ - choice - 	prompt "Boot loader type" - 	default LOADER_U_BOOT -@@ -171,6 +178,10 @@ config OWNERSHIP_TRACE - 	  enabling Nexus-compliant debuggers to keep track of the PID of the - 	  currently executing task. -  -+config DW_DMAC -+	tristate "Synopsys DesignWare DMA Controller support" -+	default y if CPU_AT32AP7000 -+ - # FPU emulation goes here -  - source "kernel/Kconfig.hz" -@@ -185,6 +196,27 @@ config CMDLINE -  - 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" -  - config PCI -diff --git a/arch/avr32/Makefile b/arch/avr32/Makefile -index dc6bc01..eb72198 100644 ---- a/arch/avr32/Makefile -+++ b/arch/avr32/Makefile -@@ -31,6 +31,7 @@ core-$(CONFIG_BOARD_ATNGW100)		+= arch/avr32/boards/atngw100/ - core-$(CONFIG_LOADER_U_BOOT)		+= arch/avr32/boot/u-boot/ - core-y					+= arch/avr32/kernel/ - core-y					+= arch/avr32/mm/ -+drivers-y				+= arch/avr32/drivers/ - libs-y					+= arch/avr32/lib/ -  - archincdir-$(CONFIG_PLATFORM_AT32AP)	:= arch-at32ap -diff --git a/arch/avr32/boards/atngw100/Kconfig b/arch/avr32/boards/atngw100/Kconfig -new file mode 100644 -index 0000000..5d922df ---- /dev/null -+++ b/arch/avr32/boards/atngw100/Kconfig -@@ -0,0 +1,12 @@ -+# NGW100 customization -+ -+config BOARD_ATNGW100_I2C_GPIO -+	bool "Use GPIO for i2c instead of built-in TWI module" -+	help -+	  The driver for the built-in TWI module has been plagued by -+	  various problems, while the i2c-gpio driver is based on the -+	  trusty old i2c-algo-bit bitbanging engine, making it work -+	  on pretty much any setup. -+ -+	  Choose 'Y' here if you're having i2c-related problems and -+	  want to rule out the i2c bus driver. -diff --git a/arch/avr32/boards/atngw100/setup.c b/arch/avr32/boards/atngw100/setup.c -index 6c4dc0a..d649974 100644 ---- a/arch/avr32/boards/atngw100/setup.c -+++ b/arch/avr32/boards/atngw100/setup.c -@@ -9,10 +9,12 @@ -  */ - #include <linux/clk.h> - #include <linux/etherdevice.h> -+#include <linux/i2c-gpio.h> - #include <linux/init.h> - #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 +23,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 +42,11 @@ static struct spi_board_info spi0_board_info[] __initdata = { - 	}, - }; -  -+static struct mci_platform_data __initdata mci0_data = { -+	.detect_pin	= GPIO_PIN_PC(25), -+	.wp_pin		= GPIO_PIN_PE(0), -+}; -+ - /* -  * The next two functions should go away as the boot loader is -  * supposed to initialize the macb address registers with a valid -@@ -100,8 +108,46 @@ void __init setup_board(void) - 	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, -+	} -+}; -+ -+#ifdef CONFIG_BOARD_ATNGW100_I2C_GPIO -+static struct i2c_gpio_platform_data i2c_gpio_data = { -+	.sda_pin	= GPIO_PIN_PA(6), -+	.scl_pin	= GPIO_PIN_PA(7), -+}; -+ -+static struct platform_device i2c_gpio_device = { -+	.name		= "i2c-gpio", -+	.id		= 0, -+	.dev		= { -+		.platform_data	= &i2c_gpio_data, -+	}, -+}; -+#endif -+ - 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 +161,22 @@ static int __init atngw100_init(void) - 	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); -+ -+#ifdef CONFIG_BOARD_ATNGW100_I2C_GPIO -+	at32_select_gpio(i2c_gpio_data.sda_pin, 0); -+	at32_select_gpio(i2c_gpio_data.scl_pin, 0); -+	platform_device_register(&i2c_gpio_device); -+#else -+	at32_add_device_twi(0); -+#endif -  - 	return 0; - } -diff --git a/arch/avr32/boards/atstk1000/Kconfig b/arch/avr32/boards/atstk1000/Kconfig -new file mode 100644 -index 0000000..718578f ---- /dev/null -+++ b/arch/avr32/boards/atstk1000/Kconfig -@@ -0,0 +1,79 @@ -+# STK1000 customization -+ -+if BOARD_ATSTK1002 -+ -+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. -+ -+if BOARD_ATSTK1002_CUSTOM -+ -+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. -+ -+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. -+ -+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. -+ -+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. -+ -+config BOARD_ATSTK1002_SW5_CUSTOM -+	bool "SW5: use MACB1 (not LCDC)" -+ -+config BOARD_ATSTK1002_SW6_CUSTOM -+	bool "SW6: more GPIOs (not MACB0)" -+ -+endif	# custom -+ -+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. -+ -+config BOARD_ATSTK1002_J2_LED -+	bool -+	default BOARD_ATSTK1002_J2_LED8 || BOARD_ATSTK1002_J2_RGB -+ -+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. -+ -+config BOARD_ATSTK1002_J2_LED8 -+	bool "LED0..LED7" -+	help -+	  Select this if J2 is jumpered to LED0..LED7 amber leds. -+ -+config BOARD_ATSTK1002_J2_RGB -+	bool "RGB leds" -+	help -+	  Select this if J2 is jumpered to the RGB leds. -+ -+endchoice -+ -+endif	# stk 1002 -diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c -index e253e86..c958fd4 100644 ---- a/arch/avr32/boards/atstk1000/atstk1002.c -+++ b/arch/avr32/boards/atstk1000/atstk1002.c -@@ -11,10 +11,12 @@ - #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> - #include <linux/spi/spi.h> -+#include <linux/spi/at73c213.h> -  - #include <video/atmel_lcdc.h> -  -@@ -27,16 +29,47 @@ -  - #include "atstk1000.h" -  --#define	SW2_DEFAULT		/* MMCI and UART_A available */ -  - struct eth_addr { - 	u8 addr[6]; - }; -  - static struct eth_addr __initdata hw_addr[2]; --static struct eth_platform_data __initdata eth_data[2]; -+static struct eth_platform_data __initdata eth_data[2] = { -+	{ -+		/* -+		 * The MDIO pullups on STK1000 are a bit too weak for -+		 * the autodetection to work properly, so we have to -+		 * mask out everything but the correct address. -+		 */ -+		.phy_mask	= ~(1U << 16), -+	}, -+	{ -+		.phy_mask	= ~(1U << 17), -+	}, -+}; -+ -+#ifndef CONFIG_BOARD_ATSTK1002_SW1_CUSTOM -+#ifndef CONFIG_BOARD_ATSTK1002_SW3_CUSTOM -+static struct at73c213_board_info at73c213_data = { -+	.ssc_id		= 0, -+	.shortname	= "AVR32 STK1000 external DAC", -+}; -+#endif -+#endif -  -+#ifndef CONFIG_BOARD_ATSTK1002_SW1_CUSTOM - static struct spi_board_info spi0_board_info[] __initdata = { -+#ifndef CONFIG_BOARD_ATSTK1002_SW3_CUSTOM -+	{ -+		/* AT73C213 */ -+		.modalias	= "at73c213", -+		.max_speed_hz	= 200000, -+		.chip_select	= 0, -+		.mode		= SPI_MODE_1, -+		.platform_data	= &at73c213_data, -+	}, -+#endif - 	{ - 		/* QVGA display */ - 		.modalias	= "ltv350qv", -@@ -45,6 +78,18 @@ static struct spi_board_info spi0_board_info[] __initdata = { - 		.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 +146,103 @@ static void __init set_hw_addr(struct platform_device *pdev) - 	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 gpio_led_platform_data stk_j2_led_data = { -+	.num_leds	= ARRAY_SIZE(stk_j2_led), -+	.leds		= stk_j2_led, -+}; -+ -+static struct platform_device stk_j2_led_dev = { -+	.name		= "leds-gpio", -+	.id		= 2,	/* gpio block J2 */ -+	.dev		= { -+		.platform_data	= &stk_j2_led_data, -+	}, -+}; -+ -+static void setup_j2_leds(void) - { --#ifdef	SW2_DEFAULT --	at32_map_usart(1, 0);	/* USART 1/A: /dev/ttyS0, DB9 */ -+	unsigned	i; -+ -+	for (i = 0; i < ARRAY_SIZE(stk_j2_led); i++) -+		at32_select_gpio(stk_j2_led[i].gpio, AT32_GPIOF_OUTPUT); -+ -+	printk("STK1002: " LEDSTRING "\n"); -+	platform_device_register(&stk_j2_led_dev); -+} -+ - #else -+static void setup_j2_leds(void) -+{ -+} -+#endif -+ -+#ifndef CONFIG_BOARD_ATSTK1002_SW1_CUSTOM -+#ifndef CONFIG_BOARD_ATSTK1002_SW3_CUSTOM -+static void __init at73c213_set_clk(struct at73c213_board_info *info) -+{ -+	struct clk *gclk; -+	struct clk *pll; -+ -+	gclk = clk_get(NULL, "gclk0"); -+	if (IS_ERR(gclk)) -+		goto err_gclk; -+	pll = clk_get(NULL, "pll0"); -+	if (IS_ERR(pll)) -+		goto err_pll; -+ -+	if (clk_set_parent(gclk, pll)) { -+		pr_debug("STK1000: failed to set pll0 as parent for DAC clock\n"); -+		goto err_set_clk; -+	} -+ -+	at32_select_periph(GPIO_PIN_PA(30), GPIO_PERIPH_A, 0); -+	info->dac_clk = gclk; -+ -+err_set_clk: -+	clk_put(pll); -+err_pll: -+	clk_put(gclk); -+err_gclk: -+	return; -+} -+#endif -+#endif -+ -+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 +276,46 @@ static int __init atstk1002_init(void) -  - 	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 -+ -+#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 -+ -+	setup_j2_leds(); -+ -+#ifndef CONFIG_BOARD_ATSTK1002_SW3_CUSTOM -+#ifndef CONFIG_BOARD_ATSTK1002_SW1_CUSTOM -+	at73c213_set_clk(&at73c213_data); -+#endif -+#endif -  - 	return 0; - } -diff --git a/arch/avr32/configs/atngw100_defconfig b/arch/avr32/configs/atngw100_defconfig -index 49493ad..adce168 100644 ---- a/arch/avr32/configs/atngw100_defconfig -+++ b/arch/avr32/configs/atngw100_defconfig -@@ -1,7 +1,7 @@ - # - # Automatically generated make config: don't edit --# Linux kernel version: 2.6.22-rc5 --# Sat Jun 23 15:40:05 2007 -+# Linux kernel version: 2.6.22.atmel.1 -+# Thu Jul 12 17:49:20 2007 - # - CONFIG_AVR32=y - CONFIG_GENERIC_GPIO=y -@@ -114,6 +114,7 @@ CONFIG_PLATFORM_AT32AP=y - CONFIG_CPU_AT32AP7000=y - # CONFIG_BOARD_ATSTK1000 is not set - CONFIG_BOARD_ATNGW100=y -+# CONFIG_BOARD_ATNGW100_I2C_GPIO is not set - CONFIG_LOADER_U_BOOT=y -  - # -@@ -122,6 +123,7 @@ CONFIG_LOADER_U_BOOT=y - # CONFIG_AP7000_32_BIT_SMC is not set - CONFIG_AP7000_16_BIT_SMC=y - # CONFIG_AP7000_8_BIT_SMC is not set -+CONFIG_GPIO_DEV=y - CONFIG_LOAD_ADDRESS=0x10000000 - CONFIG_ENTRY_ADDRESS=0x90000000 - CONFIG_PHYS_OFFSET=0x10000000 -@@ -145,6 +147,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 - # CONFIG_RESOURCES_64BIT is not set - CONFIG_ZONE_DMA_FLAG=0 - # CONFIG_OWNERSHIP_TRACE is not set -+CONFIG_DW_DMAC=y - # CONFIG_HZ_100 is not set - CONFIG_HZ_250=y - # CONFIG_HZ_300 is not set -@@ -153,6 +156,27 @@ CONFIG_HZ=250 - CONFIG_CMDLINE="" -  - # -+# Power managment options -+# -+ -+# -+# CPU Frequency scaling -+# -+CONFIG_CPU_FREQ=y -+CONFIG_CPU_FREQ_TABLE=y -+# CONFIG_CPU_FREQ_DEBUG is not set -+CONFIG_CPU_FREQ_STAT=m -+# CONFIG_CPU_FREQ_STAT_DETAILS is not set -+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y -+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set -+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -+CONFIG_CPU_FREQ_GOV_POWERSAVE=y -+CONFIG_CPU_FREQ_GOV_USERSPACE=y -+CONFIG_CPU_FREQ_GOV_ONDEMAND=y -+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set -+CONFIG_CPU_FREQ_AT32AP=y -+ -+# - # Bus options - # - # CONFIG_ARCH_SUPPORTS_MSI is not set -@@ -187,13 +211,8 @@ CONFIG_NET_KEY=y - # CONFIG_NET_KEY_MIGRATE is not set - CONFIG_INET=y - CONFIG_IP_MULTICAST=y --CONFIG_IP_ADVANCED_ROUTER=y --CONFIG_ASK_IP_FIB_HASH=y --# CONFIG_IP_FIB_TRIE is not set -+# CONFIG_IP_ADVANCED_ROUTER is not set - CONFIG_IP_FIB_HASH=y --# CONFIG_IP_MULTIPLE_TABLES is not set --# CONFIG_IP_ROUTE_MULTIPATH is not set --# CONFIG_IP_ROUTE_VERBOSE is not set - CONFIG_IP_PNP=y - CONFIG_IP_PNP_DHCP=y - # CONFIG_IP_PNP_BOOTP is not set -@@ -240,6 +259,7 @@ CONFIG_IPV6_SIT=y - # CONFIG_NETWORK_SECMARK is not set - CONFIG_NETFILTER=y - # CONFIG_NETFILTER_DEBUG is not set -+CONFIG_BRIDGE_NETFILTER=y -  - # - # Core Netfilter Configuration -@@ -284,6 +304,7 @@ CONFIG_NETFILTER_XT_MATCH_MAC=m - CONFIG_NETFILTER_XT_MATCH_MARK=m - CONFIG_NETFILTER_XT_MATCH_POLICY=m - CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m -+# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set - CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m - CONFIG_NETFILTER_XT_MATCH_QUOTA=m - CONFIG_NETFILTER_XT_MATCH_REALM=m -@@ -359,13 +380,19 @@ CONFIG_IP6_NF_TARGET_REJECT=m - CONFIG_IP6_NF_MANGLE=m - CONFIG_IP6_NF_TARGET_HL=m - CONFIG_IP6_NF_RAW=m -+ -+# -+# Bridge: Netfilter Configuration -+# -+# CONFIG_BRIDGE_NF_EBTABLES is not set - # CONFIG_IP_DCCP is not set - # CONFIG_IP_SCTP is not set - # CONFIG_TIPC is not set - # CONFIG_ATM is not set --# CONFIG_BRIDGE is not set -+CONFIG_BRIDGE=m - CONFIG_VLAN_8021Q=m - # CONFIG_DECNET is not set -+CONFIG_LLC=m - # CONFIG_LLC2 is not set - # CONFIG_IPX is not set - # CONFIG_ATALK is not set -@@ -521,7 +548,6 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 - # - # Misc devices - # --# CONFIG_BLINK is not set - # CONFIG_IDE is not set -  - # -@@ -545,13 +571,26 @@ CONFIG_NETDEVICES=y - # CONFIG_BONDING is not set - # CONFIG_EQUALIZER is not set - CONFIG_TUN=m --# CONFIG_PHYLIB is not set -+CONFIG_PHYLIB=y -+ -+# -+# MII PHY device drivers -+# -+# CONFIG_MARVELL_PHY is not set -+# CONFIG_DAVICOM_PHY is not set -+# CONFIG_QSEMI_PHY is not set -+# CONFIG_LXT_PHY is not set -+# CONFIG_CICADA_PHY is not set -+# CONFIG_VITESSE_PHY is not set -+# CONFIG_SMSC_PHY is not set -+# CONFIG_BROADCOM_PHY is not set -+# CONFIG_FIXED_PHY is not set -  - # - # Ethernet (10 or 100Mbit) - # - CONFIG_NET_ETHERNET=y --CONFIG_MII=y -+# CONFIG_MII is not set - CONFIG_MACB=y - # CONFIG_NETDEV_1000 is not set - # CONFIG_NETDEV_10000 is not set -@@ -625,7 +664,15 @@ CONFIG_UNIX98_PTYS=y - # IPMI - # - # CONFIG_IPMI_HANDLER is not set --# CONFIG_WATCHDOG is not set -+CONFIG_WATCHDOG=y -+# CONFIG_WATCHDOG_NOWAYOUT is not set -+ -+# -+# Watchdog Device Drivers -+# -+# CONFIG_SOFT_WATCHDOG is not set -+CONFIG_AT32AP700X_WDT=y -+CONFIG_AT32AP700X_WDT_TIMEOUT=2 - # CONFIG_HW_RANDOM is not set - # CONFIG_RTC is not set - # CONFIG_GEN_RTC is not set -@@ -636,7 +683,42 @@ CONFIG_UNIX98_PTYS=y - # TPM devices - # - # CONFIG_TCG_TPM is not set --# CONFIG_I2C is not set -+CONFIG_I2C=m -+CONFIG_I2C_BOARDINFO=y -+CONFIG_I2C_CHARDEV=m -+ -+# -+# I2C Algorithms -+# -+CONFIG_I2C_ALGOBIT=m -+# CONFIG_I2C_ALGOPCF is not set -+# CONFIG_I2C_ALGOPCA is not set -+ -+# -+# I2C Hardware Bus support -+# -+CONFIG_I2C_ATMELTWI=m -+CONFIG_I2C_ATMELTWI_BAUDRATE=100000 -+CONFIG_I2C_GPIO=m -+# CONFIG_I2C_OCORES is not set -+# CONFIG_I2C_PARPORT_LIGHT is not set -+# CONFIG_I2C_SIMTEC is not set -+# CONFIG_I2C_STUB is not set -+ -+# -+# Miscellaneous I2C Chip support -+# -+# CONFIG_SENSORS_DS1337 is not set -+# CONFIG_SENSORS_DS1374 is not set -+# CONFIG_SENSORS_EEPROM is not set -+# CONFIG_SENSORS_PCF8574 is not set -+# CONFIG_SENSORS_PCA9539 is not set -+# CONFIG_SENSORS_PCF8591 is not set -+# CONFIG_SENSORS_MAX6875 is not set -+# CONFIG_I2C_DEBUG_CORE is not set -+# CONFIG_I2C_DEBUG_ALGO is not set -+# CONFIG_I2C_DEBUG_BUS is not set -+# CONFIG_I2C_DEBUG_CHIP is not set -  - # - # SPI support -@@ -655,7 +737,7 @@ CONFIG_SPI_ATMEL=y - # SPI Protocol Masters - # - # CONFIG_SPI_AT25 is not set --# CONFIG_SPI_SPIDEV is not set -+CONFIG_SPI_SPIDEV=m -  - # - # Dallas's 1-wire bus -@@ -706,21 +788,59 @@ CONFIG_SPI_ATMEL=y - # - # USB Gadget Support - # --# CONFIG_USB_GADGET is not set --# CONFIG_MMC is not set -+CONFIG_USB_GADGET=y -+# CONFIG_USB_GADGET_DEBUG_FILES is not set -+CONFIG_USB_GADGET_SELECTED=y -+# CONFIG_USB_GADGET_FSL_USB2 is not set -+# CONFIG_USB_GADGET_NET2280 is not set -+# CONFIG_USB_GADGET_PXA2XX is not set -+# CONFIG_USB_GADGET_GOKU is not set -+# CONFIG_USB_GADGET_LH7A40X is not set -+CONFIG_USB_GADGET_ATMEL_USBA=y -+CONFIG_USB_ATMEL_USBA=y -+# CONFIG_USB_GADGET_OMAP is not set -+# CONFIG_USB_GADGET_AT91 is not set -+# CONFIG_USB_GADGET_DUMMY_HCD is not set -+CONFIG_USB_GADGET_DUALSPEED=y -+CONFIG_USB_ZERO=m -+CONFIG_USB_ETH=m -+CONFIG_USB_ETH_RNDIS=y -+CONFIG_USB_GADGETFS=m -+CONFIG_USB_FILE_STORAGE=m -+# CONFIG_USB_FILE_STORAGE_TEST is not set -+CONFIG_USB_G_SERIAL=m -+# CONFIG_USB_MIDI_GADGET is not set -+CONFIG_MMC=y -+# CONFIG_MMC_DEBUG is not set -+# CONFIG_MMC_UNSAFE_RESUME is not set -+ -+# -+# MMC/SD Card Drivers -+# -+CONFIG_MMC_BLOCK=y -+ -+# -+# MMC/SD Host Controller Drivers -+# -+CONFIG_MMC_ATMELMCI=y -  - # - # LED devices - # --# CONFIG_NEW_LEDS is not set -+CONFIG_NEW_LEDS=y -+CONFIG_LEDS_CLASS=y -  - # - # LED drivers - # -+CONFIG_LEDS_GPIO=y -  - # - # LED Triggers - # -+CONFIG_LEDS_TRIGGERS=y -+CONFIG_LEDS_TRIGGER_TIMER=y -+CONFIG_LEDS_TRIGGER_HEARTBEAT=y -  - # - # InfiniBand support -@@ -733,7 +853,51 @@ CONFIG_SPI_ATMEL=y - # - # Real Time Clock - # --# CONFIG_RTC_CLASS is not set -+CONFIG_RTC_LIB=y -+CONFIG_RTC_CLASS=y -+CONFIG_RTC_HCTOSYS=y -+CONFIG_RTC_HCTOSYS_DEVICE="rtc0" -+# CONFIG_RTC_DEBUG is not set -+ -+# -+# RTC interfaces -+# -+CONFIG_RTC_INTF_SYSFS=y -+CONFIG_RTC_INTF_PROC=y -+CONFIG_RTC_INTF_DEV=y -+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set -+# CONFIG_RTC_DRV_TEST is not set -+ -+# -+# I2C RTC drivers -+# -+# CONFIG_RTC_DRV_DS1307 is not set -+# CONFIG_RTC_DRV_DS1672 is not set -+# CONFIG_RTC_DRV_MAX6900 is not set -+# CONFIG_RTC_DRV_RS5C372 is not set -+# CONFIG_RTC_DRV_ISL1208 is not set -+# CONFIG_RTC_DRV_X1205 is not set -+# CONFIG_RTC_DRV_PCF8563 is not set -+# CONFIG_RTC_DRV_PCF8583 is not set -+ -+# -+# SPI RTC drivers -+# -+# CONFIG_RTC_DRV_RS5C348 is not set -+# CONFIG_RTC_DRV_MAX6902 is not set -+ -+# -+# Platform RTC drivers -+# -+# CONFIG_RTC_DRV_DS1553 is not set -+# CONFIG_RTC_DRV_DS1742 is not set -+# CONFIG_RTC_DRV_M48T86 is not set -+# CONFIG_RTC_DRV_V3020 is not set -+ -+# -+# on-CPU RTC drivers -+# -+CONFIG_RTC_DRV_AT32AP700X=y -  - # - # DMA Engine support -@@ -767,7 +931,8 @@ CONFIG_JBD=y - # CONFIG_OCFS2_FS is not set - # CONFIG_MINIX_FS is not set - # CONFIG_ROMFS_FS is not set --# CONFIG_INOTIFY is not set -+CONFIG_INOTIFY=y -+CONFIG_INOTIFY_USER=y - # CONFIG_QUOTA is not set - # CONFIG_DNOTIFY is not set - # CONFIG_AUTOFS_FS is not set -@@ -922,7 +1087,7 @@ CONFIG_TRACE_IRQFLAGS_SUPPORT=y - CONFIG_ENABLE_MUST_CHECK=y - CONFIG_MAGIC_SYSRQ=y - # CONFIG_UNUSED_SYMBOLS is not set --# CONFIG_DEBUG_FS is not set -+CONFIG_DEBUG_FS=y - # CONFIG_HEADERS_CHECK is not set - CONFIG_DEBUG_KERNEL=y - # CONFIG_DEBUG_SHIRQ is not set -diff --git a/arch/avr32/configs/atstk1002_defconfig b/arch/avr32/configs/atstk1002_defconfig -index 3b977fd..3708066 100644 ---- a/arch/avr32/configs/atstk1002_defconfig -+++ b/arch/avr32/configs/atstk1002_defconfig -@@ -1,7 +1,7 @@ - # - # Automatically generated make config: don't edit --# Linux kernel version: 2.6.22-rc5 --# Sat Jun 23 15:32:08 2007 -+# Linux kernel version: 2.6.22.atmel.2 -+# Thu Jul 19 13:46:47 2007 - # - CONFIG_AVR32=y - CONFIG_GENERIC_GPIO=y -@@ -80,10 +80,10 @@ CONFIG_BASE_SMALL=1 - # - CONFIG_MODULES=y - CONFIG_MODULE_UNLOAD=y --# CONFIG_MODULE_FORCE_UNLOAD is not set -+CONFIG_MODULE_FORCE_UNLOAD=y - # CONFIG_MODVERSIONS is not set - # CONFIG_MODULE_SRCVERSION_ALL is not set --# CONFIG_KMOD is not set -+CONFIG_KMOD=y -  - # - # Block layer -@@ -99,12 +99,12 @@ CONFIG_BLOCK=y - CONFIG_IOSCHED_NOOP=y - # CONFIG_IOSCHED_AS is not set - # CONFIG_IOSCHED_DEADLINE is not set --# CONFIG_IOSCHED_CFQ is not set -+CONFIG_IOSCHED_CFQ=y - # CONFIG_DEFAULT_AS is not set - # CONFIG_DEFAULT_DEADLINE is not set --# CONFIG_DEFAULT_CFQ is not set --CONFIG_DEFAULT_NOOP=y --CONFIG_DEFAULT_IOSCHED="noop" -+CONFIG_DEFAULT_CFQ=y -+# CONFIG_DEFAULT_NOOP is not set -+CONFIG_DEFAULT_IOSCHED="cfq" -  - # - # System Type and features -@@ -117,6 +117,11 @@ CONFIG_CPU_AT32AP7000=y - CONFIG_BOARD_ATSTK1002=y - CONFIG_BOARD_ATSTK1000=y - # CONFIG_BOARD_ATNGW100 is not set -+# CONFIG_BOARD_ATSTK1002_CUSTOM is not set -+# CONFIG_BOARD_ATSTK1002_SPI1 is not set -+# CONFIG_BOARD_ATSTK1002_J2_LED is not set -+# CONFIG_BOARD_ATSTK1002_J2_LED8 is not set -+# CONFIG_BOARD_ATSTK1002_J2_RGB is not set - CONFIG_LOADER_U_BOOT=y -  - # -@@ -125,6 +130,7 @@ CONFIG_LOADER_U_BOOT=y - # CONFIG_AP7000_32_BIT_SMC is not set - CONFIG_AP7000_16_BIT_SMC=y - # CONFIG_AP7000_8_BIT_SMC is not set -+CONFIG_GPIO_DEV=y - CONFIG_LOAD_ADDRESS=0x10000000 - CONFIG_ENTRY_ADDRESS=0x90000000 - CONFIG_PHYS_OFFSET=0x10000000 -@@ -148,6 +154,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 - # CONFIG_RESOURCES_64BIT is not set - CONFIG_ZONE_DMA_FLAG=0 - # CONFIG_OWNERSHIP_TRACE is not set -+CONFIG_DW_DMAC=y - # CONFIG_HZ_100 is not set - CONFIG_HZ_250=y - # CONFIG_HZ_300 is not set -@@ -156,6 +163,27 @@ CONFIG_HZ=250 - CONFIG_CMDLINE="" -  - # -+# Power managment options -+# -+ -+# -+# CPU Frequency scaling -+# -+CONFIG_CPU_FREQ=y -+CONFIG_CPU_FREQ_TABLE=y -+# CONFIG_CPU_FREQ_DEBUG is not set -+CONFIG_CPU_FREQ_STAT=m -+# CONFIG_CPU_FREQ_STAT_DETAILS is not set -+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y -+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set -+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -+CONFIG_CPU_FREQ_GOV_POWERSAVE=y -+CONFIG_CPU_FREQ_GOV_USERSPACE=y -+CONFIG_CPU_FREQ_GOV_ONDEMAND=y -+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set -+CONFIG_CPU_FREQ_AT32AP=y -+ -+# - # Bus options - # - # CONFIG_ARCH_SUPPORTS_MSI is not set -@@ -327,6 +355,8 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2 - # - # Self-contained MTD device drivers - # -+CONFIG_MTD_DATAFLASH=m -+# CONFIG_MTD_M25P80 is not set - # CONFIG_MTD_SLRAM is not set - # CONFIG_MTD_PHRAM is not set - # CONFIG_MTD_MTDRAM is not set -@@ -373,7 +403,7 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 - # - # Misc devices - # --# CONFIG_BLINK is not set -+CONFIG_ATMEL_SSC=m - # CONFIG_IDE is not set -  - # -@@ -397,13 +427,26 @@ CONFIG_DUMMY=y - # CONFIG_BONDING is not set - # CONFIG_EQUALIZER is not set - CONFIG_TUN=m --# CONFIG_PHYLIB is not set -+CONFIG_PHYLIB=y -+ -+# -+# MII PHY device drivers -+# -+# CONFIG_MARVELL_PHY is not set -+# CONFIG_DAVICOM_PHY is not set -+# CONFIG_QSEMI_PHY is not set -+CONFIG_LXT_PHY=y -+# CONFIG_CICADA_PHY is not set -+# CONFIG_VITESSE_PHY is not set -+# CONFIG_SMSC_PHY is not set -+# CONFIG_BROADCOM_PHY is not set -+# CONFIG_FIXED_PHY is not set -  - # - # Ethernet (10 or 100Mbit) - # - CONFIG_NET_ETHERNET=y --CONFIG_MII=y -+# CONFIG_MII is not set - CONFIG_MACB=y - # CONFIG_NETDEV_1000 is not set - # CONFIG_NETDEV_10000 is not set -@@ -443,7 +486,42 @@ CONFIG_SLHC=m - # - # Input device support - # --# CONFIG_INPUT is not set -+CONFIG_INPUT=m -+# CONFIG_INPUT_FF_MEMLESS is not set -+CONFIG_INPUT_POLLDEV=m -+ -+# -+# Userland interfaces -+# -+CONFIG_INPUT_MOUSEDEV=m -+CONFIG_INPUT_MOUSEDEV_PSAUX=y -+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -+# CONFIG_INPUT_JOYDEV is not set -+# CONFIG_INPUT_TSDEV is not set -+# CONFIG_INPUT_EVDEV is not set -+# CONFIG_INPUT_EVBUG is not set -+ -+# -+# Input Device Drivers -+# -+CONFIG_INPUT_KEYBOARD=y -+# CONFIG_KEYBOARD_ATKBD is not set -+# CONFIG_KEYBOARD_SUNKBD is not set -+# CONFIG_KEYBOARD_LKKBD is not set -+# CONFIG_KEYBOARD_XTKBD is not set -+# CONFIG_KEYBOARD_NEWTON is not set -+# CONFIG_KEYBOARD_STOWAWAY is not set -+CONFIG_KEYBOARD_GPIO=m -+CONFIG_INPUT_MOUSE=y -+# CONFIG_MOUSE_PS2 is not set -+# CONFIG_MOUSE_SERIAL is not set -+# CONFIG_MOUSE_VSXXXAA is not set -+CONFIG_MOUSE_GPIO=m -+# CONFIG_INPUT_JOYSTICK is not set -+# CONFIG_INPUT_TABLET is not set -+# CONFIG_INPUT_TOUCHSCREEN is not set -+# CONFIG_INPUT_MISC is not set -  - # - # Hardware I/O ports -@@ -477,7 +555,15 @@ CONFIG_UNIX98_PTYS=y - # IPMI - # - # CONFIG_IPMI_HANDLER is not set --# CONFIG_WATCHDOG is not set -+CONFIG_WATCHDOG=y -+# CONFIG_WATCHDOG_NOWAYOUT is not set -+ -+# -+# Watchdog Device Drivers -+# -+# CONFIG_SOFT_WATCHDOG is not set -+CONFIG_AT32AP700X_WDT=y -+CONFIG_AT32AP700X_WDT_TIMEOUT=2 - # CONFIG_HW_RANDOM is not set - # CONFIG_RTC is not set - # CONFIG_GEN_RTC is not set -@@ -488,13 +574,61 @@ CONFIG_UNIX98_PTYS=y - # TPM devices - # - # CONFIG_TCG_TPM is not set --# CONFIG_I2C is not set -+CONFIG_I2C=m -+CONFIG_I2C_BOARDINFO=y -+CONFIG_I2C_CHARDEV=m -+ -+# -+# I2C Algorithms -+# -+CONFIG_I2C_ALGOBIT=m -+# CONFIG_I2C_ALGOPCF is not set -+# CONFIG_I2C_ALGOPCA is not set -+ -+# -+# I2C Hardware Bus support -+# -+CONFIG_I2C_ATMELTWI=m -+CONFIG_I2C_ATMELTWI_BAUDRATE=100000 -+CONFIG_I2C_GPIO=m -+# CONFIG_I2C_OCORES is not set -+# CONFIG_I2C_PARPORT_LIGHT is not set -+# CONFIG_I2C_SIMTEC is not set -+# CONFIG_I2C_STUB is not set -+ -+# -+# Miscellaneous I2C Chip support -+# -+# CONFIG_SENSORS_DS1337 is not set -+# CONFIG_SENSORS_DS1374 is not set -+# CONFIG_SENSORS_EEPROM is not set -+# CONFIG_SENSORS_PCF8574 is not set -+# CONFIG_SENSORS_PCA9539 is not set -+# CONFIG_SENSORS_PCF8591 is not set -+# CONFIG_SENSORS_MAX6875 is not set -+# CONFIG_I2C_DEBUG_CORE is not set -+# CONFIG_I2C_DEBUG_ALGO is not set -+# CONFIG_I2C_DEBUG_BUS is not set -+# CONFIG_I2C_DEBUG_CHIP is not set -  - # - # SPI support - # --# CONFIG_SPI is not set --# CONFIG_SPI_MASTER is not set -+CONFIG_SPI=y -+# CONFIG_SPI_DEBUG is not set -+CONFIG_SPI_MASTER=y -+ -+# -+# SPI Master Controller Drivers -+# -+CONFIG_SPI_ATMEL=y -+# CONFIG_SPI_BITBANG is not set -+ -+# -+# SPI Protocol Masters -+# -+# CONFIG_SPI_AT25 is not set -+CONFIG_SPI_SPIDEV=m -  - # - # Dallas's 1-wire bus -@@ -517,19 +651,91 @@ CONFIG_UNIX98_PTYS=y - # - # Graphics support - # --# CONFIG_BACKLIGHT_LCD_SUPPORT is not set -+CONFIG_BACKLIGHT_LCD_SUPPORT=y -+CONFIG_LCD_CLASS_DEVICE=y -+CONFIG_LCD_LTV350QV=y -+# CONFIG_BACKLIGHT_CLASS_DEVICE is not set -  - # - # Display device support - # - # CONFIG_DISPLAY_SUPPORT is not set - # CONFIG_VGASTATE is not set --# CONFIG_FB is not set -+CONFIG_FB=y -+# CONFIG_FIRMWARE_EDID is not set -+# CONFIG_FB_DDC is not set -+CONFIG_FB_CFB_FILLRECT=y -+CONFIG_FB_CFB_COPYAREA=y -+CONFIG_FB_CFB_IMAGEBLIT=y -+# CONFIG_FB_SYS_FILLRECT is not set -+# CONFIG_FB_SYS_COPYAREA is not set -+# CONFIG_FB_SYS_IMAGEBLIT is not set -+# CONFIG_FB_SYS_FOPS is not set -+CONFIG_FB_DEFERRED_IO=y -+# CONFIG_FB_SVGALIB is not set -+# CONFIG_FB_MACMODES is not set -+# CONFIG_FB_BACKLIGHT is not set -+# CONFIG_FB_MODE_HELPERS is not set -+# CONFIG_FB_TILEBLITTING is not set -+ -+# -+# Frame buffer hardware drivers -+# -+# CONFIG_FB_S1D13XXX is not set -+CONFIG_FB_ATMEL=y -+# CONFIG_FB_VIRTUAL is not set -+# CONFIG_LOGO is not set -  - # - # Sound - # --# CONFIG_SOUND is not set -+CONFIG_SOUND=m -+ -+# -+# Advanced Linux Sound Architecture -+# -+CONFIG_SND=m -+CONFIG_SND_TIMER=m -+CONFIG_SND_PCM=m -+# CONFIG_SND_SEQUENCER is not set -+CONFIG_SND_OSSEMUL=y -+CONFIG_SND_MIXER_OSS=m -+CONFIG_SND_PCM_OSS=m -+CONFIG_SND_PCM_OSS_PLUGINS=y -+# CONFIG_SND_DYNAMIC_MINORS is not set -+# CONFIG_SND_SUPPORT_OLD_API is not set -+CONFIG_SND_VERBOSE_PROCFS=y -+# CONFIG_SND_VERBOSE_PRINTK is not set -+# CONFIG_SND_DEBUG is not set -+ -+# -+# Generic devices -+# -+# CONFIG_SND_DUMMY is not set -+# CONFIG_SND_MTPAV is not set -+# CONFIG_SND_SERIAL_U16550 is not set -+# CONFIG_SND_MPU401 is not set -+ -+# -+# SPI devices -+# -+CONFIG_SND_AT73C213=m -+CONFIG_SND_AT73C213_TARGET_BITRATE=48000 -+ -+# -+# System on Chip audio support -+# -+# CONFIG_SND_SOC is not set -+ -+# -+# Open Sound System -+# -+# CONFIG_SOUND_PRIME is not set -+ -+# -+# HID Devices -+# -+# CONFIG_HID is not set -  - # - # USB support -@@ -545,21 +751,59 @@ CONFIG_UNIX98_PTYS=y - # - # USB Gadget Support - # --# CONFIG_USB_GADGET is not set --# CONFIG_MMC is not set -+CONFIG_USB_GADGET=y -+# CONFIG_USB_GADGET_DEBUG_FILES is not set -+CONFIG_USB_GADGET_SELECTED=y -+# CONFIG_USB_GADGET_FSL_USB2 is not set -+# CONFIG_USB_GADGET_NET2280 is not set -+# CONFIG_USB_GADGET_PXA2XX is not set -+# CONFIG_USB_GADGET_GOKU is not set -+# CONFIG_USB_GADGET_LH7A40X is not set -+CONFIG_USB_GADGET_ATMEL_USBA=y -+CONFIG_USB_ATMEL_USBA=y -+# CONFIG_USB_GADGET_OMAP is not set -+# CONFIG_USB_GADGET_AT91 is not set -+# CONFIG_USB_GADGET_DUMMY_HCD is not set -+CONFIG_USB_GADGET_DUALSPEED=y -+CONFIG_USB_ZERO=m -+CONFIG_USB_ETH=m -+CONFIG_USB_ETH_RNDIS=y -+CONFIG_USB_GADGETFS=m -+CONFIG_USB_FILE_STORAGE=m -+# CONFIG_USB_FILE_STORAGE_TEST is not set -+CONFIG_USB_G_SERIAL=m -+# CONFIG_USB_MIDI_GADGET is not set -+CONFIG_MMC=y -+# CONFIG_MMC_DEBUG is not set -+# CONFIG_MMC_UNSAFE_RESUME is not set -+ -+# -+# MMC/SD Card Drivers -+# -+CONFIG_MMC_BLOCK=y -+ -+# -+# MMC/SD Host Controller Drivers -+# -+CONFIG_MMC_ATMELMCI=y -  - # - # LED devices - # --# CONFIG_NEW_LEDS is not set -+CONFIG_NEW_LEDS=y -+CONFIG_LEDS_CLASS=m -  - # - # LED drivers - # -+CONFIG_LEDS_GPIO=m -  - # - # LED Triggers - # -+CONFIG_LEDS_TRIGGERS=y -+CONFIG_LEDS_TRIGGER_TIMER=m -+CONFIG_LEDS_TRIGGER_HEARTBEAT=m -  - # - # InfiniBand support -@@ -572,7 +816,50 @@ CONFIG_UNIX98_PTYS=y - # - # Real Time Clock - # --# CONFIG_RTC_CLASS is not set -+CONFIG_RTC_LIB=y -+CONFIG_RTC_CLASS=y -+# CONFIG_RTC_HCTOSYS is not set -+# CONFIG_RTC_DEBUG is not set -+ -+# -+# RTC interfaces -+# -+CONFIG_RTC_INTF_SYSFS=y -+CONFIG_RTC_INTF_PROC=y -+CONFIG_RTC_INTF_DEV=y -+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set -+# CONFIG_RTC_DRV_TEST is not set -+ -+# -+# I2C RTC drivers -+# -+# CONFIG_RTC_DRV_DS1307 is not set -+# CONFIG_RTC_DRV_DS1672 is not set -+# CONFIG_RTC_DRV_MAX6900 is not set -+# CONFIG_RTC_DRV_RS5C372 is not set -+# CONFIG_RTC_DRV_ISL1208 is not set -+# CONFIG_RTC_DRV_X1205 is not set -+# CONFIG_RTC_DRV_PCF8563 is not set -+# CONFIG_RTC_DRV_PCF8583 is not set -+ -+# -+# SPI RTC drivers -+# -+# CONFIG_RTC_DRV_RS5C348 is not set -+# CONFIG_RTC_DRV_MAX6902 is not set -+ -+# -+# Platform RTC drivers -+# -+# CONFIG_RTC_DRV_DS1553 is not set -+# CONFIG_RTC_DRV_DS1742 is not set -+# CONFIG_RTC_DRV_M48T86 is not set -+# CONFIG_RTC_DRV_V3020 is not set -+ -+# -+# on-CPU RTC drivers -+# -+CONFIG_RTC_DRV_AT32AP700X=y -  - # - # DMA Engine support -@@ -590,11 +877,14 @@ CONFIG_UNIX98_PTYS=y - # - # File systems - # --CONFIG_EXT2_FS=m -+CONFIG_EXT2_FS=y - # CONFIG_EXT2_FS_XATTR is not set - # CONFIG_EXT2_FS_XIP is not set --# CONFIG_EXT3_FS is not set -+CONFIG_EXT3_FS=y -+# CONFIG_EXT3_FS_XATTR is not set - # CONFIG_EXT4DEV_FS is not set -+CONFIG_JBD=y -+# CONFIG_JBD_DEBUG is not set - # CONFIG_REISERFS_FS is not set - # CONFIG_JFS_FS is not set - # CONFIG_FS_POSIX_ACL is not set -@@ -609,7 +899,7 @@ CONFIG_INOTIFY_USER=y - # CONFIG_DNOTIFY is not set - # CONFIG_AUTOFS_FS is not set - # CONFIG_AUTOFS4_FS is not set --# CONFIG_FUSE_FS is not set -+CONFIG_FUSE_FS=m -  - # - # CD-ROM/DVD Filesystems -@@ -638,7 +928,7 @@ CONFIG_TMPFS=y - # CONFIG_TMPFS_POSIX_ACL is not set - # CONFIG_HUGETLB_PAGE is not set - CONFIG_RAMFS=y --CONFIG_CONFIGFS_FS=m -+CONFIG_CONFIGFS_FS=y -  - # - # Miscellaneous filesystems -@@ -683,8 +973,14 @@ CONFIG_SUNRPC=y - # CONFIG_SUNRPC_BIND34 is not set - # CONFIG_RPCSEC_GSS_KRB5 is not set - # CONFIG_RPCSEC_GSS_SPKM3 is not set --# CONFIG_SMB_FS is not set --# CONFIG_CIFS is not set -+CONFIG_SMB_FS=m -+# CONFIG_SMB_NLS_DEFAULT is not set -+CONFIG_CIFS=m -+# CONFIG_CIFS_STATS is not set -+# CONFIG_CIFS_WEAK_PW_HASH is not set -+# CONFIG_CIFS_XATTR is not set -+# CONFIG_CIFS_DEBUG2 is not set -+# CONFIG_CIFS_EXPERIMENTAL is not set - # CONFIG_NCP_FS is not set - # CONFIG_CODA_FS is not set - # CONFIG_AFS_FS is not set -diff --git a/arch/avr32/drivers/Makefile b/arch/avr32/drivers/Makefile -new file mode 100644 -index 0000000..b429b75 ---- /dev/null -+++ b/arch/avr32/drivers/Makefile -@@ -0,0 +1 @@ -+obj-$(CONFIG_DW_DMAC)			+= dw-dmac.o -diff --git a/arch/avr32/drivers/dw-dmac.c b/arch/avr32/drivers/dw-dmac.c -new file mode 100644 -index 0000000..224eb30 ---- /dev/null -+++ b/arch/avr32/drivers/dw-dmac.c -@@ -0,0 +1,761 @@ -+/* -+ * Driver for the Synopsys DesignWare DMA Controller -+ * -+ * Copyright (C) 2005-2006 Atmel Corporation -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+#include <linux/clk.h> -+#include <linux/device.h> -+#include <linux/dma-mapping.h> -+#include <linux/dmapool.h> -+#include <linux/init.h> -+#include <linux/interrupt.h> -+#include <linux/module.h> -+#include <linux/platform_device.h> -+ -+#include <asm/dma-controller.h> -+#include <asm/io.h> -+ -+#include "dw-dmac.h" -+ -+#define DMAC_NR_CHANNELS 3 -+#define DMAC_MAX_BLOCKSIZE 4095 -+ -+enum { -+	CH_STATE_FREE = 0, -+	CH_STATE_ALLOCATED, -+	CH_STATE_BUSY, -+}; -+ -+struct dw_dma_lli { -+	dma_addr_t	sar; -+	dma_addr_t	dar; -+	dma_addr_t	llp; -+	u32		ctllo; -+	u32		ctlhi; -+	u32		sstat; -+	u32		dstat; -+}; -+ -+struct dw_dma_block { -+	struct dw_dma_lli *lli_vaddr; -+	dma_addr_t lli_dma_addr; -+}; -+ -+struct dw_dma_channel { -+	unsigned int state; -+        int is_cyclic; -+	struct dma_request_sg *req_sg; -+	struct dma_request_cyclic *req_cyclic; -+	unsigned int nr_blocks; -+	int direction; -+	struct dw_dma_block *block; -+}; -+ -+struct dw_dma_controller { -+	spinlock_t lock; -+	void * __iomem	regs; -+	struct dma_pool *lli_pool; -+	struct clk *hclk; -+	struct dma_controller dma; -+	struct dw_dma_channel channel[DMAC_NR_CHANNELS]; -+}; -+#define to_dw_dmac(dmac) container_of(dmac, struct dw_dma_controller, dma) -+ -+#define dmac_writel_hi(dmac, reg, value) \ -+	__raw_writel((value), (dmac)->regs + DW_DMAC_##reg + 4) -+#define dmac_readl_hi(dmac, reg) \ -+	__raw_readl((dmac)->regs + DW_DMAC_##reg + 4) -+#define dmac_writel_lo(dmac, reg, value) \ -+	__raw_writel((value), (dmac)->regs + DW_DMAC_##reg) -+#define dmac_readl_lo(dmac, reg) \ -+	__raw_readl((dmac)->regs + DW_DMAC_##reg) -+#define dmac_chan_writel_hi(dmac, chan, reg, value) \ -+	__raw_writel((value), ((dmac)->regs + 0x58 * (chan) \ -+			       + DW_DMAC_CHAN_##reg + 4)) -+#define dmac_chan_readl_hi(dmac, chan, reg) \ -+	__raw_readl((dmac)->regs + 0x58 * (chan) + DW_DMAC_CHAN_##reg + 4) -+#define dmac_chan_writel_lo(dmac, chan, reg, value) \ -+	__raw_writel((value), (dmac)->regs + 0x58 * (chan) + DW_DMAC_CHAN_##reg) -+#define dmac_chan_readl_lo(dmac, chan, reg) \ -+	__raw_readl((dmac)->regs + 0x58 * (chan) + DW_DMAC_CHAN_##reg) -+#define set_channel_bit(dmac, reg, chan) \ -+	dmac_writel_lo(dmac, reg, (1 << (chan)) | (1 << ((chan) + 8))) -+#define clear_channel_bit(dmac, reg, chan) \ -+	dmac_writel_lo(dmac, reg, (0 << (chan)) | (1 << ((chan) + 8))) -+ -+static int dmac_alloc_channel(struct dma_controller *_dmac) -+{ -+	struct dw_dma_controller *dmac = to_dw_dmac(_dmac); -+	struct dw_dma_channel *chan; -+	unsigned long flags; -+	int i; -+ -+	spin_lock_irqsave(&dmac->lock, flags); -+	for (i = 0; i < DMAC_NR_CHANNELS; i++) -+		if (dmac->channel[i].state == CH_STATE_FREE) -+			break; -+ -+	if (i < DMAC_NR_CHANNELS) { -+		chan = &dmac->channel[i]; -+		chan->state = CH_STATE_ALLOCATED; -+	} else { -+		i = -EBUSY; -+	} -+ -+	spin_unlock_irqrestore(&dmac->lock, flags); -+ -+	return i; -+} -+ -+static void dmac_release_channel(struct dma_controller *_dmac, int channel) -+{ -+	struct dw_dma_controller *dmac = to_dw_dmac(_dmac); -+ -+	BUG_ON(channel >= DMAC_NR_CHANNELS -+	       || dmac->channel[channel].state != CH_STATE_ALLOCATED); -+ -+	dmac->channel[channel].state = CH_STATE_FREE; -+} -+ -+static struct dw_dma_block *allocate_blocks(struct dw_dma_controller *dmac, -+					    unsigned int nr_blocks) -+{ -+	struct dw_dma_block *block; -+	void *p; -+	unsigned int i; -+ -+	block = kmalloc(nr_blocks * sizeof(*block), -+			GFP_KERNEL); -+	if (unlikely(!block)) -+		return NULL; -+ -+	for (i = 0; i < nr_blocks; i++) { -+		p = dma_pool_alloc(dmac->lli_pool, GFP_KERNEL, -+				   &block[i].lli_dma_addr); -+		block[i].lli_vaddr = p; -+		if (unlikely(!p)) -+			goto fail; -+	} -+ -+	return block; -+ -+fail: -+	for (i = 0; i < nr_blocks; i++) { -+		if (!block[i].lli_vaddr) -+			break; -+		dma_pool_free(dmac->lli_pool, block[i].lli_vaddr, -+			      block[i].lli_dma_addr); -+	} -+	kfree(block); -+	return NULL; -+} -+ -+static void cleanup_channel(struct dw_dma_controller *dmac, -+			    struct dw_dma_channel *chan) -+{ -+	unsigned int i; -+ -+	if (chan->nr_blocks > 1) { -+		for (i = 0; i < chan->nr_blocks; i++) -+			dma_pool_free(dmac->lli_pool, chan->block[i].lli_vaddr, -+				      chan->block[i].lli_dma_addr); -+		kfree(chan->block); -+	} -+ -+	chan->state = CH_STATE_ALLOCATED; -+} -+ -+static int dmac_prepare_request_sg(struct dma_controller *_dmac, -+				   struct dma_request_sg *req) -+{ -+	struct dw_dma_controller *dmac = to_dw_dmac(_dmac); -+	struct dw_dma_channel *chan; -+	unsigned long ctlhi, ctllo, cfghi, cfglo; -+	unsigned long block_size; -+	unsigned int nr_blocks; -+	int ret, i, direction; -+	unsigned long flags; -+ -+	spin_lock_irqsave(&dmac->lock, flags); -+ -+	ret = -EINVAL; -+	if (req->req.channel >= DMAC_NR_CHANNELS -+	    || dmac->channel[req->req.channel].state != CH_STATE_ALLOCATED -+	    || req->block_size > DMAC_MAX_BLOCKSIZE) { -+		spin_unlock_irqrestore(&dmac->lock, flags); -+		return -EINVAL; -+	} -+ -+	chan = &dmac->channel[req->req.channel]; -+	chan->state = CH_STATE_BUSY; -+	chan->req_sg = req; -+	chan->is_cyclic = 0; -+ -+	/* -+	 * We have marked the channel as busy, so no need to keep the -+	 * lock as long as we only touch the channel-specific -+	 * registers -+	 */ -+	spin_unlock_irqrestore(&dmac->lock, flags); -+ -+	/* -+	 * There may be limitations in the driver and/or the DMA -+	 * controller that prevents us from sending a whole -+	 * scatterlist item in one go.  Taking this into account, -+	 * calculate the number of block transfers we need to set up. -+	 * -+	 * FIXME: Let the peripheral driver know about the maximum -+	 * block size we support. We really don't want to use a -+	 * different block size than what was suggested by the -+	 * peripheral. -+	 * -+	 * Each block will get its own Linked List Item (LLI) below. -+	 */ -+	block_size = req->block_size; -+	nr_blocks = req->nr_blocks; -+	pr_debug("block_size %lu, nr_blocks %u nr_sg = %u\n", -+		 block_size, nr_blocks, req->nr_sg); -+ -+	BUG_ON(nr_blocks == 0); -+	chan->nr_blocks = nr_blocks; -+ -+	ret = -EINVAL; -+	cfglo = cfghi = 0; -+	switch (req->direction) { -+	case DMA_DIR_MEM_TO_PERIPH: -+		direction = DMA_TO_DEVICE; -+		cfghi = req->periph_id << (43 - 32); -+		break; -+ -+	case DMA_DIR_PERIPH_TO_MEM: -+		direction = DMA_FROM_DEVICE; -+		cfghi = req->periph_id << (39 - 32); -+		break; -+	default: -+		goto out_unclaim_channel; -+	} -+ -+        chan->direction = direction; -+ -+	dmac_chan_writel_hi(dmac, req->req.channel, CFG, cfghi); -+	dmac_chan_writel_lo(dmac, req->req.channel, CFG, cfglo); -+ -+	ctlhi = block_size >> req->width; -+	ctllo = ((req->direction << 20) -+		 // | (1 << 14) | (1 << 11) // source/dest burst trans len -+		 | (req->width << 4) | (req->width << 1) -+		 | (1 << 0));		 // interrupt enable -+ -+	if (nr_blocks == 1) { -+		/* Only one block: No need to use block chaining */ -+		if (direction == DMA_TO_DEVICE) { -+			dmac_chan_writel_lo(dmac, req->req.channel, SAR, -+					    req->sg->dma_address); -+			dmac_chan_writel_lo(dmac, req->req.channel, DAR, -+					    req->data_reg); -+			ctllo |= 2 << 7; // no dst increment -+		} else { -+			dmac_chan_writel_lo(dmac, req->req.channel, SAR, -+					    req->data_reg); -+			dmac_chan_writel_lo(dmac, req->req.channel, DAR, -+					    req->sg->dma_address); -+			ctllo |= 2 << 9; // no src increment -+		} -+		dmac_chan_writel_lo(dmac, req->req.channel, CTL, ctllo); -+		dmac_chan_writel_hi(dmac, req->req.channel, CTL, ctlhi); -+		pr_debug("ctl hi:lo 0x%lx:%lx\n", ctlhi, ctllo); -+	} else { -+		struct dw_dma_lli *lli, *lli_prev = NULL; -+		int j = 0, offset = 0; -+ -+		ret = -ENOMEM; -+		chan->block = allocate_blocks(dmac, nr_blocks); -+		if (!chan->block) -+			goto out_unclaim_channel; -+ -+		if (direction == DMA_TO_DEVICE) -+			ctllo |= 1 << 28 | 1 << 27 | 2 << 7; -+		else -+			ctllo |= 1 << 28 | 1 << 27 | 2 << 9; -+ -+		/* -+		 * Map scatterlist items to blocks. One scatterlist -+		 * item may need more than one block for the reasons -+		 * mentioned above. -+		 */ -+		for (i = 0; i < nr_blocks; i++) { -+			lli = chan->block[i].lli_vaddr; -+			if (lli_prev) { -+				lli_prev->llp = chan->block[i].lli_dma_addr; -+				pr_debug("lli[%d] (0x%p/0x%x): 0x%x 0x%x 0x%x 0x%x 0x%x\n", -+					 i - 1, chan->block[i - 1].lli_vaddr, -+					 chan->block[i - 1].lli_dma_addr, -+					 lli_prev->sar, lli_prev->dar, lli_prev->llp, -+					 lli_prev->ctllo, lli_prev->ctlhi); -+			} -+			lli->llp = 0; -+			lli->ctllo = ctllo; -+			lli->ctlhi = ctlhi; -+			if (direction == DMA_TO_DEVICE) { -+				lli->sar = req->sg[j].dma_address + offset; -+				lli->dar = req->data_reg; -+			} else { -+				lli->sar = req->data_reg; -+				lli->dar = req->sg[j].dma_address + offset; -+			} -+			lli_prev = lli; -+ -+			offset += block_size; -+			if (offset > req->sg[j].length) { -+				j++; -+				offset = 0; -+			} -+		} -+ -+		pr_debug("lli[%d] (0x%p/0x%x): 0x%x 0x%x 0x%x 0x%x 0x%x\n", -+			 i - 1, chan->block[i - 1].lli_vaddr, -+			 chan->block[i - 1].lli_dma_addr, lli_prev->sar, -+			 lli_prev->dar, lli_prev->llp, -+			 lli_prev->ctllo, lli_prev->ctlhi); -+ -+		/* -+		 * SAR, DAR and CTL are initialized from the LLI. We -+		 * only have to enable the LLI bits in CTL. -+		 */ -+		dmac_chan_writel_hi(dmac, req->req.channel, CTL, 0); -+		dmac_chan_writel_lo(dmac, req->req.channel, LLP, -+				    chan->block[0].lli_dma_addr); -+		dmac_chan_writel_lo(dmac, req->req.channel, CTL, 1 << 28 | 1 << 27); -+	} -+ -+	set_channel_bit(dmac, MASK_XFER, req->req.channel); -+	set_channel_bit(dmac, MASK_ERROR, req->req.channel); -+	if (req->req.block_complete) -+		set_channel_bit(dmac, MASK_BLOCK, req->req.channel); -+	else -+		clear_channel_bit(dmac, MASK_BLOCK, req->req.channel); -+ -+	return 0; -+ -+out_unclaim_channel: -+	chan->state = CH_STATE_ALLOCATED; -+	return ret; -+} -+ -+static int dmac_prepare_request_cyclic(struct dma_controller *_dmac, -+                                       struct dma_request_cyclic *req) -+{ -+	struct dw_dma_controller *dmac = to_dw_dmac(_dmac); -+	struct dw_dma_channel *chan; -+	unsigned long ctlhi, ctllo, cfghi, cfglo; -+	unsigned long block_size; -+	int ret, i, direction; -+	unsigned long flags; -+ -+	spin_lock_irqsave(&dmac->lock, flags); -+ -+        block_size = (req->buffer_size/req->periods) >> req->width; -+ -+	ret = -EINVAL; -+	if (req->req.channel >= DMAC_NR_CHANNELS -+	    || dmac->channel[req->req.channel].state != CH_STATE_ALLOCATED -+            || (req->periods == 0) -+	    || block_size > DMAC_MAX_BLOCKSIZE) { -+		spin_unlock_irqrestore(&dmac->lock, flags); -+		return -EINVAL; -+	} -+ -+	chan = &dmac->channel[req->req.channel]; -+	chan->state = CH_STATE_BUSY; -+	chan->is_cyclic = 1; -+        chan->req_cyclic = req; -+ -+	/* -+	 * We have marked the channel as busy, so no need to keep the -+	 * lock as long as we only touch the channel-specific -+	 * registers -+	 */ -+	spin_unlock_irqrestore(&dmac->lock, flags); -+ -+	/* -+          Setup -+	 */ -+	BUG_ON(req->buffer_size % req->periods); -+	/* printk(KERN_INFO "block_size = %lu, periods = %u\n", block_size, req->periods); */ -+ -+	chan->nr_blocks = req->periods; -+ -+	ret = -EINVAL; -+	cfglo = cfghi = 0; -+	switch (req->direction) { -+	case DMA_DIR_MEM_TO_PERIPH: -+		direction = DMA_TO_DEVICE; -+		cfghi = req->periph_id << (43 - 32); -+		break; -+ -+	case DMA_DIR_PERIPH_TO_MEM: -+		direction = DMA_FROM_DEVICE; -+		cfghi = req->periph_id << (39 - 32); -+		break; -+	default: -+		goto out_unclaim_channel; -+	} -+ -+        chan->direction = direction; -+ -+	dmac_chan_writel_hi(dmac, req->req.channel, CFG, cfghi); -+	dmac_chan_writel_lo(dmac, req->req.channel, CFG, cfglo); -+ -+	ctlhi = block_size; -+	ctllo = ((req->direction << 20) -+		 | (req->width << 4) | (req->width << 1) -+		 | (1 << 0));		 // interrupt enable -+ -+        { -+		struct dw_dma_lli *lli = NULL, *lli_prev = NULL; -+ -+		ret = -ENOMEM; -+		chan->block = allocate_blocks(dmac, req->periods); -+		if (!chan->block) -+			goto out_unclaim_channel; -+ -+		if (direction == DMA_TO_DEVICE) -+			ctllo |= 1 << 28 | 1 << 27 | 2 << 7; -+		else -+			ctllo |= 1 << 28 | 1 << 27 | 2 << 9; -+ -+		/* -+		 * Set up a linked list items where each period gets -+		 * an item. The linked list item for the last period -+		 * points back to the star of the buffer making a -+		 * cyclic buffer. -+		 */ -+		for (i = 0; i < req->periods; i++) { -+			lli = chan->block[i].lli_vaddr; -+			if (lli_prev) { -+				lli_prev->llp = chan->block[i].lli_dma_addr; -+				/* printk(KERN_INFO "lli[%d] (0x%p/0x%x): 0x%x 0x%x 0x%x 0x%x 0x%x\n", -+				   i - 1, chan->block[i - 1].lli_vaddr, -+				   chan->block[i - 1].lli_dma_addr, -+				   lli_prev->sar, lli_prev->dar, lli_prev->llp, -+				   lli_prev->ctllo, lli_prev->ctlhi);*/ -+			} -+			lli->llp = 0; -+			lli->ctllo = ctllo; -+			lli->ctlhi = ctlhi; -+			if (direction == DMA_TO_DEVICE) { -+				lli->sar = req->buffer_start + i*(block_size << req->width); -+				lli->dar = req->data_reg; -+			} else { -+				lli->sar = req->data_reg; -+				lli->dar = req->buffer_start + i*(block_size << req->width); -+			} -+			lli_prev = lli; -+		} -+		lli->llp = chan->block[0].lli_dma_addr; -+ -+		/*printk(KERN_INFO "lli[%d] (0x%p/0x%x): 0x%x 0x%x 0x%x 0x%x 0x%x\n", -+		  i - 1, chan->block[i - 1].lli_vaddr, -+		  chan->block[i - 1].lli_dma_addr, lli_prev->sar, -+		  lli_prev->dar, lli_prev->llp, -+		  lli_prev->ctllo, lli_prev->ctlhi); */ -+ -+		/* -+		 * SAR, DAR and CTL are initialized from the LLI. We -+		 * only have to enable the LLI bits in CTL. -+		 */ -+		dmac_chan_writel_lo(dmac, req->req.channel, LLP, -+				    chan->block[0].lli_dma_addr); -+		dmac_chan_writel_lo(dmac, req->req.channel, CTL, 1 << 28 | 1 << 27); -+	} -+ -+	clear_channel_bit(dmac, MASK_XFER, req->req.channel); -+	set_channel_bit(dmac, MASK_ERROR, req->req.channel); -+	if (req->req.block_complete) -+		set_channel_bit(dmac, MASK_BLOCK, req->req.channel); -+	else -+		clear_channel_bit(dmac, MASK_BLOCK, req->req.channel); -+ -+	return 0; -+ -+out_unclaim_channel: -+	chan->state = CH_STATE_ALLOCATED; -+	return ret; -+} -+ -+static int dmac_start_request(struct dma_controller *_dmac, -+			      unsigned int channel) -+{ -+	struct dw_dma_controller *dmac = to_dw_dmac(_dmac); -+ -+	BUG_ON(channel >= DMAC_NR_CHANNELS); -+ -+	set_channel_bit(dmac, CH_EN, channel); -+ -+	return 0; -+} -+ -+static dma_addr_t dmac_get_current_pos(struct dma_controller *_dmac, -+                                       unsigned int channel) -+{ -+	struct dw_dma_controller *dmac = to_dw_dmac(_dmac); -+	struct dw_dma_channel *chan; -+        dma_addr_t current_pos; -+ -+	BUG_ON(channel >= DMAC_NR_CHANNELS); -+ -+        chan = &dmac->channel[channel]; -+ -+	switch (chan->direction) { -+	case DMA_TO_DEVICE: -+		current_pos = dmac_chan_readl_lo(dmac, channel, SAR); -+		break; -+	case DMA_FROM_DEVICE: -+		current_pos = dmac_chan_readl_lo(dmac, channel, DAR); -+		break; -+	default: -+		return 0; -+	} -+ -+ -+        if (!current_pos) { -+		if (chan->is_cyclic) { -+			current_pos = chan->req_cyclic->buffer_start; -+		} else { -+			current_pos = chan->req_sg->sg->dma_address; -+		} -+	} -+ -+	return current_pos; -+} -+ -+ -+static int dmac_stop_request(struct dma_controller *_dmac, -+                             unsigned int channel) -+{ -+	struct dw_dma_controller *dmac = to_dw_dmac(_dmac); -+	struct dw_dma_channel *chan; -+ -+	BUG_ON(channel >= DMAC_NR_CHANNELS); -+ -+	chan = &dmac->channel[channel]; -+	pr_debug("stop: st%u s%08x d%08x l%08x ctl0x%08x:0x%08x\n", -+		 chan->state, dmac_chan_readl_lo(dmac, channel, SAR), -+		 dmac_chan_readl_lo(dmac, channel, DAR), -+		 dmac_chan_readl_lo(dmac, channel, LLP), -+		 dmac_chan_readl_hi(dmac, channel, CTL), -+		 dmac_chan_readl_lo(dmac, channel, CTL)); -+ -+	if (chan->state == CH_STATE_BUSY) { -+		clear_channel_bit(dmac, CH_EN, channel); -+		cleanup_channel(dmac, &dmac->channel[channel]); -+	} -+ -+	return 0; -+} -+ -+ -+static void dmac_block_complete(struct dw_dma_controller *dmac) -+{ -+	struct dw_dma_channel *chan; -+	unsigned long status, chanid; -+ -+	status = dmac_readl_lo(dmac, STATUS_BLOCK); -+ -+	while (status) { -+		struct dma_request *req; -+		chanid = __ffs(status); -+		chan = &dmac->channel[chanid]; -+ -+                if (chan->is_cyclic) { -+			BUG_ON(!chan->req_cyclic -+			       || !chan->req_cyclic->req.block_complete); -+			req = &chan->req_cyclic->req; -+                } else { -+			BUG_ON(!chan->req_sg || !chan->req_sg->req.block_complete); -+			req = &chan->req_sg->req; -+                } -+		dmac_writel_lo(dmac, CLEAR_BLOCK, 1 << chanid); -+		req->block_complete(req); -+		status = dmac_readl_lo(dmac, STATUS_BLOCK); -+	} -+} -+ -+static void dmac_xfer_complete(struct dw_dma_controller *dmac) -+{ -+	struct dw_dma_channel *chan; -+	struct dma_request *req; -+	unsigned long status, chanid; -+ -+	status = dmac_readl_lo(dmac, STATUS_XFER); -+ -+	while (status) { -+		chanid = __ffs(status); -+		chan = &dmac->channel[chanid]; -+ -+		dmac_writel_lo(dmac, CLEAR_XFER, 1 << chanid); -+ -+                req = &chan->req_sg->req; -+                BUG_ON(!req); -+                cleanup_channel(dmac, chan); -+                if (req->xfer_complete) -+			req->xfer_complete(req); -+ -+		status = dmac_readl_lo(dmac, STATUS_XFER); -+	} -+} -+ -+static void dmac_error(struct dw_dma_controller *dmac) -+{ -+	struct dw_dma_channel *chan; -+	unsigned long status, chanid; -+ -+	status = dmac_readl_lo(dmac, STATUS_ERROR); -+ -+	while (status) { -+		struct dma_request *req; -+ -+		chanid = __ffs(status); -+		chan = &dmac->channel[chanid]; -+ -+		dmac_writel_lo(dmac, CLEAR_ERROR, 1 << chanid); -+		clear_channel_bit(dmac, CH_EN, chanid); -+ -+                if (chan->is_cyclic) { -+			BUG_ON(!chan->req_cyclic); -+			req = &chan->req_cyclic->req; -+                } else { -+			BUG_ON(!chan->req_sg); -+			req = &chan->req_sg->req; -+                } -+ -+		cleanup_channel(dmac, chan); -+		if (req->error) -+			req->error(req); -+ -+		status = dmac_readl_lo(dmac, STATUS_XFER); -+	} -+} -+ -+static irqreturn_t dmac_interrupt(int irq, void *dev_id) -+{ -+	struct dw_dma_controller *dmac = dev_id; -+	unsigned long status; -+	int ret = IRQ_NONE; -+ -+	spin_lock(&dmac->lock); -+ -+	status = dmac_readl_lo(dmac, STATUS_INT); -+ -+	while (status) { -+		ret = IRQ_HANDLED; -+		if (status & 0x10) -+			dmac_error(dmac); -+		if (status & 0x02) -+			dmac_block_complete(dmac); -+		if (status & 0x01) -+			dmac_xfer_complete(dmac); -+ -+		status = dmac_readl_lo(dmac, STATUS_INT); -+	} -+ -+	spin_unlock(&dmac->lock); -+	return ret; -+} -+ -+static int __devinit dmac_probe(struct platform_device *pdev) -+{ -+	struct dw_dma_controller *dmac; -+	struct resource *regs; -+	int ret; -+ -+	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+	if (!regs) -+		return -ENXIO; -+ -+	dmac = kmalloc(sizeof(*dmac), GFP_KERNEL); -+	if (!dmac) -+		return -ENOMEM; -+	memset(dmac, 0, sizeof(*dmac)); -+ -+	dmac->hclk = clk_get(&pdev->dev, "hclk"); -+	if (IS_ERR(dmac->hclk)) { -+		ret = PTR_ERR(dmac->hclk); -+		goto out_free_dmac; -+	} -+	clk_enable(dmac->hclk); -+ -+	ret = -ENOMEM; -+	dmac->lli_pool = dma_pool_create("dmac", &pdev->dev, -+					 sizeof(struct dw_dma_lli), 4, 0); -+	if (!dmac->lli_pool) -+		goto out_disable_clk; -+ -+	spin_lock_init(&dmac->lock); -+	dmac->dma.dev = &pdev->dev; -+	dmac->dma.alloc_channel = dmac_alloc_channel; -+	dmac->dma.release_channel = dmac_release_channel; -+	dmac->dma.prepare_request_sg = dmac_prepare_request_sg; -+	dmac->dma.prepare_request_cyclic = dmac_prepare_request_cyclic; -+	dmac->dma.start_request = dmac_start_request; -+	dmac->dma.stop_request = dmac_stop_request; -+	dmac->dma.get_current_pos = dmac_get_current_pos; -+ -+	dmac->regs = ioremap(regs->start, regs->end - regs->start + 1); -+	if (!dmac->regs) -+		goto out_free_pool; -+ -+	ret = request_irq(platform_get_irq(pdev, 0), dmac_interrupt, -+			  IRQF_SAMPLE_RANDOM, pdev->name, dmac); -+	if (ret) -+		goto out_unmap_regs; -+ -+	/* Enable the DMA controller */ -+	dmac_writel_lo(dmac, CFG, 1); -+ -+	register_dma_controller(&dmac->dma); -+ -+	printk(KERN_INFO -+	       "dmac%d: DesignWare DMA controller at 0x%p irq %d\n", -+	       dmac->dma.id, dmac->regs, platform_get_irq(pdev, 0)); -+ -+	return 0; -+ -+out_unmap_regs: -+	iounmap(dmac->regs); -+out_free_pool: -+	dma_pool_destroy(dmac->lli_pool); -+out_disable_clk: -+	clk_disable(dmac->hclk); -+	clk_put(dmac->hclk); -+out_free_dmac: -+	kfree(dmac); -+	return ret; -+} -+ -+static struct platform_driver dmac_driver = { -+	.probe		= dmac_probe, -+	.driver		= { -+		.name		= "dmaca", -+	}, -+}; -+ -+static int __init dmac_init(void) -+{ -+	return platform_driver_register(&dmac_driver); -+} -+subsys_initcall(dmac_init); -+ -+static void __exit dmac_exit(void) -+{ -+	platform_driver_unregister(&dmac_driver); -+} -+module_exit(dmac_exit); -+ -+MODULE_DESCRIPTION("Synopsys DesignWare DMA Controller driver"); -+MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>"); -+MODULE_LICENSE("GPL"); -diff --git a/arch/avr32/drivers/dw-dmac.h b/arch/avr32/drivers/dw-dmac.h -new file mode 100644 -index 0000000..1f67921 ---- /dev/null -+++ b/arch/avr32/drivers/dw-dmac.h -@@ -0,0 +1,42 @@ -+/* -+ * Driver for the Synopsys DesignWare DMA Controller -+ * -+ * Copyright (C) 2005-2006 Atmel Corporation -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+#ifndef __AVR32_DW_DMAC_H__ -+#define __AVR32_DW_DMAC_H__ -+ -+#define DW_DMAC_CFG		0x398 -+#define DW_DMAC_CH_EN		0x3a0 -+ -+#define DW_DMAC_STATUS_XFER	0x2e8 -+#define DW_DMAC_STATUS_BLOCK	0x2f0 -+#define DW_DMAC_STATUS_ERROR	0x308 -+ -+#define DW_DMAC_MASK_XFER	0x310 -+#define DW_DMAC_MASK_BLOCK	0x318 -+#define DW_DMAC_MASK_ERROR	0x330 -+ -+#define DW_DMAC_CLEAR_XFER	0x338 -+#define DW_DMAC_CLEAR_BLOCK	0x340 -+#define DW_DMAC_CLEAR_ERROR	0x358 -+ -+#define DW_DMAC_STATUS_INT	0x360 -+ -+#define DW_DMAC_CHAN_SAR	0x000 -+#define DW_DMAC_CHAN_DAR	0x008 -+#define DW_DMAC_CHAN_LLP	0x010 -+#define DW_DMAC_CHAN_CTL	0x018 -+#define DW_DMAC_CHAN_SSTAT	0x020 -+#define DW_DMAC_CHAN_DSTAT	0x028 -+#define DW_DMAC_CHAN_SSTATAR	0x030 -+#define DW_DMAC_CHAN_DSTATAR	0x038 -+#define DW_DMAC_CHAN_CFG	0x040 -+#define DW_DMAC_CHAN_SGR	0x048 -+#define DW_DMAC_CHAN_DSR	0x050 -+ -+#endif /* __AVR32_DW_DMAC_H__ */ -diff --git a/arch/avr32/kernel/Makefile b/arch/avr32/kernel/Makefile -index 90e5aff..b6afc0c 100644 ---- a/arch/avr32/kernel/Makefile -+++ b/arch/avr32/kernel/Makefile -@@ -9,6 +9,7 @@ obj-y				+= syscall_table.o syscall-stubs.o irq.o - obj-y				+= setup.o traps.o semaphore.o ptrace.o - obj-y				+= signal.o sys_avr32.o process.o time.o - obj-y				+= init_task.o switch_to.o cpu.o -+obj-y				+= dma-controller.o - obj-$(CONFIG_MODULES)		+= module.o avr32_ksyms.o - obj-$(CONFIG_KPROBES)		+= kprobes.o -  -diff --git a/arch/avr32/kernel/dma-controller.c b/arch/avr32/kernel/dma-controller.c -new file mode 100644 -index 0000000..fb654b3 ---- /dev/null -+++ b/arch/avr32/kernel/dma-controller.c -@@ -0,0 +1,34 @@ -+/* -+ * Preliminary DMA controller framework for AVR32 -+ * -+ * Copyright (C) 2005-2006 Atmel Corporation -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+#include <asm/dma-controller.h> -+ -+static LIST_HEAD(controllers); -+ -+int register_dma_controller(struct dma_controller *dmac) -+{ -+	static int next_id; -+ -+	dmac->id = next_id++; -+	list_add_tail(&dmac->list, &controllers); -+ -+	return 0; -+} -+EXPORT_SYMBOL(register_dma_controller); -+ -+struct dma_controller *find_dma_controller(int id) -+{ -+	struct dma_controller *dmac; -+ -+	list_for_each_entry(dmac, &controllers, list) -+		if (dmac->id == id) -+			return dmac; -+	return NULL; -+} -+EXPORT_SYMBOL(find_dma_controller); -diff --git a/arch/avr32/kernel/setup.c b/arch/avr32/kernel/setup.c -index b279d66..d08b0bc 100644 ---- a/arch/avr32/kernel/setup.c -+++ b/arch/avr32/kernel/setup.c -@@ -313,7 +313,7 @@ __tagtable(ATAG_MEM, parse_tag_mem); -  - static int __init parse_tag_rdimg(struct tag *tag) - { --#ifdef CONFIG_INITRD -+#ifdef CONFIG_BLK_DEV_INITRD - 	struct tag_mem_range *mem = &tag->u.mem_range; - 	int ret; -  -@@ -323,7 +323,7 @@ static int __init parse_tag_rdimg(struct tag *tag) - 		return 0; - 	} -  --	ret = add_reserved_region(mem->start, mem->start + mem->size - 1, -+	ret = add_reserved_region(mem->addr, mem->addr + mem->size - 1, - 				  "initrd"); - 	if (ret) { - 		printk(KERN_WARNING -diff --git a/arch/avr32/mach-at32ap/Kconfig b/arch/avr32/mach-at32ap/Kconfig -index eb30783..43c5b9f 100644 ---- a/arch/avr32/mach-at32ap/Kconfig -+++ b/arch/avr32/mach-at32ap/Kconfig -@@ -26,6 +26,13 @@ config AP7000_8_BIT_SMC -  - endchoice -  -+config GPIO_DEV -+	bool "GPIO /dev interface" -+	select CONFIGFS_FS -+	default n -+	help -+	  Say `Y' to enable a /dev interface to the GPIO pins. -+ - endmenu -  - endif # PLATFORM_AT32AP -diff --git a/arch/avr32/mach-at32ap/Makefile b/arch/avr32/mach-at32ap/Makefile -index f1d3957..250372a 100644 ---- a/arch/avr32/mach-at32ap/Makefile -+++ b/arch/avr32/mach-at32ap/Makefile -@@ -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 --git a/arch/avr32/mach-at32ap/at32ap.c b/arch/avr32/mach-at32ap/at32ap.c -index 90f207e..7c4987f 100644 ---- a/arch/avr32/mach-at32ap/at32ap.c -+++ b/arch/avr32/mach-at32ap/at32ap.c -@@ -11,41 +11,10 @@ - #include <linux/init.h> - #include <linux/platform_device.h> -  --#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; --} -  - void __init setup_platform(void) - { --	at32_sm_init(); - 	at32_clock_init(); - 	at32_portmux_init(); - } -diff --git a/arch/avr32/mach-at32ap/at32ap7000.c b/arch/avr32/mach-at32ap/at32ap7000.c -index 4dda42d..1130c8a 100644 ---- a/arch/avr32/mach-at32ap/at32ap7000.c -+++ b/arch/avr32/mach-at32ap/at32ap7000.c -@@ -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 <video/atmel_lcdc.h> -  - #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 -  - #define PBMEM(base)					\ - 	{						\ -@@ -88,6 +94,8 @@ static struct clk devname##_##_name = {				\ - 	.index		= _index,				\ - } -  -+static DEFINE_SPINLOCK(pm_lock); -+ - unsigned long at32ap7000_osc_rates[3] = { - 	[0] = 32768, - 	/* FIXME: these are ATSTK1002-specific */ -@@ -104,11 +112,11 @@ static unsigned long pll_get_rate(struct clk *clk, unsigned long control) - { - 	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 @@ static unsigned long pll0_get_rate(struct clk *clk) - { - 	u32 control; -  --	control = sm_readl(&system_manager, PM_PLL0); -+	control = pm_readl(PLL0); -  - 	return pll_get_rate(clk, control); - } -@@ -130,7 +138,7 @@ static unsigned long pll1_get_rate(struct clk *clk) - { - 	u32 control; -  --	control = sm_readl(&system_manager, PM_PLL1); -+	control = pm_readl(PLL1); -  - 	return pll_get_rate(clk, control); - } -@@ -187,108 +195,139 @@ static unsigned long bus_clk_get_rate(struct clk *clk, unsigned int shift) -  - static void cpu_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_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 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) -+{ -+	u32 control; -+	unsigned long parent_rate, child_div, actual_rate, div; -+ -+	parent_rate = clk->parent->get_rate(clk->parent); -+	control = pm_readl(CKSEL); -+ -+	if (control & PM_BIT(HSBDIV)) -+		child_div = 1 << (PM_BFEXT(HSBSEL, control) + 1); -+	else -+		child_div = 1; -+ -+	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)); -+	} -+ -+	pr_debug("clk %s: new rate %lu (actual rate %lu)\n", -+			clk->name, rate, actual_rate); -+ -+	if (apply) -+		pm_writel(CKSEL, control); -+ -+	return actual_rate; -+} -+ - 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); - } -  - static unsigned long hsb_clk_get_rate(struct clk *clk) - { - 	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); - } -  - 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); - } -  - static unsigned long pba_clk_get_rate(struct clk *clk) - { - 	unsigned long cksel, shift = 0; -  --	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; -  - 	return bus_clk_get_rate(clk, shift); - } -  - static void pbb_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_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); - } -  - static unsigned long pbb_clk_get_rate(struct clk *clk) - { - 	unsigned long cksel, shift = 0; -  --	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 bus_clk_get_rate(clk, shift); - } -@@ -296,6 +335,7 @@ static unsigned long pbb_clk_get_rate(struct clk *clk) - 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 @@ static void genclk_mode(struct clk *clk, int enabled) - { - 	u32 control; -  --	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); - } -  - static unsigned long genclk_get_rate(struct clk *clk) -@@ -340,9 +380,9 @@ static unsigned long genclk_get_rate(struct clk *clk) - 	u32 control; - 	unsigned long div = 1; -  --	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); -  - 	return clk->parent->get_rate(clk->parent) / div; - } -@@ -353,23 +393,22 @@ static long genclk_set_rate(struct clk *clk, unsigned long rate, int apply) - 	unsigned long parent_rate, actual_rate, div; -  - 	parent_rate = clk->parent->get_rate(clk->parent); --	control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index); -+	control = pm_readl(GCCTRL(clk->index)); -  - 	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)); - 	} -  --	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); -  - 	if (apply) --		sm_writel(&system_manager, PM_GCCTRL + 4 * clk->index, --			  control); -+		pm_writel(GCCTRL(clk->index), control); -  - 	return actual_rate; - } -@@ -378,24 +417,24 @@ int genclk_set_parent(struct clk *clk, struct clk *parent) - { - 	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; -  - 	if (parent == &pll0 || parent == &pll1) --		control |= SM_BIT(PLLSEL); -+		control |= PM_BIT(PLLSEL); - 	else --		control &= ~SM_BIT(PLLSEL); -+		control &= ~PM_BIT(PLLSEL); -  --	sm_writel(&system_manager, PM_GCCTRL + 4 * clk->index, control); -+	pm_writel(GCCTRL(clk->index), control); - 	clk->parent = parent; -  - 	return 0; -@@ -408,11 +447,11 @@ static void __init genclk_init_parent(struct clk *clk) -  - 	BUG_ON(clk->index > 7); -  --	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; -  - 	clk->parent = parent; - } -@@ -420,21 +459,53 @@ static void __init genclk_init_parent(struct clk *clk) - /* -------------------------------------------------------------------- -  *  System peripherals -  * -------------------------------------------------------------------- */ --static struct resource sm_resource[] = { --	PBMEM(0xfff00000), --	NAMED_IRQ(19, "eim"), --	NAMED_IRQ(20, "pm"), --	NAMED_IRQ(21, "rtc"), --}; --struct platform_device at32_sm_device = { --	.name		= "sm", --	.id		= 0, --	.resource	= sm_resource, --	.num_resources	= ARRAY_SIZE(sm_resource), -+static struct resource at32_pm0_resource[] = { -+	{ -+		.start	= 0xfff00000, -+		.end	= 0xfff0007f, -+		.flags	= IORESOURCE_MEM, -+	}, -+	IRQ(20), - }; --static struct clk at32_sm_pclk = { -+ -+static struct resource at32ap700x_rtc0_resource[] = { -+	{ -+		.start	= 0xfff00080, -+		.end	= 0xfff000af, -+		.flags	= IORESOURCE_MEM, -+	}, -+	IRQ(21), -+}; -+ -+static struct resource at32_wdt0_resource[] = { -+	{ -+		.start	= 0xfff000b0, -+		.end	= 0xfff000bf, -+		.flags	= IORESOURCE_MEM, -+	}, -+}; -+ -+static struct resource at32_eic0_resource[] = { -+	{ -+		.start	= 0xfff00100, -+		.end	= 0xfff0013f, -+		.flags	= IORESOURCE_MEM, -+	}, -+	IRQ(19), -+}; -+ -+DEFINE_DEV(at32_pm, 0); -+DEFINE_DEV(at32ap700x_rtc, 0); -+DEFINE_DEV(at32_wdt, 0); -+DEFINE_DEV(at32_eic, 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 @@ static struct clk pico_clk = { - 	.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 -  * -------------------------------------------------------------------- */ -@@ -583,12 +665,14 @@ DEV_CLK(mck, pio4, pba, 14); -  - void __init at32_add_system_devices(void) - { --	system_manager.eim_first_irq = EIM_IRQ_BASE; -- --	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); -  - 	platform_device_register(&at32_systc0_device); -  -@@ -894,6 +978,83 @@ at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n) - } -  - /* -------------------------------------------------------------------- -+ *  TWI -+ * -------------------------------------------------------------------- */ -+ -+static struct resource atmel_twi0_resource[] = { -+	PBMEM(0xffe00800), -+	IRQ(5), -+}; -+DEFINE_DEV(atmel_twi, 0); -+DEV_CLK(pclk,atmel_twi0,pba,2); -+ -+struct platform_device *__init -+at32_add_device_twi(unsigned int id) -+{ -+	struct platform_device *pdev; -+ -+	switch (id) { -+	case 0: -+		pdev = &atmel_twi0_device; -+		select_peripheral(PA(6),  PERIPH_A, 0);	/* SDA	*/ -+		select_peripheral(PA(7),  PERIPH_A, 0);	/* SCL	*/ -+		break; -+ -+	default: -+		return NULL; -+	} -+ -+	platform_device_register(pdev); -+	return pdev; -+} -+ -+/* -------------------------------------------------------------------- -+ * MMC -+ * -------------------------------------------------------------------- */ -+static struct mci_platform_data atmel_mci0_data = { -+	.detect_pin	= GPIO_PIN_NONE, -+	.wp_pin		= GPIO_PIN_NONE, -+}; -+static struct resource atmel_mci0_resource[] = { -+	PBMEM(0xfff02400), -+	IRQ(28), -+}; -+DEFINE_DEV_DATA(atmel_mci, 0); -+DEV_CLK(mci_clk, atmel_mci0, pbb, 9); -+ -+struct platform_device *__init -+at32_add_device_mci(unsigned int id, struct mci_platform_data *data) -+{ -+	struct platform_device *pdev; -+ -+	switch (id) { -+	case 0: -+		pdev = &atmel_mci0_device; -+		select_peripheral(PA(10), PERIPH_A, 0);	/* CLK	 */ -+		select_peripheral(PA(11), PERIPH_A, 0);	/* CMD	 */ -+		select_peripheral(PA(12), PERIPH_A, 0);	/* DATA0 */ -+		select_peripheral(PA(13), PERIPH_A, 0);	/* DATA1 */ -+		select_peripheral(PA(14), PERIPH_A, 0);	/* DATA2 */ -+		select_peripheral(PA(15), PERIPH_A, 0);	/* DATA3 */ -+		break; -+	default: -+		return NULL; -+	} -+ -+	if (data) { -+		if (data->detect_pin != GPIO_PIN_NONE) -+			at32_select_gpio(data->detect_pin, 0); -+		if (data->wp_pin != GPIO_PIN_NONE) -+			at32_select_gpio(data->wp_pin, 0); -+		memcpy(pdev->dev.platform_data, data, -+		       sizeof(struct mci_platform_data)); -+	} -+ -+	platform_device_register(pdev); -+	return pdev; -+} -+ -+/* -------------------------------------------------------------------- -  *  LCDC -  * -------------------------------------------------------------------- */ - static struct atmel_lcdfb_info atmel_lcdfb0_data; -@@ -1013,6 +1174,228 @@ err_dup_modedb: - } -  - /* -------------------------------------------------------------------- -+ *  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; -+ -+	pdev = platform_device_alloc("atmel_usba_udc", 0); -+	if (!pdev) -+		return NULL; -+ -+	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 (data->vbus_pin != GPIO_PIN_NONE) -+			at32_select_gpio(data->vbus_pin, 0); -+	} -+ -+	usba0_pclk.dev = &pdev->dev; -+	usba0_hclk.dev = &pdev->dev; -+ -+	platform_device_add(pdev); -+ -+	return pdev; -+ -+out_free_pdev: -+	platform_device_put(pdev); -+	return NULL; -+} -+ -+/* -------------------------------------------------------------------- -+ *  SSC -+ * -------------------------------------------------------------------- */ -+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(ssc, 1); -+DEV_CLK(pclk, ssc1, pba, 8); -+ -+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 = &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; -+	} -+ -+	platform_device_register(pdev); -+	return pdev; -+} -+ -+/* -------------------------------------------------------------------- -+ *  AC97C -+ * -------------------------------------------------------------------- */ -+static struct resource atmel_ac97c0_resource[] = { -+	PBMEM(0xfff02800), -+	IRQ(29), -+}; -+DEFINE_DEV(atmel_ac97c, 0); -+DEV_CLK(pclk, atmel_ac97c0, pbb, 10); -+ -+struct platform_device *__init -+at32_add_device_ac97c(unsigned int id) -+{ -+	struct platform_device *pdev; -+ -+	switch (id) { -+	case 0: -+		pdev = &atmel_ac97c0_device; -+		select_peripheral(PB(20), PERIPH_B, 0);	/* SYNC	*/ -+		select_peripheral(PB(21), PERIPH_B, 0);	/* SDO	*/ -+		select_peripheral(PB(22), PERIPH_B, 0);	/* SDI	*/ -+		select_peripheral(PB(23), PERIPH_B, 0);	/* SCLK	*/ -+		break; -+	default: -+		return NULL; -+	} -+ -+	platform_device_register(pdev); -+	return pdev; -+} -+ -+/* -------------------------------------------------------------------- -+ *  DAC -+ * -------------------------------------------------------------------- */ -+static struct resource abdac0_resource[] = { -+	PBMEM(0xfff02000), -+	IRQ(27), -+}; -+DEFINE_DEV(abdac, 0); -+DEV_CLK(pclk, abdac0, pbb, 8); -+static struct clk abdac0_sample_clk = { -+	.name           = "sample_clk", -+	.dev            = &abdac0_device.dev, -+	.mode           = genclk_mode, -+	.get_rate       = genclk_get_rate, -+	.set_rate       = genclk_set_rate, -+	.set_parent     = genclk_set_parent, -+	.index          = 6, -+}; -+ -+struct platform_device *__init -+at32_add_device_abdac(unsigned int id) -+{ -+	struct platform_device *pdev; -+ -+	switch (id) { -+	case 0: -+		pdev = &abdac0_device; -+		select_peripheral(PB(20), PERIPH_A, 0);	/* DATA1	*/ -+		select_peripheral(PB(21), PERIPH_A, 0);	/* DATA0	*/ -+		select_peripheral(PB(22), PERIPH_A, 0);	/* DATAN1	*/ -+		select_peripheral(PB(23), PERIPH_A, 0);	/* DATAN0	*/ -+		break; -+	default: -+		return NULL; -+	} -+ -+	platform_device_register(pdev); -+	return pdev; -+} -+ -+/* -------------------------------------------------------------------- -  *  GCLK -  * -------------------------------------------------------------------- */ - static struct clk gclk0 = { -@@ -1066,7 +1449,7 @@ struct clk *at32_clock_list[] = { - 	&hsb_clk, - 	&pba_clk, - 	&pbb_clk, --	&at32_sm_pclk, -+	&at32_pm_pclk, - 	&at32_intc0_pclk, - 	&hmatrix_clk, - 	&ebi_clk, -@@ -1075,6 +1458,7 @@ struct clk *at32_clock_list[] = { - 	&smc0_mck, - 	&pdc_hclk, - 	&pdc_pclk, -+	&dmaca0_hclk, - 	&pico_clk, - 	&pio0_mck, - 	&pio1_mck, -@@ -1092,8 +1476,18 @@ struct clk *at32_clock_list[] = { - 	&macb1_pclk, - 	&atmel_spi0_spi_clk, - 	&atmel_spi1_spi_clk, -+	&atmel_twi0_pclk, -+	&atmel_mci0_mci_clk, - 	&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, -@@ -1113,18 +1507,20 @@ void __init at32_portmux_init(void) -  - 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 @@ void __init at32_clock_init(void) - 	genclk_init_parent(&gclk3); - 	genclk_init_parent(&gclk4); - 	genclk_init_parent(&atmel_lcdfb0_pixclk); -+	genclk_init_parent(&abdac0_sample_clk); -  - 	/* - 	 * Turn on all clocks that have at least one user already, and -@@ -1157,8 +1554,8 @@ void __init at32_clock_init(void) - 			pbb_mask |= 1 << clk->index; - 	} -  --	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 --git a/arch/avr32/mach-at32ap/cpufreq.c b/arch/avr32/mach-at32ap/cpufreq.c -new file mode 100644 -index 0000000..235524b ---- /dev/null -+++ b/arch/avr32/mach-at32ap/cpufreq.c -@@ -0,0 +1,112 @@ -+/* -+ * Copyright (C) 2004-2007 Atmel Corporation -+ * -+ * Based on MIPS implementation arch/mips/kernel/time.c -+ *   Copyright 2001 MontaVista Software Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+/*#define DEBUG*/ -+ -+#include <linux/kernel.h> -+#include <linux/types.h> -+#include <linux/init.h> -+#include <linux/cpufreq.h> -+#include <linux/io.h> -+#include <linux/clk.h> -+#include <linux/err.h> -+#include <asm/system.h> -+ -+static struct clk *cpuclk; -+ -+static int at32_verify_speed(struct cpufreq_policy *policy) -+{ -+	if (policy->cpu != 0) -+		return -EINVAL; -+ -+	cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, -+			policy->cpuinfo.max_freq); -+	return 0; -+} -+ -+static unsigned int at32_get_speed(unsigned int cpu) -+{ -+	/* No SMP support */ -+	if (cpu) -+		return 0; -+	return (unsigned int)((clk_get_rate(cpuclk) + 500) / 1000); -+} -+ -+static int at32_set_target(struct cpufreq_policy *policy, -+			  unsigned int target_freq, -+			  unsigned int relation) -+{ -+	struct cpufreq_freqs freqs; -+	long freq; -+ -+	/* Convert target_freq from kHz to Hz */ -+	freq = clk_round_rate(cpuclk, target_freq * 1000); -+ -+	/* Check if policy->min <= new_freq <= policy->max */ -+	if(freq < (policy->min * 1000) || freq > (policy->max * 1000)) -+		return -EINVAL; -+ -+	pr_debug("cpufreq: requested frequency %u Hz\n", target_freq * 1000); -+ -+	freqs.old = at32_get_speed(0); -+	freqs.new = (freq + 500) / 1000; -+	freqs.cpu = 0; -+	freqs.flags = 0; -+ -+	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); -+	clk_set_rate(cpuclk, freq); -+	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); -+ -+	pr_debug("cpufreq: set frequency %lu Hz\n", freq); -+ -+	return 0; -+} -+ -+static int __init at32_cpufreq_driver_init(struct cpufreq_policy *policy) -+{ -+	if (policy->cpu != 0) -+		return -EINVAL; -+ -+	cpuclk = clk_get(NULL, "cpu"); -+	if (IS_ERR(cpuclk)) { -+		pr_debug("cpufreq: could not get CPU clk\n"); -+		return PTR_ERR(cpuclk); -+	} -+ -+	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; -+ -+	printk("cpufreq: AT32AP CPU frequency driver\n"); -+ -+	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, -+}; -+ -+static int __init at32_cpufreq_init(void) -+{ -+	return cpufreq_register_driver(&at32_driver); -+} -+ -+arch_initcall(at32_cpufreq_init); -diff --git a/arch/avr32/mach-at32ap/extint.c b/arch/avr32/mach-at32ap/extint.c -index 4a60ecc..8acd010 100644 ---- a/arch/avr32/mach-at32ap/extint.c -+++ b/arch/avr32/mach-at32ap/extint.c -@@ -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 -+ -+/* 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)) -+ -+/* 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) -+ -+struct eic { -+	void __iomem *regs; -+	struct irq_chip *chip; -+	unsigned int first_irq; -+}; -  --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)); - } -  --static void eim_mask_irq(unsigned int irq) -+static void eic_mask_irq(unsigned int irq) - { --	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)); - } -  --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)); - } -  --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)); - } -  --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) - { --	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 @@ static int eim_set_irq_type(unsigned int irq, unsigned int flow_type) - 		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 @@ static int eim_set_irq_type(unsigned int irq, unsigned int flow_type) - 	} -  - 	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 @@ static int eim_set_irq_type(unsigned int irq, unsigned int flow_type) - 		desc->status |= flow_type; - 	} -  --	spin_unlock_irqrestore(&sm->lock, flags); -- - 	return ret; - } -  --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) - { --	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 @@ static void demux_eim_irq(unsigned int irq, struct irq_desc *desc) - 	} - } -  --static int __init eim_init(void) -+static int __init eic_probe(struct platform_device *pdev) - { --	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; -  --	/* --	 * 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; -+	} -  - 	/* - 	 * Find out how many interrupt lines that are actually - 	 * implemented in hardware. - 	 */ --	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); - 	} -  --	int_irq = platform_get_irq_byname(sm->pdev, "eim"); -- --	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); -  --	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); -  - 	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); - } --arch_initcall(eim_init); -+arch_initcall(eic_init); -diff --git a/arch/avr32/mach-at32ap/gpio-dev.c b/arch/avr32/mach-at32ap/gpio-dev.c -new file mode 100644 -index 0000000..3d4810d ---- /dev/null -+++ b/arch/avr32/mach-at32ap/gpio-dev.c -@@ -0,0 +1,570 @@ -+/* -+ * 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> -+ -+#include <asm/gpio.h> -+#include <asm/arch/portmux.h> -+ -+#define GPIO_DEV_MAX			8 -+ -+static struct class *gpio_dev_class; -+static dev_t gpio_devt; -+ -+struct gpio_item { -+	spinlock_t lock; -+ -+	int enabled; -+	int initialized; -+	int port; -+	u32 pin_mask; -+	u32 oe_mask; -+ -+	/* Pin state last time we read it (for blocking reads) */ -+	u32 pin_state; -+	int changed; -+ -+	wait_queue_head_t change_wq; -+	struct fasync_struct *async_queue; -+ -+	int id; -+	struct class_device *gpio_dev; -+	struct cdev char_dev; -+	struct config_item item; -+}; -+ -+struct gpio_attribute { -+	struct configfs_attribute attr; -+	ssize_t (*show)(struct gpio_item *, char *); -+	ssize_t (*store)(struct gpio_item *, const char *, size_t); -+}; -+ -+static irqreturn_t gpio_dev_interrupt(int irq, void *dev_id) -+{ -+	struct gpio_item *gpio = dev_id; -+	u32 old_state, new_state; -+ -+	old_state = gpio->pin_state; -+	new_state = at32_gpio_get_value_multiple(gpio->port, gpio->pin_mask); -+	gpio->pin_state = new_state; -+ -+	if (new_state != old_state) { -+		gpio->changed = 1; -+		wake_up_interruptible(&gpio->change_wq); -+ -+		if (gpio->async_queue) -+			kill_fasync(&gpio->async_queue, SIGIO, POLL_IN); -+	} -+ -+	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; -+ -+	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; -+		} -+	} -+ -+	return 0; -+ -+err_irq: -+	while (i--) { -+		if (gpio->pin_mask & (1 << i)) { -+			irq = gpio_to_irq(32 * gpio->port + i); -+			free_irq(irq, gpio); -+		} -+	} -+ -+	config_item_put(&gpio->item); -+ -+	return ret; -+} -+ -+static int gpio_dev_fasync(int fd, struct file *file, int mode) -+{ -+	struct gpio_item *gpio = file->private_data; -+ -+	return fasync_helper(fd, file, mode, &gpio->async_queue); -+} -+ -+static int gpio_dev_release(struct inode *inode, struct file *file) -+{ -+	struct gpio_item *gpio = file->private_data; -+	unsigned int irq; -+	unsigned int i; -+ -+	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); -+		} -+	} -+ -+	config_item_put(&gpio->item); -+ -+	return 0; -+} -+ -+static unsigned int gpio_dev_poll(struct file *file, poll_table *wait) -+{ -+	struct gpio_item *gpio = file->private_data; -+	unsigned int mask = 0; -+ -+	poll_wait(file, &gpio->change_wq, wait); -+	if (gpio->changed) -+		mask |= POLLIN | POLLRDNORM; -+ -+	return mask; -+} -+ -+static ssize_t gpio_dev_read(struct file *file, char __user *buf, -+			     size_t count, loff_t *offset) -+{ -+	struct gpio_item *gpio = file->private_data; -+	u32 value; -+ -+	spin_lock_irq(&gpio->lock); -+	while (!gpio->changed) { -+		spin_unlock_irq(&gpio->lock); -+ -+		if (file->f_flags & O_NONBLOCK) -+			return -EAGAIN; -+ -+		if (wait_event_interruptible(gpio->change_wq, gpio->changed)) -+			return -ERESTARTSYS; -+ -+		spin_lock_irq(&gpio->lock); -+	} -+ -+	gpio->changed = 0; -+	value = at32_gpio_get_value_multiple(gpio->port, gpio->pin_mask); -+ -+	spin_unlock_irq(&gpio->lock); -+ -+	count = min(count, (size_t)4); -+	if (copy_to_user(buf, &value, count)) -+		return -EFAULT; -+ -+	return count; -+} -+ -+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; -+ -+	count = min(count, (size_t)4); -+	if (copy_from_user(&value, buf, count)) -+		return -EFAULT; -+ -+	/* Assuming big endian */ -+	mask <<= (4 - count) * 8; -+	mask &= gpio->pin_mask; -+ -+	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 struct gpio_item *to_gpio_item(struct config_item *item) -+{ -+	return item ? container_of(item, struct gpio_item, item) : NULL; -+} -+ -+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 ret; -+} -+ -+static ssize_t gpio_show_pin_mask(struct gpio_item *gpio, char *page) -+{ -+	return sprintf(page, "0x%08x\n", gpio->pin_mask); -+} -+ -+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; -+ -+	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; -+} -+ -+static ssize_t gpio_show_oe_mask(struct gpio_item *gpio, char *page) -+{ -+	return sprintf(page, "0x%08x\n", gpio->oe_mask); -+} -+ -+static ssize_t gpio_store_oe_mask(struct gpio_item *gpio, -+				  const char *page, size_t count) -+{ -+	u32 mask; -+	char *p = (char *)page; -+	ssize_t ret = -EINVAL; -+ -+	mask = simple_strtoul(p, &p, 0); -+	if (!p || (*p && (*p != '\n'))) -+		return -EINVAL; -+ -+	spin_lock(&gpio->lock); -+	if (!gpio->enabled) { -+		gpio->oe_mask = mask & gpio->pin_mask; -+		ret = count; -+	} -+	spin_unlock(&gpio->lock); -+ -+	return ret; -+} -+ -+static ssize_t gpio_show_enabled(struct gpio_item *gpio, char *page) -+{ -+	return sprintf(page, "%d\n", gpio->enabled); -+} -+ -+static ssize_t gpio_store_enabled(struct gpio_item *gpio, -+				  const char *page, size_t count) -+{ -+	char *p = (char *)page; -+	int enabled; -+	int ret; -+ -+	enabled = simple_strtoul(p, &p, 0); -+	if (!p || (*p && (*p != '\n'))) -+		return -EINVAL; -+ -+	/* make it a boolean value */ -+	enabled = !!enabled; -+ -+	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; -+	} -+ -+	/* Disallow any updates to gpio_id or pin_mask */ -+	spin_lock(&gpio->lock); -+	gpio->enabled = enabled; -+	spin_unlock(&gpio->lock); -+ -+	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; -+ -+	gpio->initialized = 1; -+ -+	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; -+	} -+ -+	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)); -+ -+	return 0; -+ -+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 ret; -+} -+ -+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 gpio_item *gpio_item = to_gpio_item(item); -+	struct gpio_attribute *gpio_attr -+		= container_of(attr, struct gpio_attribute, attr); -+	ssize_t ret = 0; -+ -+	if (gpio_attr->show) -+		ret = gpio_attr->show(gpio_item, page); -+	return ret; -+} -+ -+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 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 gpio_dev_init(void) -+{ -+	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 --git a/arch/avr32/mach-at32ap/pio.c b/arch/avr32/mach-at32ap/pio.c -index 1eb99b8..153bb9a 100644 ---- a/arch/avr32/mach-at32ap/pio.c -+++ b/arch/avr32/mach-at32ap/pio.c -@@ -158,6 +158,82 @@ fail: - 	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) -+{ -+	return port < MAX_NR_PIO_DEVICES && pio_dev[port].regs != NULL; -+} -+ -+int at32_select_gpio_pins(unsigned int port, u32 pins, u32 oe_mask) -+{ -+	struct pio_device *pio; -+	u32 old, new; -+ -+	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 --git a/arch/avr32/mach-at32ap/pm.h b/arch/avr32/mach-at32ap/pm.h -new file mode 100644 -index 0000000..a1f8ace ---- /dev/null -+++ b/arch/avr32/mach-at32ap/pm.h -@@ -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 --git a/arch/avr32/mach-at32ap/sm.h b/arch/avr32/mach-at32ap/sm.h -deleted file mode 100644 -index cad02b5..0000000 ---- a/arch/avr32/mach-at32ap/sm.h -+++ /dev/null -@@ -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 --git a/arch/avr32/mm/dma-coherent.c b/arch/avr32/mm/dma-coherent.c -index 099212d..26f29c6 100644 ---- a/arch/avr32/mm/dma-coherent.c -+++ b/arch/avr32/mm/dma-coherent.c -@@ -41,6 +41,13 @@ static struct page *__dma_alloc(struct device *dev, size_t size, - 	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 --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig -index 53f5538..520afb8 100644 ---- a/drivers/char/watchdog/Kconfig -+++ b/drivers/char/watchdog/Kconfig -@@ -187,6 +187,26 @@ config PNX4008_WATCHDOG -  - 	  Say N if you are unsure. -  -+# AVR32 Architecture -+ -+config AT32AP700X_WDT -+	tristate "AT32AP700x watchdog" -+	depends on WATCHDOG && CPU_AT32AP7000 -+	help -+	  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 -+	  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 --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile -index d90f649..3907ec0 100644 ---- a/drivers/char/watchdog/Makefile -+++ b/drivers/char/watchdog/Makefile -@@ -36,6 +36,9 @@ obj-$(CONFIG_MPCORE_WATCHDOG) += mpcore_wdt.o - 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 --git a/drivers/char/watchdog/at32ap700x_wdt.c b/drivers/char/watchdog/at32ap700x_wdt.c -new file mode 100644 -index 0000000..9b598d9 ---- /dev/null -+++ b/drivers/char/watchdog/at32ap700x_wdt.c -@@ -0,0 +1,325 @@ -+/* -+ * Watchdog driver for Atmel AT32AP700X devices -+ * -+ * Copyright (C) 2005-2006 Atmel Corporation -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#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> -+ -+#define TIMEOUT_MIN		1 -+#define TIMEOUT_DEFAULT		CONFIG_AT32AP700X_WDT_TIMEOUT -+#define TIMEOUT_MAX		2 -+ -+/* Watchdog registers and write/read macro */ -+#define	WDT_CTRL		0x00 -+#define WDT_CTRL_EN		   0 -+#define WDT_CTRL_PSEL		   8 -+#define WDT_CTRL_KEY		  24 -+ -+#define WDT_CLR			0x04 -+ -+#define WDT_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; -+ -+/* -+ * Disable the watchdog. -+ */ -+static void inline at32_wdt_stop(void) -+{ -+	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)); -+} -+ -+/* -+ * Enable and reset the watchdog. -+ */ -+static void inline at32_wdt_start(void) -+{ -+	/* 0xf is 2^16 divider = 2 sec, 0xe is 2^15 divider = 1 sec */ -+	unsigned long psel = (wdt->timeout > 1) ? 0xf : 0xe; -+ -+	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)); -+} -+ -+/* -+ * Pat the watchdog timer. -+ */ -+static void inline at32_wdt_pat(void) -+{ -+	wdt_writel(wdt, CLR, 0x42); -+} -+ -+/* -+ * Watchdog device is opened, and watchdog starts running. -+ */ -+static int at32_wdt_open(struct inode *inode, struct file *file) -+{ -+	if (test_and_set_bit(1, &wdt->users)) -+		return -EBUSY; -+ -+	at32_wdt_start(); -+	return nonseekable_open(inode, file); -+} -+ -+/* -+ * Close the watchdog device. If CONFIG_WATCHDOG_NOWAYOUT is _not_ defined then -+ * the watchdog is also disabled. -+ */ -+static int at32_wdt_close(struct inode *inode, struct file *file) -+{ -+#ifndef CONFIG_WATCHDOG_NOWAYOUT -+	at32_wdt_stop(); -+#endif -+	clear_bit(1, &wdt->users); -+	return 0; -+} -+ -+/* -+ * Change the watchdog time interval. -+ */ -+static int at32_wdt_settimeout(int time) -+{ -+	/* -+	 * All counting occurs at 1 / SLOW_CLOCK (32 kHz) and max prescaler is -+	 * 2 ^ 16 allowing up to 2 seconds timeout. -+	 */ -+	if ((time < TIMEOUT_MIN) || (time > TIMEOUT_MAX)) -+		return -EINVAL; -+ -+	/* -+	 * Set new watchdog time. It will be used when at32_wdt_start() is -+	 * called. -+	 */ -+	wdt->timeout = time; -+	return 0; -+} -+ -+static struct watchdog_info at32_wdt_info = { -+	.identity	= "at32ap700x watchdog", -+	.options	= WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, -+}; -+ -+/* -+ * 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; -+	} -+ -+	return ret; -+} -+ -+static ssize_t at32_wdt_write(struct file *file, const char *data, size_t len, -+				loff_t *ppos) -+{ -+	at32_wdt_pat(); -+	return len; -+} -+ -+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, -+}; -+ -+static int __init at32_wdt_probe(struct platform_device *pdev) -+{ -+	struct resource	*regs; -+	int ret; -+ -+	if (wdt) { -+		dev_dbg(&pdev->dev, "only 1 wdt instance supported.\n"); -+		return -EBUSY; -+	} -+ -+	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+	if (!regs) { -+		dev_dbg(&pdev->dev, "missing mmio resource\n"); -+		return -ENXIO; -+	} -+ -+	wdt = kzalloc(sizeof(struct wdt_at32ap700x), GFP_KERNEL); -+	if (!wdt) { -+		dev_dbg(&pdev->dev, "no memory for wdt structure\n"); -+		return -ENOMEM; -+	} -+ -+	wdt->regs = ioremap(regs->start, regs->end - regs->start + 1); -+	if (!wdt->regs) { -+		ret = -ENOMEM; -+		dev_dbg(&pdev->dev, "could not map I/O memory\n"); -+		goto err_free; -+	} -+	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); -+	} -+ -+	ret = misc_register(&wdt->miscdev); -+	if (ret) { -+		dev_dbg(&pdev->dev, "failed to register wdt miscdev\n"); -+		goto err_iounmap; -+	} -+ -+	platform_set_drvdata(pdev, wdt); -+	wdt->miscdev.parent = &pdev->dev; -+	dev_info(&pdev->dev, "AT32AP700X WDT at 0x%p\n", wdt->regs); -+ -+	return 0; -+ -+err_iounmap: -+	iounmap(wdt->regs); -+err_free: -+	kfree(wdt); -+	wdt = NULL; -+	return ret; -+} -+ -+static int __exit at32_wdt_remove(struct platform_device *pdev) -+{ -+	if (wdt && platform_get_drvdata(pdev) == wdt) { -+		misc_deregister(&wdt->miscdev); -+		iounmap(wdt->regs); -+		kfree(wdt); -+		wdt = NULL; -+		platform_set_drvdata(pdev, NULL); -+	} -+ -+	return 0; -+} -+ -+static void at32_wdt_shutdown(struct platform_device *pdev) -+{ -+	at32_wdt_stop(); -+} -+ -+#ifdef CONFIG_PM -+static int at32_wdt_suspend(struct platform_device *pdev, pm_message_t message) -+{ -+	at32_wdt_stop(); -+	return 0; -+} -+ -+static int at32_wdt_resume(struct platform_device *pdev) -+{ -+	if (wdt->users) -+		at32_wdt_start(); -+	return 0; -+} -+#else -+#define at32_wdt_suspend NULL -+#define at32_wdt_resume NULL -+#endif -+ -+static struct platform_driver at32_wdt_driver = { -+	.remove		= __exit_p(at32_wdt_remove), -+	.suspend	= at32_wdt_suspend, -+	.resume		= at32_wdt_resume, -+	.driver		= { -+		.name	= "at32_wdt", -+		.owner	= THIS_MODULE, -+	}, -+	.shutdown	= at32_wdt_shutdown, -+}; -+ -+static int __init at32_wdt_init(void) -+{ -+	return platform_driver_probe(&at32_wdt_driver, at32_wdt_probe); -+} -+module_init(at32_wdt_init); -+ -+static void __exit at32_wdt_exit(void) -+{ -+	platform_driver_unregister(&at32_wdt_driver); -+} -+module_exit(at32_wdt_exit); -+ -+MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>"); -+MODULE_DESCRIPTION("Watchdog driver for Atmel AT32AP700X"); -+MODULE_LICENSE("GPL"); -+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); -diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig -index 838dc1c..80da12d 100644 ---- a/drivers/i2c/busses/Kconfig -+++ b/drivers/i2c/busses/Kconfig -@@ -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 --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile -index 14d1432..fd7c3b3 100644 ---- a/drivers/i2c/busses/Makefile -+++ b/drivers/i2c/busses/Makefile -@@ -52,6 +52,7 @@ obj-$(CONFIG_I2C_VIAPRO)	+= i2c-viapro.o - 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 --git a/drivers/i2c/busses/atmeltwi.h b/drivers/i2c/busses/atmeltwi.h -new file mode 100644 -index 0000000..8502ea6 ---- /dev/null -+++ b/drivers/i2c/busses/atmeltwi.h -@@ -0,0 +1,117 @@ -+/* -+ * Register definitions for the Atmel Two-Wire Interface -+ */ -+ -+#ifndef __ASM_AVR32_TWI_H__ -+#define __ASM_AVR32_TWI_H__ -+ -+/* TWI register offsets */ -+#define TWI_CR					0x0000 -+#define TWI_MMR					0x0004 -+#define TWI_SMR					0x0008 -+#define TWI_IADR				0x000c -+#define TWI_CWGR				0x0010 -+#define TWI_SR					0x0020 -+#define TWI_IER					0x0024 -+#define TWI_IDR					0x0028 -+#define TWI_IMR					0x002c -+#define TWI_RHR					0x0030 -+#define TWI_THR					0x0034 -+ -+/* Bitfields in CR */ -+#define TWI_START_OFFSET			0 -+#define TWI_START_SIZE				1 -+#define TWI_STOP_OFFSET				1 -+#define TWI_STOP_SIZE				1 -+#define TWI_MSEN_OFFSET				2 -+#define TWI_MSEN_SIZE				1 -+#define TWI_MSDIS_OFFSET			3 -+#define TWI_MSDIS_SIZE				1 -+#define TWI_SVEN_OFFSET				4 -+#define TWI_SVEN_SIZE				1 -+#define TWI_SVDIS_OFFSET			5 -+#define TWI_SVDIS_SIZE				1 -+#define TWI_SWRST_OFFSET			7 -+#define TWI_SWRST_SIZE				1 -+ -+/* Bitfields in MMR */ -+#define TWI_IADRSZ_OFFSET			8 -+#define TWI_IADRSZ_SIZE				2 -+#define TWI_MREAD_OFFSET			12 -+#define TWI_MREAD_SIZE				1 -+#define TWI_DADR_OFFSET				16 -+#define TWI_DADR_SIZE				7 -+ -+/* Bitfields in SMR */ -+#define TWI_SADR_OFFSET				16 -+#define TWI_SADR_SIZE				7 -+ -+/* Bitfields in IADR */ -+#define TWI_IADR_OFFSET				0 -+#define TWI_IADR_SIZE				24 -+ -+/* Bitfields in CWGR */ -+#define TWI_CLDIV_OFFSET			0 -+#define TWI_CLDIV_SIZE				8 -+#define TWI_CHDIV_OFFSET			8 -+#define TWI_CHDIV_SIZE				8 -+#define TWI_CKDIV_OFFSET			16 -+#define TWI_CKDIV_SIZE				3 -+ -+/* Bitfields in SR */ -+#define TWI_TXCOMP_OFFSET			0 -+#define TWI_TXCOMP_SIZE				1 -+#define TWI_RXRDY_OFFSET			1 -+#define TWI_RXRDY_SIZE				1 -+#define TWI_TXRDY_OFFSET			2 -+#define TWI_TXRDY_SIZE				1 -+#define TWI_SVDIR_OFFSET			3 -+#define TWI_SVDIR_SIZE				1 -+#define TWI_SVACC_OFFSET			4 -+#define TWI_SVACC_SIZE				1 -+#define TWI_GCACC_OFFSET			5 -+#define TWI_GCACC_SIZE				1 -+#define TWI_OVRE_OFFSET				6 -+#define TWI_OVRE_SIZE				1 -+#define TWI_UNRE_OFFSET				7 -+#define TWI_UNRE_SIZE				1 -+#define TWI_NACK_OFFSET				8 -+#define TWI_NACK_SIZE				1 -+#define TWI_ARBLST_OFFSET			9 -+#define TWI_ARBLST_SIZE				1 -+ -+/* Bitfields in RHR */ -+#define TWI_RXDATA_OFFSET			0 -+#define TWI_RXDATA_SIZE				8 -+ -+/* Bitfields in THR */ -+#define TWI_TXDATA_OFFSET			0 -+#define TWI_TXDATA_SIZE				8 -+ -+/* Constants for IADRSZ */ -+#define TWI_IADRSZ_NO_ADDR			0 -+#define TWI_IADRSZ_ONE_BYTE			1 -+#define TWI_IADRSZ_TWO_BYTES			2 -+#define TWI_IADRSZ_THREE_BYTES			3 -+ -+/* Bit manipulation macros */ -+#define TWI_BIT(name)					\ -+	(1 << TWI_##name##_OFFSET) -+#define TWI_BF(name,value)				\ -+	(((value) & ((1 << TWI_##name##_SIZE) - 1))	\ -+	 << TWI_##name##_OFFSET) -+#define TWI_BFEXT(name,value)				\ -+	(((value) >> TWI_##name##_OFFSET)		\ -+	 & ((1 << TWI_##name##_SIZE) - 1)) -+#define TWI_BFINS(name,value,old)			\ -+	(((old) & ~(((1 << TWI_##name##_SIZE) - 1)	\ -+		    << TWI_##name##_OFFSET))		\ -+	 | TWI_BF(name,value)) -+ -+/* Register access macros */ -+#define twi_readl(port,reg)				\ -+	__raw_readl((port)->regs + TWI_##reg) -+#define twi_writel(port,reg,value)			\ -+	__raw_writel((value), (port)->regs + TWI_##reg) -+ -+#endif /* __ASM_AVR32_TWI_H__ */ -diff --git a/drivers/i2c/busses/i2c-atmeltwi.c b/drivers/i2c/busses/i2c-atmeltwi.c -new file mode 100644 -index 0000000..9a3f223 ---- /dev/null -+++ b/drivers/i2c/busses/i2c-atmeltwi.c -@@ -0,0 +1,383 @@ -+/* -+ * 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> -+ * -+ * Partialy rewriten by Karel Hojdar <cmkaho at seznam.cz> -+ * bugs removed, interrupt routine markedly rewritten -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ */ -+ -+ -+#include <linux/err.h> -+#include <linux/module.h> -+#include <linux/kernel.h> -+#include <linux/slab.h> -+#include <linux/types.h> -+#include <linux/delay.h> -+#include <linux/i2c.h> -+#include <linux/init.h> -+#include <linux/clk.h> -+#include <linux/interrupt.h> -+#include <linux/irq.h> -+#include <linux/platform_device.h> -+#include <linux/completion.h> -+#include <asm/io.h> -+#include <linux/time.h> -+#include "atmeltwi.h" -+ -+static unsigned int baudrate = CONFIG_I2C_ATMELTWI_BAUDRATE; -+module_param(baudrate, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); -+MODULE_PARM_DESC(baudrate, "The TWI baudrate"); -+ -+ -+struct atmel_twi { -+	void __iomem *regs; -+	struct i2c_adapter adapter; -+	struct clk *pclk; -+	spinlock_t lock; -+	struct completion comp; -+	u32 intmask; -+	u8 *buf; -+	u8 len; -+	u8 acks_left; -+	u8 nack; -+	unsigned int irq; -+ -+}; -+#define to_atmel_twi(adap) container_of(adap, struct atmel_twi, adapter) -+ -+/* -+ * Initialize the TWI hardware registers. -+ */ -+static int __devinit twi_hwinit(struct atmel_twi *twi) -+{ -+	unsigned long cdiv, ckdiv=0; -+ -+	twi_writel(twi, IDR, ~0UL); -+	twi_writel(twi, CR, TWI_BIT(SWRST));	/*Reset peripheral*/ -+	twi_readl(twi, SR); -+ -+	cdiv = (clk_get_rate(twi->pclk) / (2 * baudrate)) - 4; -+ -+	while (cdiv > 255) { -+		ckdiv++; -+		cdiv = cdiv >> 1; -+	} -+ -+	if (ckdiv > 7) -+		return -EINVAL; -+	else -+		twi_writel(twi, CWGR, (TWI_BF(CKDIV, ckdiv) -+			       | TWI_BF(CHDIV, cdiv) -+			       | TWI_BF(CLDIV, cdiv))); -+	return 0; -+} -+ -+/* -+ * Waits for the i2c status register to set the specified bitmask -+ * Returns 0 if timed out (~100ms). -+ */ -+static short twi_complete(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)) { -+		/* RESET TWI interface */ -+		twi_writel(twi, CR, TWI_BIT(SWRST)); -+ -+		/* Reinitialize TWI */ -+		twi_hwinit(twi); -+ -+		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); -+ -+	twi->nack = 0; -+	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) { -+			if (twi->len == 1) -+				twi_writel(twi, CR, -+					TWI_BIT(START) | TWI_BIT(STOP)); -+			else -+				twi_writel(twi, CR, TWI_BIT(START)); -+ -+			if (twi_complete(twi, TWI_BIT(RXRDY)) == -ETIMEDOUT) { -+				dev_dbg(&adap->dev, "RXRDY timeout. Stopped with %d bytes left\n", -+					twi->acks_left); -+				return -ETIMEDOUT; -+			} -+		} else { -+			twi_writel(twi, THR, twi->buf[0]); -+			if (twi_complete(twi, TWI_BIT(TXRDY)) == -ETIMEDOUT) { -+				dev_dbg(&adap->dev, "TXRDY timeout. Stopped with %d bytes left\n", -+				twi->acks_left); -+				return -ETIMEDOUT; -+			} -+ -+			if (twi->nack) -+			    return -ENODEV; -+		} -+ -+		/* 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); -+ -+	/* Save state for later debug prints */ -+	int old_mask = twi->intmask; -+	int old_status = status; -+ -+	if (twi->intmask & status) { -+		if (status & TWI_BIT(NACK)) -+			goto nack; -+ -+		status &= twi->intmask; -+ -+		if (status & TWI_BIT(TXCOMP)) -+		    goto complete; -+ -+		else if (status & TWI_BIT(RXRDY)) { -+			if ( twi->acks_left > 0 ) { -+			    twi->buf[twi->len - twi->acks_left] = -+				twi_readl(twi, RHR); -+			    twi->acks_left--; -+			} -+			if ( twi->acks_left == 1 ) -+				twi_writel(twi, CR, TWI_BIT(STOP)); -+ -+			if (twi->acks_left == 0 ) { -+				twi->intmask = TWI_BIT(TXCOMP); -+				twi_writel(twi, IER, TWI_BIT(TXCOMP)); -+			} -+		} else if (status & TWI_BIT(TXRDY)) { -+			twi->acks_left--; -+			if ( twi->acks_left == 0 ) { -+				twi->intmask = TWI_BIT(TXCOMP); -+				twi_writel(twi, IER, TWI_BIT(TXCOMP)); -+			} else if (twi->acks_left > 0) -+				twi_writel(twi, THR, twi->buf[twi->len - twi->acks_left]); -+		} -+	} -+ -+	dev_dbg(&twi->adapter.dev, -+		"TWI ISR, SR 0x%08X, intmask 0x%08X, acks_left %i.\n", -+		old_status, old_mask, twi->acks_left); -+ -+	return IRQ_HANDLED; -+ -+nack: -+	dev_dbg(&twi->adapter.dev, "NACK received!\n"); -+	twi->nack = 1; -+ -+complete: -+	twi_writel(twi, IDR, ~0UL); -+	complete(&twi->comp); -+ -+	dev_dbg(&twi->adapter.dev, -+		"TWI ISR, SR 0x%08X, intmask 0x%08X, \ -+		acks_left %i - completed.\n", -+		old_status, old_mask, twi->acks_left); -+ -+	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 --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig -index 50e06e8..7bbea09 100644 ---- a/drivers/input/mouse/Kconfig -+++ b/drivers/input/mouse/Kconfig -@@ -216,4 +216,20 @@ config MOUSE_HIL - 	help - 	  Say Y here to support HIL pointers. -  -+config MOUSE_GPIO -+	tristate "GPIO mouse" -+	depends on GENERIC_GPIO -+	select INPUT_POLLDEV -+	help -+	  This driver simulates a mouse on GPIO lines of various CPUs (and some -+	  other chips). -+ -+	  Say Y here if your device has buttons or a simple joystick connected -+	  directly to GPIO lines. Your board-specific setup logic must also -+	  provide a platform device and platform data saying which GPIOs are -+	  used. -+ -+	  To compile this driver as a module, choose M here: the -+	  module will be called gpio_mouse. -+ - endif -diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile -index aa4ba87..9e6e363 100644 ---- a/drivers/input/mouse/Makefile -+++ b/drivers/input/mouse/Makefile -@@ -15,6 +15,7 @@ obj-$(CONFIG_MOUSE_PS2)		+= psmouse.o - obj-$(CONFIG_MOUSE_SERIAL)	+= sermouse.o - obj-$(CONFIG_MOUSE_HIL)		+= hil_ptr.o - obj-$(CONFIG_MOUSE_VSXXXAA)	+= vsxxxaa.o -+obj-$(CONFIG_MOUSE_GPIO)	+= gpio_mouse.o -  - psmouse-objs := psmouse-base.o synaptics.o -  -diff --git a/drivers/input/mouse/gpio_mouse.c b/drivers/input/mouse/gpio_mouse.c -new file mode 100644 -index 0000000..0936d6b ---- /dev/null -+++ b/drivers/input/mouse/gpio_mouse.c -@@ -0,0 +1,196 @@ -+/* -+ * Driver for simulating a mouse on GPIO lines. -+ * -+ * 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/init.h> -+#include <linux/version.h> -+#include <linux/module.h> -+#include <linux/platform_device.h> -+#include <linux/input-polldev.h> -+#include <linux/gpio_mouse.h> -+ -+#include <asm/gpio.h> -+ -+/* -+ * Timer function which is run every scan_ms ms when the device is opened. -+ * The dev input varaible is set to the the input_dev pointer. -+ */ -+static void gpio_mouse_scan(struct input_polled_dev *dev) -+{ -+	struct gpio_mouse_platform_data *gpio = dev->private; -+	struct input_dev *input = dev->input; -+	int x, y; -+ -+	if (gpio->bleft >= 0) -+		input_report_key(input, BTN_LEFT, -+				gpio_get_value(gpio->bleft) ^ gpio->polarity); -+	if (gpio->bmiddle >= 0) -+		input_report_key(input, BTN_MIDDLE, -+				gpio_get_value(gpio->bmiddle) ^ gpio->polarity); -+	if (gpio->bright >= 0) -+		input_report_key(input, BTN_RIGHT, -+				gpio_get_value(gpio->bright) ^ gpio->polarity); -+ -+	x = (gpio_get_value(gpio->right) ^ gpio->polarity) -+		- (gpio_get_value(gpio->left) ^ gpio->polarity); -+	y = (gpio_get_value(gpio->down) ^ gpio->polarity) -+		- (gpio_get_value(gpio->up) ^ gpio->polarity); -+ -+	input_report_rel(input, REL_X, x); -+	input_report_rel(input, REL_Y, y); -+	input_sync(input); -+} -+ -+static int __init gpio_mouse_probe(struct platform_device *pdev) -+{ -+	struct gpio_mouse_platform_data *pdata = pdev->dev.platform_data; -+	struct input_polled_dev *input_poll; -+	struct input_dev *input; -+	int pin, i; -+	int error; -+ -+	if (!pdata) { -+		dev_err(&pdev->dev, "no platform data\n"); -+		error = -ENXIO; -+		goto out; -+	} -+ -+	if (pdata->scan_ms < 0) { -+		dev_err(&pdev->dev, "invalid scan time\n"); -+		error = -EINVAL; -+		goto out; -+	} -+ -+	for (i = 0; i < GPIO_MOUSE_PIN_MAX; i++) { -+		pin = pdata->pins[i]; -+ -+		if (pin < 0) { -+ -+			if (i <= GPIO_MOUSE_PIN_RIGHT) { -+				/* Mouse direction is required. */ -+				dev_err(&pdev->dev, -+					"missing GPIO for directions\n"); -+				error = -EINVAL; -+				goto out_free_gpios; -+			} -+ -+			if (i == GPIO_MOUSE_PIN_BLEFT) -+				dev_dbg(&pdev->dev, "no left button defined\n"); -+ -+		} else { -+			error = gpio_request(pin, "gpio_mouse"); -+			if (error) { -+				dev_err(&pdev->dev, "fail %d pin (%d idx)\n", -+					pin, i); -+				goto out_free_gpios; -+			} -+ -+			gpio_direction_input(pin); -+		} -+	} -+ -+	input_poll = input_allocate_polled_device(); -+	if (!input_poll) { -+		dev_err(&pdev->dev, "not enough memory for input device\n"); -+		error = -ENOMEM; -+		goto out_free_gpios; -+	} -+ -+	platform_set_drvdata(pdev, input_poll); -+ -+	/* set input-polldev handlers */ -+	input_poll->private = pdata; -+	input_poll->poll = gpio_mouse_scan; -+	input_poll->poll_interval = pdata->scan_ms; -+ -+	input = input_poll->input; -+	input->name = pdev->name; -+	input->id.bustype = BUS_HOST; -+	input->dev.parent = &pdev->dev; -+ -+	input_set_capability(input, EV_REL, REL_X); -+	input_set_capability(input, EV_REL, REL_Y); -+	if (pdata->bleft >= 0) -+		input_set_capability(input, EV_KEY, BTN_LEFT); -+	if (pdata->bmiddle >= 0) -+		input_set_capability(input, EV_KEY, BTN_MIDDLE); -+	if (pdata->bright >= 0) -+		input_set_capability(input, EV_KEY, BTN_RIGHT); -+ -+	error = input_register_polled_device(input_poll); -+	if (error) { -+		dev_err(&pdev->dev, "could not register input device\n"); -+		goto out_free_polldev; -+	} -+ -+	dev_dbg(&pdev->dev, "%d ms scan time, buttons: %s%s%s\n", -+			pdata->scan_ms, -+			pdata->bleft < 0 ? "" : "left ", -+			pdata->bmiddle < 0 ? "" : "middle ", -+			pdata->bright < 0 ? "" : "right"); -+ -+	return 0; -+ -+ out_free_polldev: -+	input_free_polled_device(input_poll); -+	platform_set_drvdata(pdev, NULL); -+ -+ out_free_gpios: -+	while (--i >= 0) { -+		pin = pdata->pins[i]; -+		if (pin) -+			gpio_free(pin); -+	} -+ out: -+	return error; -+} -+ -+static int __devexit gpio_mouse_remove(struct platform_device *pdev) -+{ -+	struct input_polled_dev *input = platform_get_drvdata(pdev); -+	struct gpio_mouse_platform_data *pdata = input->private; -+	int pin, i; -+ -+	input_unregister_polled_device(input); -+	input_free_polled_device(input); -+ -+	for (i = 0; i < GPIO_MOUSE_PIN_MAX; i++) { -+		pin = pdata->pins[i]; -+		if (pin >= 0) -+			gpio_free(pin); -+	} -+ -+	platform_set_drvdata(pdev, NULL); -+ -+	return 0; -+} -+ -+struct platform_driver gpio_mouse_device_driver = { -+	.remove		= __devexit_p(gpio_mouse_remove), -+	.driver		= { -+		.name	= "gpio_mouse", -+	} -+}; -+ -+static int __init gpio_mouse_init(void) -+{ -+	return platform_driver_probe(&gpio_mouse_device_driver, -+			gpio_mouse_probe); -+} -+module_init(gpio_mouse_init); -+ -+static void __exit gpio_mouse_exit(void) -+{ -+	platform_driver_unregister(&gpio_mouse_device_driver); -+} -+module_exit(gpio_mouse_exit); -+ -+MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>"); -+MODULE_DESCRIPTION("GPIO mouse driver"); -+MODULE_LICENSE("GPL"); -diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig -index 87d2046..9ce3ca1 100644 ---- a/drivers/leds/Kconfig -+++ b/drivers/leds/Kconfig -@@ -95,6 +95,14 @@ config LEDS_COBALT - 	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 --git a/drivers/leds/Makefile b/drivers/leds/Makefile -index aa2c18e..f8995c9 100644 ---- a/drivers/leds/Makefile -+++ b/drivers/leds/Makefile -@@ -16,6 +16,7 @@ obj-$(CONFIG_LEDS_NET48XX)		+= leds-net48xx.o - 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 --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c -new file mode 100644 -index 0000000..47d90db ---- /dev/null -+++ b/drivers/leds/leds-gpio.c -@@ -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 --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig -index 616eee9..0810d83 100644 ---- a/drivers/misc/Kconfig -+++ b/drivers/misc/Kconfig -@@ -187,5 +187,15 @@ config THINKPAD_ACPI_BAY -  - 	  If you are not sure, say Y here. -  -+config ATMEL_SSC -+	tristate "Device driver for Atmel SSC peripheral" -+	depends on AVR32 || ARCH_AT91 -+	---help--- -+	  This option enables device driver support for Atmel Syncronized -+	  Serial Communication peripheral (SSC). -+ -+	  The SSC peripheral supports a wide variety of serial frame based -+	  communications, i.e. I2S, SPI, etc. -  -+	  If unsure, say N. - endmenu -diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile -index 8abbf2f..2d52cc6 100644 ---- a/drivers/misc/Makefile -+++ b/drivers/misc/Makefile -@@ -14,3 +14,4 @@ obj-$(CONFIG_PHANTOM)		+= phantom.o - obj-$(CONFIG_SGI_IOC4)		+= ioc4.o - obj-$(CONFIG_SONY_LAPTOP)	+= sony-laptop.o - obj-$(CONFIG_THINKPAD_ACPI)	+= thinkpad_acpi.o -+obj-$(CONFIG_ATMEL_SSC)		+= atmel-ssc.o -diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c -new file mode 100644 -index 0000000..058ccac ---- /dev/null -+++ b/drivers/misc/atmel-ssc.c -@@ -0,0 +1,174 @@ -+/* -+ * Atmel SSC driver -+ * -+ * 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/platform_device.h> -+#include <linux/list.h> -+#include <linux/clk.h> -+#include <linux/err.h> -+#include <linux/io.h> -+#include <linux/list.h> -+#include <linux/spinlock.h> -+#include <linux/atmel-ssc.h> -+ -+/* Serialize access to ssc_list and user count */ -+static DEFINE_SPINLOCK(user_lock); -+static LIST_HEAD(ssc_list); -+ -+struct ssc_device *ssc_request(unsigned int ssc_num) -+{ -+	int ssc_valid = 0; -+	struct ssc_device *ssc; -+ -+	spin_lock(&user_lock); -+	list_for_each_entry(ssc, &ssc_list, list) { -+		if (ssc->pdev->id == ssc_num) { -+			ssc_valid = 1; -+			break; -+		} -+	} -+ -+	if (!ssc_valid) { -+		spin_unlock(&user_lock); -+		dev_dbg(&ssc->pdev->dev, "could not find requested device\n"); -+		return ERR_PTR(-ENODEV); -+	} -+ -+	if (ssc->user) { -+		spin_unlock(&user_lock); -+		dev_dbg(&ssc->pdev->dev, "module busy\n"); -+		return ERR_PTR(-EBUSY); -+	} -+	ssc->user++; -+	spin_unlock(&user_lock); -+ -+	clk_enable(ssc->clk); -+ -+	return ssc; -+} -+EXPORT_SYMBOL(ssc_request); -+ -+void ssc_free(struct ssc_device *ssc) -+{ -+	spin_lock(&user_lock); -+	if (ssc->user) { -+		ssc->user--; -+		clk_disable(ssc->clk); -+	} else { -+		dev_dbg(&ssc->pdev->dev, "device already free\n"); -+	} -+	spin_unlock(&user_lock); -+} -+EXPORT_SYMBOL(ssc_free); -+ -+static int __init ssc_probe(struct platform_device *pdev) -+{ -+	int retval = 0; -+	struct resource *regs; -+	struct ssc_device *ssc; -+ -+	ssc = kzalloc(sizeof(struct ssc_device), GFP_KERNEL); -+	if (!ssc) { -+		dev_dbg(&pdev->dev, "out of memory\n"); -+		retval = -ENOMEM; -+		goto out; -+	} -+ -+	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+	if (!regs) { -+		dev_dbg(&pdev->dev, "no mmio resource defined\n"); -+		retval = -ENXIO; -+		goto out_free; -+	} -+ -+	ssc->clk = clk_get(&pdev->dev, "pclk"); -+	if (IS_ERR(ssc->clk)) { -+		dev_dbg(&pdev->dev, "no pclk clock defined\n"); -+		retval = -ENXIO; -+		goto out_free; -+	} -+ -+	ssc->pdev = pdev; -+	ssc->regs = ioremap(regs->start, regs->end - regs->start + 1); -+	if (!ssc->regs) { -+		dev_dbg(&pdev->dev, "ioremap failed\n"); -+		retval = -EINVAL; -+		goto out_clk; -+	} -+ -+	/* disable all interrupts */ -+	clk_enable(ssc->clk); -+	ssc_writel(ssc->regs, IDR, ~0UL); -+	ssc_readl(ssc->regs, SR); -+	clk_disable(ssc->clk); -+ -+	ssc->irq = platform_get_irq(pdev, 0); -+	if (!ssc->irq) { -+		dev_dbg(&pdev->dev, "could not get irq\n"); -+		retval = -ENXIO; -+		goto out_unmap; -+	} -+ -+	spin_lock(&user_lock); -+	list_add_tail(&ssc->list, &ssc_list); -+	spin_unlock(&user_lock); -+ -+	platform_set_drvdata(pdev, ssc); -+ -+	dev_info(&pdev->dev, "Atmel SSC device at 0x%p (irq %d)\n", -+			ssc->regs, ssc->irq); -+ -+	goto out; -+ -+out_unmap: -+	iounmap(ssc->regs); -+out_clk: -+	clk_put(ssc->clk); -+out_free: -+	kfree(ssc); -+out: -+	return retval; -+} -+ -+static int __devexit ssc_remove(struct platform_device *pdev) -+{ -+	struct ssc_device *ssc = platform_get_drvdata(pdev); -+ -+	spin_lock(&user_lock); -+	iounmap(ssc->regs); -+	clk_put(ssc->clk); -+	list_del(&ssc->list); -+	kfree(ssc); -+	spin_unlock(&user_lock); -+ -+	return 0; -+} -+ -+static struct platform_driver ssc_driver = { -+	.remove		= __devexit_p(ssc_remove), -+	.driver		= { -+		.name		= "ssc", -+	}, -+}; -+ -+static int __init ssc_init(void) -+{ -+	return platform_driver_probe(&ssc_driver, ssc_probe); -+} -+module_init(ssc_init); -+ -+static void __exit ssc_exit(void) -+{ -+	platform_driver_unregister(&ssc_driver); -+} -+module_exit(ssc_exit); -+ -+MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>"); -+MODULE_DESCRIPTION("SSC driver for Atmel AVR32 and AT91"); -+MODULE_LICENSE("GPL"); -diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig -index e23082f..1de1716 100644 ---- a/drivers/mmc/host/Kconfig -+++ b/drivers/mmc/host/Kconfig -@@ -74,6 +74,16 @@ config MMC_AT91 -  - 	  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 --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile -index 6685f64..4b8e6e2 100644 ---- a/drivers/mmc/host/Makefile -+++ b/drivers/mmc/host/Makefile -@@ -14,5 +14,6 @@ obj-$(CONFIG_MMC_WBSD)		+= wbsd.o - 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 --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c -new file mode 100644 -index 0000000..74d343f ---- /dev/null -+++ b/drivers/mmc/host/atmel-mci.c -@@ -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 --git a/drivers/mmc/host/atmel-mci.h b/drivers/mmc/host/atmel-mci.h -new file mode 100644 -index 0000000..60d15c4 ---- /dev/null -+++ b/drivers/mmc/host/atmel-mci.h -@@ -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 --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c -index 2f19fa7..94304ca 100644 ---- a/drivers/mtd/chips/cfi_cmdset_0001.c -+++ b/drivers/mtd/chips/cfi_cmdset_0001.c -@@ -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 @@ static void cfi_tell_features(struct cfi_pri_intelext *extp) - } - #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 void fixup_use_powerup_lock(struct mtd_info *mtd, void *param) - } -  - 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 --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c -index 1f64458..205977b 100644 ---- a/drivers/mtd/chips/cfi_cmdset_0002.c -+++ b/drivers/mtd/chips/cfi_cmdset_0002.c -@@ -185,6 +185,10 @@ static void fixup_convert_atmel_pri(struct mtd_info *mtd, void *param) - 		extp->TopBottom = 2; - 	else - 		extp->TopBottom = 3; -+ -+	/* burst write mode not supported */ -+	cfi->cfiq->BufWriteTimeoutTyp = 0; -+	cfi->cfiq->BufWriteTimeoutMax = 0; - } -  - static void fixup_use_secsi(struct mtd_info *mtd, void *param) -@@ -217,6 +221,7 @@ static void fixup_use_atmel_lock(struct mtd_info *mtd, void *param) - } -  - 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 @@ static struct cfi_fixup cfi_fixup_table[] = { - #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 --git a/drivers/net/Kconfig b/drivers/net/Kconfig -index b49375a..b9cb56a 100644 ---- a/drivers/net/Kconfig -+++ b/drivers/net/Kconfig -@@ -191,7 +191,7 @@ config MII - 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 --git a/drivers/net/macb.c b/drivers/net/macb.c -index 0e04f7a..c20a585 100644 ---- a/drivers/net/macb.c -+++ b/drivers/net/macb.c -@@ -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 @@ static void __init macb_get_hwaddr(struct macb *bp) - 		memcpy(bp->dev->dev_addr, addr, sizeof(addr)); - } -  --static void macb_enable_mdio(struct macb *bp) -+static int macb_mdio_read(struct mii_bus *bus, int mii_id, int regnum) - { --	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) --{ --	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_completion(&bp->mdio_complete); -+	/* wait for end of transfer */ -+	while (!MACB_BFEXT(IDLE, macb_readl(bp, NSR))) -+		cpu_relax(); -  --	macb_disable_mdio(bp); --	mutex_unlock(&bp->mdio_mutex); -+	return 0; - } -  --static int macb_phy_probe(struct macb *bp) -+static int macb_mdio_reset(struct mii_bus *bus) - { --	int phy_address; --	u16 phyid1, phyid2; -+	return 0; -+} -  --	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); -+static void macb_handle_link_change(struct net_device *dev) -+{ -+	struct macb *bp = netdev_priv(dev); -+	struct phy_device *phydev = bp->phy_dev; -+	unsigned long flags; -  --		if (phyid1 != 0xffff && phyid1 != 0x0000 --		    && phyid2 != 0xffff && phyid2 != 0x0000) --			break; -+	int status_change = 0; -+ -+	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 @@ static void macb_update_stats(struct macb *bp) - 		*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 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) - 	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 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) - 				 * 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 @@ static void macb_init_hw(struct macb *bp) - 	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,126 @@ static void macb_init_hw(struct macb *bp) - 			      | MACB_BIT(TCOMP) - 			      | MACB_BIT(ISR_ROVR) - 			      | MACB_BIT(HRESP))); -+ - } -  --static void macb_init_phy(struct net_device *dev) -+/* -+ * The hash address register is 64 bits long and takes up two -+ * locations in the memory map.  The least significant bits are stored -+ * in EMAC_HSL and the most significant bits in EMAC_HSH. -+ * -+ * The unicast hash enable and the multicast hash enable bits in the -+ * network configuration register enable the reception of hash matched -+ * frames. The destination address is reduced to a 6 bit index into -+ * the 64 bit hash register using the following hash function.  The -+ * hash function is an exclusive or of every sixth bit of the -+ * destination address. -+ * -+ * hi[5] = da[5] ^ da[11] ^ da[17] ^ da[23] ^ da[29] ^ da[35] ^ da[41] ^ da[47] -+ * hi[4] = da[4] ^ da[10] ^ da[16] ^ da[22] ^ da[28] ^ da[34] ^ da[40] ^ da[46] -+ * hi[3] = da[3] ^ da[09] ^ da[15] ^ da[21] ^ da[27] ^ da[33] ^ da[39] ^ da[45] -+ * hi[2] = da[2] ^ da[08] ^ da[14] ^ da[20] ^ da[26] ^ da[32] ^ da[38] ^ da[44] -+ * hi[1] = da[1] ^ da[07] ^ da[13] ^ da[19] ^ da[25] ^ da[31] ^ da[37] ^ da[43] -+ * hi[0] = da[0] ^ da[06] ^ da[12] ^ da[18] ^ da[24] ^ da[30] ^ da[36] ^ da[42] -+ * -+ * da[0] represents the least significant bit of the first byte -+ * received, that is, the multicast/unicast indicator, and da[47] -+ * represents the most significant bit of the last byte received.  If -+ * the hash index, hi[n], points to a bit that is set in the hash -+ * register then the frame will be matched according to whether the -+ * frame is multicast or unicast.  A multicast match will be signalled -+ * if the multicast hash enable bit is set, da[0] is 1 and the hash -+ * index points to a bit set in the hash register.  A unicast match -+ * will be signalled if the unicast hash enable bit is set, da[0] is 0 -+ * and the hash index points to a bit set in the hash register.  To -+ * receive all multicast frames, the hash register should be set with -+ * all ones and the multicast hash enable bit should be set in the -+ * network configuration register. -+ */ -+ -+static inline int hash_bit_value(int bitnr, __u8 *addr) - { -+	if (addr[bitnr / 8] & (1 << (bitnr % 8))) -+		return 1; -+	return 0; -+} -+ -+/* -+ * Return the hash index value for the specified address. -+ */ -+static int hash_get_index(__u8 *addr) -+{ -+	int i, j, bitval; -+	int hash_index = 0; -+ -+	for (j = 0; j < 6; j++) { -+		for (i = 0, bitval = 0; i < 8; i++) -+			bitval ^= hash_bit_value(i*6 + j, addr); -+ -+		hash_index |= (bitval << j); -+	} -+ -+	return hash_index; -+} -+ -+/* -+ * Add multicast addresses to the internal multicast-hash table. -+ */ -+static void macb_sethashtable(struct net_device *dev) -+{ -+	struct dev_mc_list *curr; -+	unsigned long mc_filter[2]; -+	unsigned int i, bitnr; -+	struct macb *bp = netdev_priv(dev); -+ -+	mc_filter[0] = mc_filter[1] = 0; -+ -+	curr = dev->mc_list; -+	for (i = 0; i < dev->mc_count; i++, curr = curr->next) { -+		if (!curr) break;	/* unexpected end of list */ -+ -+		bitnr = hash_get_index(curr->dmi_addr); -+		mc_filter[bitnr >> 5] |= 1 << (bitnr & 31); -+	} -+ -+	macb_writel(bp, HRB, mc_filter[0]); -+	macb_writel(bp, HRT, mc_filter[1]); -+} -+ -+/* -+ * Enable/Disable promiscuous and multicast modes. -+ */ -+static void macb_set_rx_mode(struct net_device *dev) -+{ -+	unsigned long cfg; - 	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)); -+	cfg = macb_readl(bp, NCFGR); -+ -+	if (dev->flags & IFF_PROMISC) -+		/* Enable promiscuous mode */ -+		cfg |= MACB_BIT(CAF); -+	else if (dev->flags & (~IFF_PROMISC)) -+		 /* Disable promiscuous mode */ -+		cfg &= ~MACB_BIT(CAF); -+ -+	if (dev->flags & IFF_ALLMULTI) { -+		/* Enable all multicast mode */ -+		macb_writel(bp, HRB, -1); -+		macb_writel(bp, HRT, -1); -+		cfg |= MACB_BIT(NCFGR_MTI); -+	} else if (dev->mc_count > 0) { -+		/* Enable specific multicasts */ -+		macb_sethashtable(dev); -+		cfg |= MACB_BIT(NCFGR_MTI); -+	} else if (dev->flags & (~IFF_ALLMULTI)) { -+		/* Disable all multicast mode */ -+		macb_writel(bp, HRB, 0); -+		macb_writel(bp, HRT, 0); -+		cfg &= ~MACB_BIT(NCFGR_MTI); -+	} -+ -+	macb_writel(bp, NCFGR, cfg); - } -  - static int macb_open(struct net_device *dev) -@@ -797,6 +924,10 @@ static int macb_open(struct net_device *dev) -  - 	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 +941,11 @@ static int macb_open(struct net_device *dev) -  - 	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 +955,11 @@ static int macb_close(struct net_device *dev) - 	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 +976,9 @@ static struct net_device_stats *macb_get_stats(struct net_device *dev) - 	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 +1016,27 @@ static struct net_device_stats *macb_get_stats(struct net_device *dev) - 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; -  --	return mii_ethtool_sset(&bp->mii, cmd); -+	if (!phydev) -+		return -ENODEV; -+ -+	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 +1045,34 @@ static void macb_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *inf - 	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; -@@ -1073,6 +1146,7 @@ static int __devinit macb_probe(struct platform_device *pdev) - 	dev->stop = macb_close; - 	dev->hard_start_xmit = macb_start_xmit; - 	dev->get_stats = macb_get_stats; -+	dev->set_multicast_list = macb_set_rx_mode; - 	dev->do_ioctl = macb_ioctl; - 	dev->poll = macb_poll; - 	dev->weight = 64; -@@ -1080,10 +1154,6 @@ static int __devinit macb_probe(struct platform_device *pdev) -  - 	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 +1166,9 @@ static int __devinit macb_probe(struct platform_device *pdev) - 		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 +1190,11 @@ static int __devinit macb_probe(struct platform_device *pdev) - 		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 +1202,15 @@ static int __devinit macb_probe(struct platform_device *pdev) - 	       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 +1221,9 @@ err_out_disable_clocks: - 	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 +1241,8 @@ static int __devexit macb_remove(struct platform_device *pdev) -  - 	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 --git a/drivers/net/macb.h b/drivers/net/macb.h -index b3bb218..4e3283e 100644 ---- a/drivers/net/macb.h -+++ b/drivers/net/macb.h -@@ -383,11 +383,11 @@ struct macb { -  - 	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 --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig -index 4e4c10a..6d014fb 100644 ---- a/drivers/rtc/Kconfig -+++ b/drivers/rtc/Kconfig -@@ -379,6 +379,13 @@ config RTC_DRV_PL031 - 	  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 --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile -index a1afbc2..5fb1c10 100644 ---- a/drivers/rtc/Makefile -+++ b/drivers/rtc/Makefile -@@ -19,6 +19,7 @@ obj-$(CONFIG_RTC_DRV_CMOS)	+= rtc-cmos.o - 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 --git a/drivers/rtc/rtc-at32ap700x.c b/drivers/rtc/rtc-at32ap700x.c -new file mode 100644 -index 0000000..2999214 ---- /dev/null -+++ b/drivers/rtc/rtc-at32ap700x.c -@@ -0,0 +1,317 @@ -+/* -+ * 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 -+ -+#define RTC_VAL			0x04 -+ -+#define RTC_TOP			0x08 -+ -+#define RTC_IER			0x10 -+#define RTC_IER_TOPI		   0 -+ -+#define RTC_IDR			0x14 -+#define RTC_IDR_TOPI		   0 -+ -+#define RTC_IMR			0x18 -+#define RTC_IMR_TOPI		   0 -+ -+#define RTC_ISR			0x1c -+#define RTC_ISR_TOPI		   0 -+ -+#define RTC_ICR			0x20 -+#define RTC_ICR_TOPI		   0 -+ -+#define RTC_BIT(name)		(1 << RTC_##name) -+#define RTC_BF(name, value)	((value) << RTC_##name) -+ -+#define rtc_readl(dev, reg)				\ -+	__raw_readl((dev)->regs + RTC_##reg) -+#define rtc_writel(dev, reg, value)			\ -+	__raw_writel((value), (dev)->regs + RTC_##reg) -+ -+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; -+}; -+ -+static int at32_rtc_readtime(struct device *dev, struct rtc_time *tm) -+{ -+	struct rtc_at32ap700x *rtc = dev_get_drvdata(dev); -+	unsigned long now; -+ -+	now = rtc_readl(rtc, VAL); -+	rtc_time_to_tm(now, tm); -+ -+	return 0; -+} -+ -+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; -+ -+	ret = rtc_tm_to_time(tm, &now); -+	if (ret == 0) -+		rtc_writel(rtc, VAL, now); -+ -+	return ret; -+} -+ -+static int at32_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) -+{ -+	struct rtc_at32ap700x *rtc = dev_get_drvdata(dev); -+ -+	rtc_time_to_tm(rtc->alarm_time, &alrm->time); -+	alrm->pending = rtc_readl(rtc, IMR) & RTC_BIT(IMR_TOPI) ? 1 : 0; -+ -+	return 0; -+} -+ -+static int at32_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) -+{ -+	struct rtc_at32ap700x *rtc = dev_get_drvdata(dev); -+	unsigned long rtc_unix_time; -+	unsigned long alarm_unix_time; -+	int ret; -+ -+	rtc_unix_time = rtc_readl(rtc, VAL); -+ -+	ret = rtc_tm_to_time(&alrm->time, &alarm_unix_time); -+	if (ret) -+		return ret; -+ -+	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 int at32_rtc_ioctl(struct device *dev, unsigned int cmd, -+			unsigned long arg) -+{ -+	struct rtc_at32ap700x *rtc = dev_get_drvdata(dev); -+	int ret = 0; -+ -+	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 irqreturn_t at32_rtc_interrupt(int irq, void *dev_id) -+{ -+	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 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 __init at32_rtc_probe(struct platform_device *pdev) -+{ -+	struct resource	*regs; -+	struct rtc_at32ap700x *rtc; -+	int irq = -1; -+	int ret; -+ -+	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; -+	} -+ -+	irq = platform_get_irq(pdev, 0); -+	if (irq < 0) { -+		dev_dbg(&pdev->dev, "could not get irq\n"); -+		ret = -ENXIO; -+		goto out; -+	} -+ -+	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; -+	} -+ -+	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); -+ -+	/* -+	 * 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)); -+	} -+ -+	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; -+	} -+ -+	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 __exit at32_rtc_remove(struct platform_device *pdev) -+{ -+	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; -+} -+ -+MODULE_ALIAS("at32ap700x_rtc"); -+ -+static struct platform_driver at32_rtc_driver = { -+	.remove		= __exit_p(at32_rtc_remove), -+	.driver		= { -+		.name	= "at32ap700x_rtc", -+		.owner	= THIS_MODULE, -+	}, -+}; -+ -+static int __init at32_rtc_init(void) -+{ -+	return platform_driver_probe(&at32_rtc_driver, at32_rtc_probe); -+} -+module_init(at32_rtc_init); -+ -+static void __exit at32_rtc_exit(void) -+{ -+	platform_driver_unregister(&at32_rtc_driver); -+} -+module_exit(at32_rtc_exit); -+ -+MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>"); -+MODULE_DESCRIPTION("Real time clock for AVR32 AT32AP700x"); -+MODULE_LICENSE("GPL"); -diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c -index 3320bcd..4d6b3c5 100644 ---- a/drivers/serial/atmel_serial.c -+++ b/drivers/serial/atmel_serial.c -@@ -114,6 +114,7 @@ struct atmel_uart_port { - 	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_break_ctl(struct uart_port *port, int break_state) -  */ - 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 @@ static void atmel_rx_chars(struct uart_port *port) - 		 * 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 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id) - 		/* 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 --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c -index 8b2601d..8f5453f 100644 ---- a/drivers/spi/atmel_spi.c -+++ b/drivers/spi/atmel_spi.c -@@ -412,8 +412,8 @@ static int atmel_spi_setup(struct spi_device *spi) - 		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 --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig -index f771a7c..0c3d55b 100644 ---- a/drivers/usb/gadget/Kconfig -+++ b/drivers/usb/gadget/Kconfig -@@ -175,6 +175,19 @@ config USB_LH7A40X - 	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 --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile -index 5db1939..c28da01 100644 ---- a/drivers/usb/gadget/Makefile -+++ b/drivers/usb/gadget/Makefile -@@ -8,6 +8,7 @@ obj-$(CONFIG_USB_GOKU)		+= goku_udc.o - 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 --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c -new file mode 100644 -index 0000000..34dbae3 ---- /dev/null -+++ b/drivers/usb/gadget/atmel_usba_udc.c -@@ -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 */ -+ -+#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> -+ -+#include <asm/gpio.h> -+#include <asm/arch/board.h> -+ -+#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 -+ -+static struct usba_udc the_udc; -+ -+#ifdef CONFIG_DEBUG_FS -+#include <linux/debugfs.h> -+#include <linux/uaccess.h> -+ -+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); -+ -+	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); -+ -+	file->private_data = queue_data; -+	return 0; -+ -+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; -+} -+ -+/* -+ * 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) -+{ -+	struct list_head *queue = file->private_data; -+	struct usba_request *req, *tmp_req; -+	size_t len, remaining, actual = 0; -+	char tmpbuf[38]; -+ -+	if (!access_ok(VERIFY_WRITE, buf, nbytes)) -+		return -EFAULT; -+ -+	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; -+ -+		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); -+ -+	return actual; -+} -+ -+static int queue_dbg_release(struct inode *inode, struct file *file) -+{ -+	struct list_head *queue_data = file->private_data; -+	struct usba_request *req, *tmp_req; -+ -+	list_for_each_entry_safe(req, tmp_req, queue_data, queue) { -+		list_del(&req->queue); -+		kfree(req); -+	} -+	kfree(queue_data); -+	return 0; -+} -+ -+static int regs_dbg_open(struct inode *inode, struct file *file) -+{ -+	struct usba_udc *udc; -+	unsigned int i; -+	u32 *data; -+	int ret = -ENOMEM; -+ -+	mutex_lock(&inode->i_mutex); -+	udc = inode->i_private; -+	data = kmalloc(inode->i_size, GFP_KERNEL); -+	if (!data) -+		goto out; -+ -+	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); -+ -+	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; -+} -+ -+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, -+}; -+ -+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 usba_ep_init_debugfs(struct usba_udc *udc, -+				  struct usba_ep *ep) -+{ -+	struct dentry *ep_root; -+ -+	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; -+	} -+ -+	return; -+ -+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 usba_ep_cleanup_debugfs(struct usba_ep *ep) -+{ -+	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; -+} -+ -+static void usba_init_debugfs(struct usba_udc *udc) -+{ -+	struct dentry *root, *regs; -+	struct resource *regs_resource; -+ -+	root = debugfs_create_dir(udc->gadget.name, NULL); -+	if (IS_ERR(root) || !root) -+		goto err_root; -+	udc->debugfs_root = root; -+ -+	regs = debugfs_create_file("regs", 0400, root, udc, ®s_dbg_fops); -+	if (!regs) -+		goto err_regs; -+ -+	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; -+ -+	usba_ep_init_debugfs(udc, to_usba_ep(udc->gadget.ep0)); -+ -+	return; -+ -+err_regs: -+	debugfs_remove(root); -+err_root: -+	udc->debugfs_root = NULL; -+	dev_err(&udc->pdev->dev, "debugfs is not available\n"); -+} -+ -+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) -+{ -+ -+} -+ -+static inline void usba_ep_cleanup_debugfs(struct usba_ep *ep) -+{ -+ -+} -+ -+static inline void usba_init_debugfs(struct usba_udc *udc) -+{ -+ -+} -+ -+static inline void usba_cleanup_debugfs(struct usba_udc *udc) -+{ -+ -+} -+#endif -+ -+static int vbus_is_present(struct usba_udc *udc) -+{ -+	if (udc->vbus_pin != -1) -+		return gpio_get_value(udc->vbus_pin); -+ -+	/* No Vbus detection: Assume always present */ -+	return 1; -+} -+ -+static void copy_to_fifo(void __iomem *fifo, const void *buf, int len) -+{ -+	unsigned long tmp; -+ -+	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 copy_from_fifo(void *buf, void __iomem *fifo, int len) -+{ -+	union { -+		unsigned long *w; -+		unsigned char *b; -+	} p; -+	unsigned long tmp; -+ -+	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 next_fifo_transaction(struct usba_ep *ep, -+				  struct usba_request *req) -+{ -+	unsigned int transaction_len; -+ -+	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 submit_request(struct usba_ep *ep, struct usba_request *req) -+{ -+	DBG(DBG_QUEUE, "%s: submit_request: req %p (length %d)\n", -+	    ep_name(ep), req, req->req.length); -+ -+	req->req.actual = 0; -+	req->submitted = 1; -+ -+	if (req->using_dma) { -+		if (req->req.length == 0) { -+			usba_ep_writel(ep, CTL_ENB, USBA_BIT(TX_PK_RDY)); -+			return; -+		} -+ -+		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)); -+ -+		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)); -+		} -+	} -+} -+ -+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; -+	} -+ -+	req = list_entry(ep->queue.next, struct usba_request, queue); -+	if (!req->submitted) -+		submit_request(ep, req); -+} -+ -+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)); -+} -+ -+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; -+ -+	status = usba_ep_readl(ep, STA); -+	nr_busy = USBA_BFEXT(BUSY_BANKS, status); -+ -+	DBG(DBG_QUEUE, "receive data: nr_busy=%u\n", nr_busy); -+ -+	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); -+ -+		bytecount = USBA_BFEXT(BYTE_COUNT, status); -+ -+		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; -+		} -+ -+		copy_from_fifo(req->req.buf + req->req.actual, -+			       ep->fifo, bytecount); -+		req->req.actual += bytecount; -+ -+		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); -+		} -+ -+		status = usba_ep_readl(ep, STA); -+		nr_busy = USBA_BFEXT(BUSY_BANKS, status); -+ -+		if (is_complete && ep_is_control(ep)) { -+			send_status(udc, ep); -+			break; -+		} -+	} -+} -+ -+static void request_complete(struct usba_ep *ep, -+			     struct usba_request *req, -+			     int status) -+{ -+	struct usba_udc *udc = ep->udc; -+ -+	WARN_ON(!list_empty(&req->queue)); -+ -+	if (req->req.status == -EINPROGRESS) -+		req->req.status = status; -+ -+	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; -+	} -+ -+	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 request_complete_list(struct usba_ep *ep, -+				  struct list_head *list, -+				  int status) -+{ -+	struct usba_request *req, *tmp_req; -+ -+	list_for_each_entry_safe(req, tmp_req, list, queue) { -+		list_del_init(&req->queue); -+		request_complete(ep, req, status); -+	} -+} -+ -+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; -+ -+	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 { -+		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 struct usb_request * -+usba_ep_alloc_request(struct usb_ep *_ep, unsigned gfp_flags) -+{ -+	struct usba_request *req; -+ -+	DBG(DBG_GADGET, "ep_alloc_request: %p, 0x%x\n", _ep, gfp_flags); -+ -+	req = kzalloc(sizeof(*req), gfp_flags); -+	if (!req) -+		return NULL; -+ -+	INIT_LIST_HEAD(&req->queue); -+	req->req.dma = DMA_ADDR_INVALID; -+ -+	return &req->req; -+} -+ -+static void -+usba_ep_free_request(struct usb_ep *_ep, struct usb_request *_req) -+{ -+	struct usba_request *req = to_usba_req(_req); -+ -+	DBG(DBG_GADGET, "ep_free_request: %p, %p\n", _ep, _req); -+ -+	kfree(req); -+} -+ -+static void *usba_ep_alloc_buffer(struct usb_ep *_ep, unsigned bytes, -+				   dma_addr_t *dma, unsigned gfp_flags) -+{ -+	void *buf; -+ -+	if (bytes < L1_CACHE_BYTES) -+		bytes = L1_CACHE_BYTES; -+ -+	buf = kmalloc(bytes, gfp_flags); -+ -+	/* -+	 * 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 void usba_ep_free_buffer(struct usb_ep *_ep, void *buf, -+				 dma_addr_t dma, unsigned bytes) -+{ -+	DBG(DBG_GADGET, "ep_free_buffer: %s, buf %p (size %u)\n", -+	    _ep->name, buf, bytes); -+	kfree(buf); -+} -+ -+static int queue_dma(struct usba_udc *udc, struct usba_ep *ep, -+		     struct usba_request *req, gfp_t gfp_flags) -+{ -+	unsigned long flags; -+	int ret; -+ -+	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'); -+ -+	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; -+	} -+ -+	req->using_dma = 1; -+ -+	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 { -+		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; -+	} -+ -+	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; -+	} -+	spin_unlock_irqrestore(&udc->lock, flags); -+ -+	return ret; -+} -+ -+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; -+ -+	DBG(DBG_GADGET | DBG_QUEUE | DBG_REQ, -+	    "%s: queue req %p, len %u\n", ep_name(ep), req, _req->length); -+ -+	if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN -+	    || !ep->desc) -+		return -ESHUTDOWN; -+ -+	req->submitted = 0; -+	req->using_dma = 0; -+	req->last_transaction = 0; -+ -+	_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); -+ -+	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); -+	} -+ -+	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; -+	} -+ -+	return 0; -+} -+ -+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; -+ -+	DBG(DBG_GADGET | DBG_QUEUE, "ep_dequeue: %s, req %p\n", -+	    ep_name(ep), req); -+ -+	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); -+		} -+	} -+ -+	/* -+	 * Errors should stop the queue from advancing until the -+	 * completion function returns. -+	 */ -+	list_del_init(&req->queue); -+	spin_unlock_irqrestore(&udc->lock, flags); -+ -+	request_complete(ep, req, -ECONNRESET); -+ -+	/* Process the next request if any */ -+	spin_lock_irqsave(&udc->lock, flags); -+	submit_next_request(ep); -+	spin_unlock_irqrestore(&udc->lock, flags); -+ -+	return 0; -+} -+ -+static int usba_ep_set_halt(struct usb_ep *_ep, int value) -+{ -+	struct usba_ep *ep = to_usba_ep(_ep); -+	struct usba_udc *udc = ep->udc; -+	unsigned long flags; -+	int ret = 0; -+ -+	DBG(DBG_GADGET, "endpoint %s: %s HALT\n", ep_name(ep), -+	    value ? "set" : "clear"); -+ -+	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; -+	} -+ -+	spin_lock_irqsave(&udc->lock, flags); -+ -+	/* -+	 * 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); -+	} -+ -+	spin_unlock_irqrestore(&udc->lock, flags); -+ -+	return ret; -+} -+ -+static int usba_ep_fifo_status(struct usb_ep *_ep) -+{ -+	struct usba_ep *ep = to_usba_ep(_ep); -+ -+	return USBA_BFEXT(BYTE_COUNT, usba_ep_readl(ep, STA)); -+} -+ -+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); -+} -+ -+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 usba_udc_get_frame(struct usb_gadget *gadget) -+{ -+	struct usba_udc *udc = to_usba_udc(gadget); -+ -+	return USBA_BFEXT(FRAME_NUMBER, usba_readl(udc, FNUM)); -+} -+ -+struct usb_gadget_ops usba_udc_ops = { -+	.get_frame	= usba_udc_get_frame, -+}; -+ -+#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, -+}; -+ -+static void nop_release(struct device *dev) -+{ -+ -+} -+ -+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, -+		}, -+	}, -+ -+	.lock	= SPIN_LOCK_UNLOCKED, -+}; -+ -+/* -+ * 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; -+ -+	usba_writel(udc, EPT_RST, ~0UL); -+ -+	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); -+	} -+ -+	list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) { -+		if (ep->desc) -+			usba_ep_disable(&ep->ep); -+	} -+} -+ -+static struct usba_ep *get_ep_by_addr(struct usba_udc *udc, u16 wIndex) -+{ -+	struct usba_ep *ep; -+ -+	if ((wIndex & USB_ENDPOINT_NUMBER_MASK) == 0) -+		return to_usba_ep(udc->gadget.ep0); -+ -+	list_for_each_entry (ep, &udc->gadget.ep_list, ep.ep_list) { -+		u8 bEndpointAddress; -+ -+		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; -+	} -+ -+	return NULL; -+} -+ -+/* 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; -+} -+ -+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; -+} -+ -+static inline void set_address(struct usba_udc *udc, unsigned int addr) -+{ -+	u32 regval; -+ -+	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); -+} -+ -+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; -+ -+	/* Start from a clean slate */ -+	reset_all_endpoints(udc); -+ -+	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) -+{ -+	if (crq->wValue == __constant_cpu_to_le16(USB_DEVICE_REMOTE_WAKEUP)) -+		return true; -+	return false; -+} -+ -+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; -+} -+ -+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; -+} -+ -+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 (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; -+ -+			target = get_ep_by_addr(udc, le16_to_cpu(crq->wIndex)); -+			if (!target) -+				goto stall; -+ -+			status = 0; -+			if (is_stalled(udc, target)) -+				status |= __constant_cpu_to_le16(1); -+		} else { -+			goto delegate; -+		} -+ -+		/* 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; -+	} -+ -+	case USB_REQ_CLEAR_FEATURE: { -+		if (crq->bRequestType == USB_RECIP_DEVICE) { -+			if (feature_is_dev_remote_wakeup(crq)) { -+				/* TODO: Handle REMOTE_WAKEUP */ -+			} else { -+				/* 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; -+		} -+ -+		send_status(udc, ep); -+		break; -+	} -+ -+	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; -+ -+			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, SET_STA, USBA_BIT(FORCE_STALL)); -+		} else -+			goto delegate; -+ -+		send_status(udc, ep); -+		break; -+	} -+ -+	case USB_REQ_SET_ADDRESS: -+		if (crq->bRequestType != (USB_DIR_OUT | USB_RECIP_DEVICE)) -+			goto delegate; -+ -+		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; -+} -+ -+static void usba_control_irq(struct usba_udc *udc, struct usba_ep *ep) -+{ -+	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; -+		} -+ -+		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; -+ -+			/* -+			 * 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; -+			} -+ -+			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; -+		} -+ -+		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)); -+ -+		/* printk(KERN_DEBUG "setup: %d: %02x.%02x\n", -+		       ep->state, crq.crq.bRequestType, -+		       crq.crq.bRequest); */ -+ -+		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; -+		} -+ -+		ret = -1; -+		if (ep->index == 0) -+			ret = handle_ep0_setup(udc, ep, &crq.crq); -+		else -+			ret = udc->driver->setup(&udc->gadget, &crq.crq); -+ -+		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); -+ -+		if (ret < 0) { -+			/* Let the host know that we failed */ -+			set_protocol_stall(udc, ep); -+		} -+	} -+} -+ -+static void usba_ep_irq(struct usba_udc *udc, struct usba_ep *ep) -+{ -+	struct usba_request *req; -+	u32 epstatus; -+	u32 epctrl; -+ -+	epstatus = usba_ep_readl(ep, STA); -+	epctrl = usba_ep_readl(ep, CTL); -+ -+	DBG(DBG_INT, "%s: interrupt, status: 0x%08x\n", -+	    ep_name(ep), epstatus); -+ -+	while ((epctrl & USBA_BIT(TX_PK_RDY)) -+	       && !(epstatus & USBA_BIT(TX_PK_RDY))) { -+		DBG(DBG_BUS, "%s: TX PK ready\n", ep_name(ep)); -+ -+		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; -+		} -+ -+		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); -+ -+			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)); -+	} -+} -+ -+static void usba_dma_irq(struct usba_udc *udc, struct usba_ep *ep) -+{ -+	struct usba_request *req; -+	u32 status, control, pending; -+ -+	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); -+ -+	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); -+ -+		/* -+		 * try to pretend nothing happened. We might have to -+		 * do something here... -+		 */ -+	} -+ -+	if (list_empty(&ep->queue)) -+		/* Might happen if a reset comes along at the right moment */ -+		return; -+ -+	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); -+ -+		list_del_init(&req->queue); -+		submit_next_request(ep); -+		request_complete(ep, req, 0); -+	} -+} -+ -+static irqreturn_t usba_udc_irq(int irq, void *devid) -+{ -+	struct usba_udc *udc = devid; -+	u32 status; -+	u32 dma_status; -+	u32 ep_status; -+ -+	spin_lock(&udc->lock); -+ -+	status = usba_readl(udc, INT_STA); -+	DBG(DBG_INT, "irq, status=%#08x\n", status); -+ -+	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); -+	} -+ -+	if (status & USBA_BIT(WAKE_UP)) { -+		usba_writel(udc, INT_CLR, USBA_BIT(WAKE_UP)); -+		DBG(DBG_BUS, "Wake Up CPU detected\n"); -+	} -+ -+	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); -+	} -+ -+	dma_status = USBA_BFEXT(DMA_INT, status); -+	if (dma_status) { -+		int i; -+ -+		for (i = 1; i < USBA_NR_ENDPOINTS; i++) -+			if (dma_status & (1 << i)) -+				usba_dma_irq(udc, &usba_ep[i]); -+	} -+ -+	ep_status = USBA_BFEXT(EPT_INT, status); -+	if (ep_status) { -+		int i; -+ -+		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]); -+			} -+	} -+ -+	if (status & USBA_BIT(END_OF_RESET)) { -+		struct usba_ep *ep0; -+ -+		usba_writel(udc, INT_CLR, USBA_BIT(END_OF_RESET)); -+		reset_all_endpoints(udc); -+ -+		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; -+		} -+ -+		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"); -+	} -+ -+	spin_unlock(&udc->lock); -+ -+	return IRQ_HANDLED; -+} -+ -+static irqreturn_t usba_vbus_irq(int irq, void *devid) -+{ -+	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; -+} -+ -+int usb_gadget_register_driver(struct usb_gadget_driver *driver) -+{ -+	struct usba_udc *udc = &the_udc; -+	unsigned long flags; -+	int ret; -+ -+	if (!udc->pdev) -+		return -ENODEV; -+ -+	spin_lock_irqsave(&udc->lock, flags); -+	if (udc->driver) { -+		spin_unlock_irqrestore(&udc->lock, flags); -+		return -EBUSY; -+	} -+ -+	udc->driver = driver; -+	udc->gadget.dev.driver = &driver->driver; -+	spin_unlock_irqrestore(&udc->lock, flags); -+ -+	clk_enable(udc->pclk); -+	clk_enable(udc->hclk); -+ -+	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; -+	} -+ -+	DBG(DBG_GADGET, "registered driver `%s'\n", driver->driver.name); -+ -+	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"); -+		} -+	} -+ -+	/* 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; -+ -+err_driver_bind: -+	udc->driver = NULL; -+	udc->gadget.dev.driver = NULL; -+	return ret; -+} -+EXPORT_SYMBOL(usb_gadget_register_driver); -+ -+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) -+{ -+	struct usba_udc *udc = &the_udc; -+	unsigned long flags; -+ -+	if (!udc->pdev) -+		return -ENODEV; -+	if (driver != udc->driver) -+		return -EINVAL; -+ -+	if (udc->vbus_pin != -1) -+		free_irq(gpio_to_irq(udc->vbus_pin), udc); -+ -+	spin_lock_irqsave(&udc->lock, flags); -+	udc->gadget.speed = USB_SPEED_UNKNOWN; -+	reset_all_endpoints(udc); -+	spin_unlock_irqrestore(&udc->lock, flags); -+ -+	/* This will also disable the DP pullup */ -+	usba_writel(udc, CTRL, 0); -+ -+	driver->unbind(&udc->gadget); -+	udc->gadget.dev.driver = NULL; -+	udc->driver = NULL; -+ -+	clk_disable(udc->hclk); -+	clk_disable(udc->pclk); -+ -+	DBG(DBG_GADGET, "unregistered driver `%s'\n", driver->driver.name); -+ -+	return 0; -+} -+EXPORT_SYMBOL(usb_gadget_unregister_driver); -+ -+static int __devinit usba_udc_probe(struct platform_device *pdev) -+{ -+	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; -+ -+	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; -+ -+	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; -+	} -+ -+	udc->pdev = pdev; -+	udc->pclk = pclk; -+	udc->hclk = hclk; -+	udc->vbus_pin = -1; -+ -+	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; -+	} -+	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; -+	} -+	dev_info(&pdev->dev, "FIFO at 0x%08lx mapped at %p\n", -+		 (unsigned long)fifo->start, udc->fifo); -+ -+	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); -+ -+	/* Make sure we start from a clean slate */ -+	clk_enable(pclk); -+	usba_writel(udc, CTRL, 0); -+	clk_disable(pclk); -+ -+	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]; -+ -+		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); -+ -+		list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list); -+	} -+ -+	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; -+ -+	ret = device_add(&udc->gadget.dev); -+	if (ret) { -+		dev_dbg(&pdev->dev, "Could not add gadget: %d\n", ret); -+		goto err_device_add; -+	} -+ -+	if (pdata && pdata->vbus_pin != GPIO_PIN_NONE) -+		if (!gpio_request(pdata->vbus_pin, "atmel_usba_udc")) -+			udc->vbus_pin = pdata->vbus_pin; -+ -+	usba_init_debugfs(udc); -+	for (i = 1; i < ARRAY_SIZE(usba_ep); i++) -+		usba_ep_init_debugfs(udc, &usba_ep[i]); -+ -+	return 0; -+ -+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); -+ -+	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); -+ -+	if (udc->vbus_pin != -1) -+		gpio_free(udc->vbus_pin); -+ -+	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", -+	}, -+}; -+ -+static int __init udc_init(void) -+{ -+	return platform_driver_register(&udc_driver); -+} -+module_init(udc_init); -+ -+static void __exit udc_exit(void) -+{ -+	platform_driver_unregister(&udc_driver); -+} -+module_exit(udc_exit); -+ -+MODULE_DESCRIPTION("Atmel USBA UDC driver"); -+MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>"); -+MODULE_LICENSE("GPL"); -diff --git a/drivers/usb/gadget/atmel_usba_udc.h b/drivers/usb/gadget/atmel_usba_udc.h -new file mode 100644 -index 0000000..408d2ce ---- /dev/null -+++ b/drivers/usb/gadget/atmel_usba_udc.h -@@ -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 -+ -+/* 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 --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c -index 325bf7c..23e874b 100644 ---- a/drivers/usb/gadget/ether.c -+++ b/drivers/usb/gadget/ether.c -@@ -277,7 +277,7 @@ MODULE_PARM_DESC(host_addr, "Host Ethernet Address"); - #define DEV_CONFIG_CDC - #endif -  --#ifdef CONFIG_USB_GADGET_HUSB2DEV -+#ifdef CONFIG_USB_GADGET_ATMEL_USBA - #define DEV_CONFIG_CDC - #endif -  -diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h -index d041b91..96e4dbc 100644 ---- a/drivers/usb/gadget/gadget_chips.h -+++ b/drivers/usb/gadget/gadget_chips.h -@@ -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 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget) - 		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 --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c -index 46d0e52..855f8cc 100644 ---- a/drivers/usb/gadget/inode.c -+++ b/drivers/usb/gadget/inode.c -@@ -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 --git a/drivers/video/Kconfig b/drivers/video/Kconfig -index 403dac7..f3e2897 100644 ---- a/drivers/video/Kconfig -+++ b/drivers/video/Kconfig -@@ -849,6 +849,16 @@ config FB_INTSRAM - 	  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 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 --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c -index e1d5bd0..bb361ab 100644 ---- a/drivers/video/atmel_lcdfb.c -+++ b/drivers/video/atmel_lcdfb.c -@@ -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 @@ static struct fb_fix_screeninfo atmel_lcdfb_fix __initdata = { - 	.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 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var, - 	var->xoffset = var->yoffset = 0; -  - 	switch (var->bits_per_pixel) { -+	case 1: - 	case 2: - 	case 4: - 	case 8: -@@ -195,8 +221,11 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var, - 		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_check_var(struct fb_var_screeninfo *var, - 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 @@ static int atmel_lcdfb_set_par(struct fb_info *info) -  - 	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 @@ static int atmel_lcdfb_set_par(struct fb_info *info) - 	/* 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 { - 		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)); -+	} -+ -  - 	/* Initialize control register 2 */ - 	value = sinfo->default_lcdcon2; -@@ -311,9 +348,14 @@ static int atmel_lcdfb_set_par(struct fb_info *info) - 	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)); -+ - 	/* 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 @@ static int atmel_lcdfb_setcolreg(unsigned int regno, unsigned int red, - 			ret = 0; - 		} - 		break; -+ -+	case FB_VISUAL_MONO01: -+		if (regno < 2) { -+			val = (regno == 0) ? 0x00 : 0x1F; -+			lcdc_writel(sinfo, ATMEL_LCDC_LUT(regno), val); -+			ret = 0; -+		} -+		break; -+ - 	} -  - 	return ret; -diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig -index fbef663..b6f936a 100644 ---- a/drivers/video/backlight/Kconfig -+++ b/drivers/video/backlight/Kconfig -@@ -8,26 +8,44 @@ menuconfig BACKLIGHT_LCD_SUPPORT - 	  Enable this to be able to choose the drivers for controlling the - 	  backlight and the LCD panel on some platforms, for example on PDAs. -  --config BACKLIGHT_CLASS_DEVICE --        tristate "Lowlevel Backlight controls" -+# -+# LCD -+# -+config LCD_CLASS_DEVICE -+        tristate "Lowlevel LCD controls" - 	depends on BACKLIGHT_LCD_SUPPORT - 	default m - 	help --	  This framework adds support for low-level control of the LCD --          backlight. This includes support for brightness and power. -+	  This framework adds support for low-level control of LCD. -+	  Some framebuffer devices connect to platform-specific LCD modules -+	  in order to have a platform-specific way to control the flat panel -+	  (contrast and applying power to the LCD (not to the backlight!)). -  - 	  To have support for your specific LCD panel you will have to - 	  select the proper drivers which depend on this option. -  --config LCD_CLASS_DEVICE --        tristate "Lowlevel LCD controls" -+config LCD_LTV350QV -+	tristate "Samsung LTV350QV LCD Panel" -+	depends on LCD_CLASS_DEVICE && SPI_MASTER -+	default n -+	help -+	  If you have a Samsung LTV350QV LCD panel, say y to include a -+	  power control driver for it.  The panel starts up in power -+	  off state, so you need this driver in order to see any -+	  output. -+ -+	  The LTV350QV panel is present on all ATSTK1000 boards. -+ -+# -+# Backlight -+# -+config BACKLIGHT_CLASS_DEVICE -+        tristate "Lowlevel Backlight controls" - 	depends on BACKLIGHT_LCD_SUPPORT - 	default m - 	help --	  This framework adds support for low-level control of LCD. --	  Some framebuffer devices connect to platform-specific LCD modules --	  in order to have a platform-specific way to control the flat panel --	  (contrast and applying power to the LCD (not to the backlight!)). -+	  This framework adds support for low-level control of the LCD -+          backlight. This includes support for brightness and power. -  - 	  To have support for your specific LCD panel you will have to - 	  select the proper drivers which depend on this option. -diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile -index c6e2266..965a78b 100644 ---- a/drivers/video/backlight/Makefile -+++ b/drivers/video/backlight/Makefile -@@ -1,6 +1,8 @@ - # Backlight & LCD drivers -  - obj-$(CONFIG_LCD_CLASS_DEVICE)     += lcd.o -+obj-$(CONFIG_LCD_LTV350QV)	+= ltv350qv.o -+ - obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o - obj-$(CONFIG_BACKLIGHT_CORGI)	+= corgi_bl.o - obj-$(CONFIG_BACKLIGHT_HP680)	+= hp680_bl.o -diff --git a/drivers/video/backlight/ltv350qv.c b/drivers/video/backlight/ltv350qv.c -new file mode 100644 -index 0000000..342b97a ---- /dev/null -+++ b/drivers/video/backlight/ltv350qv.c -@@ -0,0 +1,340 @@ -+/* -+ * Power control for Samsung LTV350QV Quarter VGA LCD Panel -+ * -+ * Copyright (C) 2006, 2007 Atmel Corporation -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+#include <linux/delay.h> -+#include <linux/err.h> -+#include <linux/fb.h> -+#include <linux/init.h> -+#include <linux/lcd.h> -+#include <linux/module.h> -+#include <linux/spi/spi.h> -+ -+#include "ltv350qv.h" -+ -+#define POWER_IS_ON(pwr)	((pwr) <= FB_BLANK_NORMAL) -+ -+struct ltv350qv { -+	struct spi_device	*spi; -+	u8			*buffer; -+	int			power; -+	struct lcd_device	*ld; -+}; -+ -+/* -+ * The power-on and power-off sequences are taken from the -+ * LTV350QV-F04 data sheet from Samsung. The register definitions are -+ * taken from the S6F2002 command list also from Samsung. Both -+ * documents are distributed with the AVR32 Linux BSP CD from Atmel. -+ * -+ * There's still some voodoo going on here, but it's a lot better than -+ * in the first incarnation of the driver where all we had was the raw -+ * numbers from the initialization sequence. -+ */ -+static int ltv350qv_write_reg(struct ltv350qv *lcd, u8 reg, u16 val) -+{ -+	struct spi_message msg; -+	struct spi_transfer index_xfer = { -+		.len		= 3, -+		.cs_change	= 1, -+	}; -+	struct spi_transfer value_xfer = { -+		.len		= 3, -+		.cs_change	= 1, -+	}; -+ -+	spi_message_init(&msg); -+ -+	/* register index */ -+	lcd->buffer[0] = LTV_OPC_INDEX; -+	lcd->buffer[1] = 0x00; -+	lcd->buffer[2] = reg & 0x7f; -+	index_xfer.tx_buf = lcd->buffer; -+	spi_message_add_tail(&index_xfer, &msg); -+ -+	/* register value */ -+	lcd->buffer[4] = LTV_OPC_DATA; -+	lcd->buffer[5] = val >> 8; -+	lcd->buffer[6] = val; -+	value_xfer.tx_buf = lcd->buffer + 4; -+	spi_message_add_tail(&value_xfer, &msg); -+ -+	return spi_sync(lcd->spi, &msg); -+} -+ -+/* The comments are taken straight from the data sheet */ -+static int ltv350qv_power_on(struct ltv350qv *lcd) -+{ -+	int ret; -+ -+	/* Power On Reset Display off State */ -+	if (ltv350qv_write_reg(lcd, LTV_PWRCTL1, 0x0000)) -+		goto err; -+	msleep(15); -+ -+	/* Power Setting Function 1 */ -+	if (ltv350qv_write_reg(lcd, LTV_PWRCTL1, LTV_VCOM_DISABLE)) -+		goto err; -+	if (ltv350qv_write_reg(lcd, LTV_PWRCTL2, LTV_VCOML_ENABLE)) -+		goto err_power1; -+ -+	/* Power Setting Function 2 */ -+	if (ltv350qv_write_reg(lcd, LTV_PWRCTL1, -+			       LTV_VCOM_DISABLE | LTV_DRIVE_CURRENT(5) -+			       | LTV_SUPPLY_CURRENT(5))) -+		goto err_power2; -+ -+	msleep(55); -+ -+	/* Instruction Setting */ -+	ret = ltv350qv_write_reg(lcd, LTV_IFCTL, -+				 LTV_NMD | LTV_REV | LTV_NL(0x1d)); -+	ret |= ltv350qv_write_reg(lcd, LTV_DATACTL, -+				  LTV_DS_SAME | LTV_CHS_480 -+				  | LTV_DF_RGB | LTV_RGB_BGR); -+	ret |= ltv350qv_write_reg(lcd, LTV_ENTRY_MODE, -+				  LTV_VSPL_ACTIVE_LOW -+				  | LTV_HSPL_ACTIVE_LOW -+				  | LTV_DPL_SAMPLE_RISING -+				  | LTV_EPL_ACTIVE_LOW -+				  | LTV_SS_RIGHT_TO_LEFT); -+	ret |= ltv350qv_write_reg(lcd, LTV_GATECTL1, LTV_CLW(3)); -+	ret |= ltv350qv_write_reg(lcd, LTV_GATECTL2, -+				  LTV_NW_INV_1LINE | LTV_FWI(3)); -+	ret |= ltv350qv_write_reg(lcd, LTV_VBP, 0x000a); -+	ret |= ltv350qv_write_reg(lcd, LTV_HBP, 0x0021); -+	ret |= ltv350qv_write_reg(lcd, LTV_SOTCTL, LTV_SDT(3) | LTV_EQ(0)); -+	ret |= ltv350qv_write_reg(lcd, LTV_GAMMA(0), 0x0103); -+	ret |= ltv350qv_write_reg(lcd, LTV_GAMMA(1), 0x0301); -+	ret |= ltv350qv_write_reg(lcd, LTV_GAMMA(2), 0x1f0f); -+	ret |= ltv350qv_write_reg(lcd, LTV_GAMMA(3), 0x1f0f); -+	ret |= ltv350qv_write_reg(lcd, LTV_GAMMA(4), 0x0707); -+	ret |= ltv350qv_write_reg(lcd, LTV_GAMMA(5), 0x0307); -+	ret |= ltv350qv_write_reg(lcd, LTV_GAMMA(6), 0x0707); -+	ret |= ltv350qv_write_reg(lcd, LTV_GAMMA(7), 0x0000); -+	ret |= ltv350qv_write_reg(lcd, LTV_GAMMA(8), 0x0004); -+	ret |= ltv350qv_write_reg(lcd, LTV_GAMMA(9), 0x0000); -+	if (ret) -+		goto err_settings; -+ -+	/* Wait more than 2 frames */ -+	msleep(20); -+ -+	/* Display On Sequence */ -+	ret = ltv350qv_write_reg(lcd, LTV_PWRCTL1, -+				 LTV_VCOM_DISABLE | LTV_VCOMOUT_ENABLE -+				 | LTV_POWER_ON | LTV_DRIVE_CURRENT(5) -+				 | LTV_SUPPLY_CURRENT(5)); -+	ret |= ltv350qv_write_reg(lcd, LTV_GATECTL2, -+				  LTV_NW_INV_1LINE | LTV_DSC | LTV_FWI(3)); -+	if (ret) -+		goto err_disp_on; -+ -+	/* Display should now be ON. Phew. */ -+	return 0; -+ -+err_disp_on: -+	/* -+	 * Try to recover. Error handling probably isn't very useful -+	 * at this point, just make a best effort to switch the panel -+	 * off. -+	 */ -+	ltv350qv_write_reg(lcd, LTV_PWRCTL1, -+			   LTV_VCOM_DISABLE | LTV_DRIVE_CURRENT(5) -+			   | LTV_SUPPLY_CURRENT(5)); -+	ltv350qv_write_reg(lcd, LTV_GATECTL2, -+			   LTV_NW_INV_1LINE | LTV_FWI(3)); -+err_settings: -+err_power2: -+err_power1: -+	ltv350qv_write_reg(lcd, LTV_PWRCTL2, 0x0000); -+	msleep(1); -+err: -+	ltv350qv_write_reg(lcd, LTV_PWRCTL1, LTV_VCOM_DISABLE); -+	return -EIO; -+} -+ -+static int ltv350qv_power_off(struct ltv350qv *lcd) -+{ -+	int ret; -+ -+	/* Display Off Sequence */ -+	ret = ltv350qv_write_reg(lcd, LTV_PWRCTL1, -+				 LTV_VCOM_DISABLE -+				 | LTV_DRIVE_CURRENT(5) -+				 | LTV_SUPPLY_CURRENT(5)); -+	ret |= ltv350qv_write_reg(lcd, LTV_GATECTL2, -+				  LTV_NW_INV_1LINE | LTV_FWI(3)); -+ -+	/* Power down setting 1 */ -+	ret |= ltv350qv_write_reg(lcd, LTV_PWRCTL2, 0x0000); -+ -+	/* Wait at least 1 ms */ -+	msleep(1); -+ -+	/* Power down setting 2 */ -+	ret |= ltv350qv_write_reg(lcd, LTV_PWRCTL1, LTV_VCOM_DISABLE); -+ -+	/* -+	 * No point in trying to recover here. If we can't switch the -+	 * panel off, what are we supposed to do other than inform the -+	 * user about the failure? -+	 */ -+	if (ret) -+		return -EIO; -+ -+	/* Display power should now be OFF */ -+	return 0; -+} -+ -+static int ltv350qv_power(struct ltv350qv *lcd, int power) -+{ -+	int ret = 0; -+ -+	if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->power)) -+		ret = ltv350qv_power_on(lcd); -+	else if (!POWER_IS_ON(power) && POWER_IS_ON(lcd->power)) -+		ret = ltv350qv_power_off(lcd); -+ -+	if (!ret) -+		lcd->power = power; -+ -+	return ret; -+} -+ -+static int ltv350qv_set_power(struct lcd_device *ld, int power) -+{ -+	struct ltv350qv *lcd; -+ -+	lcd = class_get_devdata(&ld->class_dev); -+	return ltv350qv_power(lcd, power); -+} -+ -+static int ltv350qv_get_power(struct lcd_device *ld) -+{ -+	struct ltv350qv *lcd; -+ -+	lcd = class_get_devdata(&ld->class_dev); -+	return lcd->power; -+} -+ -+static struct lcd_ops ltv_ops = { -+	.get_power	= ltv350qv_get_power, -+	.set_power	= ltv350qv_set_power, -+}; -+ -+static int __devinit ltv350qv_probe(struct spi_device *spi) -+{ -+	struct ltv350qv *lcd; -+	struct lcd_device *ld; -+	int ret; -+ -+	lcd = kzalloc(sizeof(struct ltv350qv), GFP_KERNEL); -+	if (!lcd) -+		return -ENOMEM; -+ -+	lcd->spi = spi; -+	lcd->power = FB_BLANK_POWERDOWN; -+	lcd->buffer = kzalloc(8, GFP_KERNEL); -+ -+	ld = lcd_device_register("ltv350qv", lcd, <v_ops); -+	if (IS_ERR(ld)) { -+		ret = PTR_ERR(ld); -+		goto out_free_lcd; -+	} -+	lcd->ld = ld; -+ -+	ret = ltv350qv_power(lcd, FB_BLANK_UNBLANK); -+	if (ret) -+		goto out_unregister; -+ -+	dev_set_drvdata(&spi->dev, lcd); -+ -+	return 0; -+ -+out_unregister: -+	lcd_device_unregister(ld); -+out_free_lcd: -+	kfree(lcd); -+	return ret; -+} -+ -+static int __devexit ltv350qv_remove(struct spi_device *spi) -+{ -+	struct ltv350qv *lcd = dev_get_drvdata(&spi->dev); -+ -+	ltv350qv_power(lcd, FB_BLANK_POWERDOWN); -+	lcd_device_unregister(lcd->ld); -+	kfree(lcd); -+ -+	return 0; -+} -+ -+#ifdef CONFIG_PM -+static int ltv350qv_suspend(struct spi_device *spi, -+			    pm_message_t state, u32 level) -+{ -+	struct ltv350qv *lcd = dev_get_drvdata(&spi->dev); -+ -+	if (level == SUSPEND_POWER_DOWN) -+		return ltv350qv_power(lcd, FB_BLANK_POWERDOWN); -+ -+	return 0; -+} -+ -+static int ltv350qv_resume(struct spi_device *spi, u32 level) -+{ -+	struct ltv350qv *lcd = dev_get_drvdata(&spi->dev); -+ -+	if (level == RESUME_POWER_ON) -+		return ltv350qv_power(lcd, FB_BLANK_UNBLANK); -+ -+	return 0; -+} -+#else -+#define ltv350qv_suspend	NULL -+#define ltv350qv_resume		NULL -+#endif -+ -+/* Power down all displays on reboot, poweroff or halt */ -+static void ltv350qv_shutdown(struct spi_device *spi) -+{ -+	struct ltv350qv *lcd = dev_get_drvdata(&spi->dev); -+ -+	ltv350qv_power(lcd, FB_BLANK_POWERDOWN); -+} -+ -+static struct spi_driver ltv350qv_driver = { -+	.driver = { -+		.name		= "ltv350qv", -+		.bus		= &spi_bus_type, -+		.owner		= THIS_MODULE, -+	}, -+ -+	.probe		= ltv350qv_probe, -+	.remove		= __devexit_p(ltv350qv_remove), -+	.shutdown	= ltv350qv_shutdown, -+	.suspend	= ltv350qv_suspend, -+	.resume		= ltv350qv_resume, -+}; -+ -+static int __init ltv350qv_init(void) -+{ -+	return spi_register_driver(<v350qv_driver); -+} -+ -+static void __exit ltv350qv_exit(void) -+{ -+	spi_unregister_driver(<v350qv_driver); -+} -+module_init(ltv350qv_init); -+module_exit(ltv350qv_exit); -+ -+MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>"); -+MODULE_DESCRIPTION("Samsung LTV350QV LCD Driver"); -+MODULE_LICENSE("GPL"); -diff --git a/drivers/video/backlight/ltv350qv.h b/drivers/video/backlight/ltv350qv.h -new file mode 100644 -index 0000000..189112e ---- /dev/null -+++ b/drivers/video/backlight/ltv350qv.h -@@ -0,0 +1,95 @@ -+/* -+ * Register definitions for Samsung LTV350QV Quarter VGA LCD Panel -+ * -+ * Copyright (C) 2006, 2007 Atmel Corporation -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+#ifndef __LTV350QV_H -+#define __LTV350QV_H -+ -+#define LTV_OPC_INDEX	0x74 -+#define LTV_OPC_DATA	0x76 -+ -+#define LTV_ID		0x00		/* ID Read */ -+#define LTV_IFCTL	0x01		/* Display Interface Control */ -+#define LTV_DATACTL	0x02		/* Display Data Control */ -+#define LTV_ENTRY_MODE	0x03		/* Entry Mode */ -+#define LTV_GATECTL1	0x04		/* Gate Control 1 */ -+#define LTV_GATECTL2	0x05		/* Gate Control 2 */ -+#define LTV_VBP		0x06		/* Vertical Back Porch */ -+#define LTV_HBP		0x07		/* Horizontal Back Porch */ -+#define LTV_SOTCTL	0x08		/* Source Output Timing Control */ -+#define LTV_PWRCTL1	0x09		/* Power Control 1 */ -+#define LTV_PWRCTL2	0x0a		/* Power Control 2 */ -+#define LTV_GAMMA(x)	(0x10 + (x))	/* Gamma control */ -+ -+/* Bit definitions for LTV_IFCTL */ -+#define LTV_IM			(1 << 15) -+#define LTV_NMD			(1 << 14) -+#define LTV_SSMD		(1 << 13) -+#define LTV_REV			(1 <<  7) -+#define LTV_NL(x)		(((x) & 0x001f) << 0) -+ -+/* Bit definitions for LTV_DATACTL */ -+#define LTV_DS_SAME		(0 << 12) -+#define LTV_DS_D_TO_S		(1 << 12) -+#define LTV_DS_S_TO_D		(2 << 12) -+#define LTV_CHS_384		(0 <<  9) -+#define LTV_CHS_480		(1 <<  9) -+#define LTV_CHS_492		(2 <<  9) -+#define LTV_DF_RGB		(0 <<  6) -+#define LTV_DF_RGBX		(1 <<  6) -+#define LTV_DF_XRGB		(2 <<  6) -+#define LTV_RGB_RGB		(0 <<  2) -+#define LTV_RGB_BGR		(1 <<  2) -+#define LTV_RGB_GRB		(2 <<  2) -+#define LTV_RGB_RBG		(3 <<  2) -+ -+/* Bit definitions for LTV_ENTRY_MODE */ -+#define LTV_VSPL_ACTIVE_LOW	(0 << 15) -+#define LTV_VSPL_ACTIVE_HIGH	(1 << 15) -+#define LTV_HSPL_ACTIVE_LOW	(0 << 14) -+#define LTV_HSPL_ACTIVE_HIGH	(1 << 14) -+#define LTV_DPL_SAMPLE_RISING	(0 << 13) -+#define LTV_DPL_SAMPLE_FALLING	(1 << 13) -+#define LTV_EPL_ACTIVE_LOW	(0 << 12) -+#define LTV_EPL_ACTIVE_HIGH	(1 << 12) -+#define LTV_SS_LEFT_TO_RIGHT	(0 <<  8) -+#define LTV_SS_RIGHT_TO_LEFT	(1 <<  8) -+#define LTV_STB			(1 <<  1) -+ -+/* Bit definitions for LTV_GATECTL1 */ -+#define LTV_CLW(x)		(((x) & 0x0007) << 12) -+#define LTV_GAON		(1 <<  5) -+#define LTV_SDR			(1 <<  3) -+ -+/* Bit definitions for LTV_GATECTL2 */ -+#define LTV_NW_INV_FRAME	(0 << 14) -+#define LTV_NW_INV_1LINE	(1 << 14) -+#define LTV_NW_INV_2LINE	(2 << 14) -+#define LTV_DSC			(1 << 12) -+#define LTV_GIF			(1 <<  8) -+#define LTV_FHN			(1 <<  7) -+#define LTV_FTI(x)		(((x) & 0x0003) << 4) -+#define LTV_FWI(x)		(((x) & 0x0003) << 0) -+ -+/* Bit definitions for LTV_SOTCTL */ -+#define LTV_SDT(x)		(((x) & 0x0007) << 10) -+#define LTV_EQ(x)		(((x) & 0x0007) <<  2) -+ -+/* Bit definitions for LTV_PWRCTL1 */ -+#define LTV_VCOM_DISABLE	(1 << 14) -+#define LTV_VCOMOUT_ENABLE	(1 << 11) -+#define LTV_POWER_ON		(1 <<  9) -+#define LTV_DRIVE_CURRENT(x)	(((x) & 0x0007) << 4)	/* 0=off, 5=max */ -+#define LTV_SUPPLY_CURRENT(x)	(((x) & 0x0007) << 0)	/* 0=off, 5=max */ -+ -+/* Bit definitions for LTV_PWRCTL2 */ -+#define LTV_VCOML_ENABLE	(1 << 13) -+#define LTV_VCOML_VOLTAGE(x)	(((x) & 0x001f) << 8)	/* 0=1V, 31=-1V */ -+#define LTV_VCOMH_VOLTAGE(x)	(((x) & 0x001f) << 0)	/* 0=3V, 31=4.5V */ -+ -+#endif /* __LTV350QV_H */ -diff --git a/include/asm-arm/arch-at91/board.h b/include/asm-arm/arch-at91/board.h -index 0ce6ee9..d96b10f 100644 ---- a/include/asm-arm/arch-at91/board.h -+++ b/include/asm-arm/arch-at91/board.h -@@ -64,6 +64,7 @@ extern void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) -  -  /* Ethernet (EMAC & MACB) */ - struct at91_eth_data { -+	u32		phy_mask; - 	u8		phy_irq_pin;	/* PHY IRQ */ - 	u8		is_rmii;	/* using RMII interface? */ - }; -diff --git a/include/asm-avr32/arch-at32ap/board.h b/include/asm-avr32/arch-at32ap/board.h -index 9fd2e32..9b36eb8 100644 ---- a/include/asm-avr32/arch-at32ap/board.h -+++ b/include/asm-avr32/arch-at32ap/board.h -@@ -6,6 +6,8 @@ -  - #include <linux/types.h> -  -+#define GPIO_PIN_NONE	(-1) -+ - /* Add basic devices: system manager, interrupt controller, portmuxes, etc. */ - void at32_add_system_devices(void); -  -@@ -21,6 +23,7 @@ void at32_map_usart(unsigned int hw_id, unsigned int line); - 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 spi_board_info; - struct platform_device * - at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n); -  -+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_mci(unsigned int id, struct mci_platform_data *data); -+ -+struct usba_platform_data { -+	int vbus_pin; -+}; -+struct platform_device * -+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); -+ -+/* 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) -+ -+#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) -+ -+struct platform_device * -+at32_add_device_ssc(unsigned int id, unsigned int flags); -+ - #endif /* __ASM_ARCH_BOARD_H */ -diff --git a/include/asm-avr32/arch-at32ap/portmux.h b/include/asm-avr32/arch-at32ap/portmux.h -index 9930871..0f95567 100644 ---- a/include/asm-avr32/arch-at32ap/portmux.h -+++ b/include/asm-avr32/arch-at32ap/portmux.h -@@ -25,4 +25,16 @@ void at32_select_periph(unsigned int pin, unsigned int periph, - 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 --git a/include/asm-avr32/arch-at32ap/sm.h b/include/asm-avr32/arch-at32ap/sm.h -deleted file mode 100644 -index 265a9ea..0000000 ---- a/include/asm-avr32/arch-at32ap/sm.h -+++ /dev/null -@@ -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 --git a/include/asm-avr32/atomic.h b/include/asm-avr32/atomic.h -index b9c2548..7ef3862 100644 ---- a/include/asm-avr32/atomic.h -+++ b/include/asm-avr32/atomic.h -@@ -101,7 +101,7 @@ static inline int atomic_sub_unless(atomic_t *v, int a, int u) - 		"	mov	%1, 1\n" - 		"1:" - 		: "=&r"(tmp), "=&r"(result), "=o"(v->counter) --		: "m"(v->counter), "rKs21"(a), "rKs21"(u) -+		: "m"(v->counter), "rKs21"(a), "rKs21"(u), "1"(result) - 		: "cc", "memory"); -  - 	return result; -@@ -137,7 +137,7 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u) - 			"	mov	%1, 1\n" - 			"1:" - 			: "=&r"(tmp), "=&r"(result), "=o"(v->counter) --			: "m"(v->counter), "r"(a), "ir"(u) -+			: "m"(v->counter), "r"(a), "ir"(u), "1"(result) - 			: "cc", "memory"); - 	} -  -diff --git a/include/asm-avr32/dma-controller.h b/include/asm-avr32/dma-controller.h -new file mode 100644 -index 0000000..56a4965 ---- /dev/null -+++ b/include/asm-avr32/dma-controller.h -@@ -0,0 +1,166 @@ -+/* -+ * Copyright (C) 2005-2006 Atmel Corporation -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+#ifndef __ASM_AVR32_DMA_CONTROLLER_H -+#define __ASM_AVR32_DMA_CONTROLLER_H -+ -+#include <linux/device.h> -+ -+#define DMA_DIR_MEM_TO_MEM		0x0000 -+#define DMA_DIR_MEM_TO_PERIPH		0x0001 -+#define DMA_DIR_PERIPH_TO_MEM		0x0002 -+#define DMA_DIR_PERIPH_TO_PERIPH	0x0003 -+ -+#define DMA_WIDTH_8BIT			0 -+#define DMA_WIDTH_16BIT			1 -+#define DMA_WIDTH_32BIT			2 -+ -+struct dma_request { -+	struct dma_controller *dmac; -+	struct list_head list; -+ -+	unsigned short channel; -+ -+	void (*xfer_complete)(struct dma_request *req); -+	void (*block_complete)(struct dma_request *req); -+	void (*error)(struct dma_request *req); -+}; -+ -+struct dma_request_sg { -+	struct dma_request req; -+ -+	int nr_sg; -+	struct scatterlist *sg; -+	unsigned long block_size; -+	unsigned int nr_blocks; -+ -+	dma_addr_t data_reg; -+	unsigned short periph_id; -+ -+	unsigned char direction; -+	unsigned char width; -+}; -+#define to_dma_request_sg(_req)				\ -+	container_of(_req, struct dma_request_sg, req) -+ -+struct dma_request_cyclic { -+	struct dma_request req; -+ -+        int periods; -+	unsigned long buffer_size; -+ -+        dma_addr_t buffer_start; -+	dma_addr_t data_reg; -+ -+	unsigned short periph_id; -+	unsigned char direction; -+	unsigned char width; -+ -+        void *dev_id; -+}; -+#define to_dma_request_cyclic(_req)				\ -+	container_of(_req, struct dma_request_cyclic, req) -+ -+struct dma_request_memcpy { -+	struct dma_request req; -+ -+	dma_addr_t src_addr; -+	unsigned int src_width; -+	unsigned int src_stride; -+ -+	dma_addr_t dst_addr; -+	unsigned int dst_width; -+	unsigned int dst_stride; -+ -+	size_t length; -+ -+	unsigned short src_reverse:1; -+	unsigned short dst_reverse:1; -+}; -+#define to_dma_request_memcpy(_req)				\ -+	container_of(_req, struct dma_request_memcpy, req) -+ -+struct dma_controller { -+	struct list_head list; -+	int id; -+	struct device *dev; -+ -+	int (*alloc_channel)(struct dma_controller *dmac); -+	void (*release_channel)(struct dma_controller *dmac, -+				int channel); -+	int (*prepare_request_sg)(struct dma_controller *dmac, -+				  struct dma_request_sg *req); -+        int (*prepare_request_cyclic)(struct dma_controller *dmac, -+				      struct dma_request_cyclic *req); -+	int (*prepare_request_memcpy)(struct dma_controller *dmac, -+				      struct dma_request_memcpy *req); -+	int (*start_request)(struct dma_controller *dmac, -+			     unsigned int channel); -+	int (*stop_request)(struct dma_controller *dmac, -+                            unsigned int channel); -+        dma_addr_t (*get_current_pos)(struct dma_controller *dmac, -+                                      unsigned int channel); -+}; -+ -+static inline int -+dma_alloc_channel(struct dma_controller *dmac) -+{ -+	return dmac->alloc_channel(dmac); -+} -+ -+static inline void -+dma_release_channel(struct dma_controller *dmac, int chan) -+{ -+	dmac->release_channel(dmac, chan); -+} -+ -+static inline int -+dma_prepare_request_sg(struct dma_controller *dmac, -+		       struct dma_request_sg *req) -+{ -+	return dmac->prepare_request_sg(dmac, req); -+} -+ -+static inline int -+dma_prepare_request_cyclic(struct dma_controller *dmac, -+			   struct dma_request_cyclic *req) -+{ -+	return dmac->prepare_request_cyclic(dmac, req); -+} -+ -+static inline int -+dma_prepare_request_memcpy(struct dma_controller *dmac, -+			   struct dma_request_memcpy *req) -+{ -+	return dmac->prepare_request_memcpy(dmac, req); -+} -+ -+static inline int -+dma_start_request(struct dma_controller *dmac, -+		  unsigned int channel) -+{ -+	return dmac->start_request(dmac, channel); -+} -+ -+static inline int -+dma_stop_request(struct dma_controller *dmac, -+                 unsigned int channel) -+{ -+	return dmac->stop_request(dmac, channel); -+} -+ -+static inline dma_addr_t -+dma_get_current_pos(struct dma_controller *dmac, -+                    unsigned int channel) -+{ -+	return dmac->get_current_pos(dmac, channel); -+} -+ -+extern int register_dma_controller(struct dma_controller *dmac); -+extern struct dma_controller *find_dma_controller(int id); -+ -+#endif /* __ASM_AVR32_DMA_CONTROLLER_H */ -diff --git a/include/asm-avr32/unaligned.h b/include/asm-avr32/unaligned.h -index 3042723..36f5fd4 100644 ---- a/include/asm-avr32/unaligned.h -+++ b/include/asm-avr32/unaligned.h -@@ -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> -- --/* Use memmove here, so gcc does not insert a __builtin_memcpy. */ -- --#define get_unaligned(ptr) \ --  ({ __typeof__(*(ptr)) __tmp; memmove(&__tmp, (ptr), sizeof(*(ptr))); __tmp; }) -- --#define put_unaligned(val, ptr)				\ --  ({ __typeof__(*(ptr)) __tmp = (val);			\ --     memmove((ptr), &__tmp, sizeof(*(ptr)));		\ --     (void)0; }) -+#include <asm-generic/unaligned.h> -  - #endif /* __ASM_AVR32_UNALIGNED_H */ -diff --git a/include/linux/atmel-ssc.h b/include/linux/atmel-ssc.h -new file mode 100644 -index 0000000..0602339 ---- /dev/null -+++ b/include/linux/atmel-ssc.h -@@ -0,0 +1,312 @@ -+#ifndef __INCLUDE_ATMEL_SSC_H -+#define __INCLUDE_ATMEL_SSC_H -+ -+#include <linux/platform_device.h> -+#include <linux/list.h> -+ -+struct ssc_device { -+	struct list_head	list; -+	void __iomem		*regs; -+	struct platform_device	*pdev; -+	struct clk		*clk; -+	int			user; -+	int			irq; -+}; -+ -+struct ssc_device * __must_check ssc_request(unsigned int ssc_num); -+void ssc_free(struct ssc_device *ssc); -+ -+/* SSC register offsets */ -+ -+/* SSC Control Register */ -+#define SSC_CR				0x00000000 -+#define SSC_CR_RXDIS_SIZE			 1 -+#define SSC_CR_RXDIS_OFFSET			 1 -+#define SSC_CR_RXEN_SIZE			 1 -+#define SSC_CR_RXEN_OFFSET			 0 -+#define SSC_CR_SWRST_SIZE			 1 -+#define SSC_CR_SWRST_OFFSET			15 -+#define SSC_CR_TXDIS_SIZE			 1 -+#define SSC_CR_TXDIS_OFFSET			 9 -+#define SSC_CR_TXEN_SIZE			 1 -+#define SSC_CR_TXEN_OFFSET			 8 -+ -+/* SSC Clock Mode Register */ -+#define SSC_CMR				0x00000004 -+#define SSC_CMR_DIV_SIZE			12 -+#define SSC_CMR_DIV_OFFSET			 0 -+ -+/* SSC Receive Clock Mode Register */ -+#define SSC_RCMR			0x00000010 -+#define SSC_RCMR_CKG_SIZE			 2 -+#define SSC_RCMR_CKG_OFFSET			 6 -+#define SSC_RCMR_CKI_SIZE			 1 -+#define SSC_RCMR_CKI_OFFSET			 5 -+#define SSC_RCMR_CKO_SIZE			 3 -+#define SSC_RCMR_CKO_OFFSET			 2 -+#define SSC_RCMR_CKS_SIZE			 2 -+#define SSC_RCMR_CKS_OFFSET			 0 -+#define SSC_RCMR_PERIOD_SIZE			 8 -+#define SSC_RCMR_PERIOD_OFFSET			24 -+#define SSC_RCMR_START_SIZE			 4 -+#define SSC_RCMR_START_OFFSET			 8 -+#define SSC_RCMR_STOP_SIZE			 1 -+#define SSC_RCMR_STOP_OFFSET			12 -+#define SSC_RCMR_STTDLY_SIZE			 8 -+#define SSC_RCMR_STTDLY_OFFSET			16 -+ -+/* SSC Receive Frame Mode Register */ -+#define SSC_RFMR			0x00000014 -+#define SSC_RFMR_DATLEN_SIZE			 5 -+#define SSC_RFMR_DATLEN_OFFSET			 0 -+#define SSC_RFMR_DATNB_SIZE			 4 -+#define SSC_RFMR_DATNB_OFFSET			 8 -+#define SSC_RFMR_FSEDGE_SIZE			 1 -+#define SSC_RFMR_FSEDGE_OFFSET			24 -+#define SSC_RFMR_FSLEN_SIZE			 4 -+#define SSC_RFMR_FSLEN_OFFSET			16 -+#define SSC_RFMR_FSOS_SIZE			 4 -+#define SSC_RFMR_FSOS_OFFSET			20 -+#define SSC_RFMR_LOOP_SIZE			 1 -+#define SSC_RFMR_LOOP_OFFSET			 5 -+#define SSC_RFMR_MSBF_SIZE			 1 -+#define SSC_RFMR_MSBF_OFFSET			 7 -+ -+/* SSC Transmit Clock Mode Register */ -+#define SSC_TCMR			0x00000018 -+#define SSC_TCMR_CKG_SIZE			 2 -+#define SSC_TCMR_CKG_OFFSET			 6 -+#define SSC_TCMR_CKI_SIZE			 1 -+#define SSC_TCMR_CKI_OFFSET			 5 -+#define SSC_TCMR_CKO_SIZE			 3 -+#define SSC_TCMR_CKO_OFFSET			 2 -+#define SSC_TCMR_CKS_SIZE			 2 -+#define SSC_TCMR_CKS_OFFSET			 0 -+#define SSC_TCMR_PERIOD_SIZE			 8 -+#define SSC_TCMR_PERIOD_OFFSET			24 -+#define SSC_TCMR_START_SIZE			 4 -+#define SSC_TCMR_START_OFFSET			 8 -+#define SSC_TCMR_STTDLY_SIZE			 8 -+#define SSC_TCMR_STTDLY_OFFSET			16 -+ -+/* SSC Transmit Frame Mode Register */ -+#define SSC_TFMR			0x0000001c -+#define SSC_TFMR_DATDEF_SIZE			 1 -+#define SSC_TFMR_DATDEF_OFFSET			 5 -+#define SSC_TFMR_DATLEN_SIZE			 5 -+#define SSC_TFMR_DATLEN_OFFSET			 0 -+#define SSC_TFMR_DATNB_SIZE			 4 -+#define SSC_TFMR_DATNB_OFFSET			 8 -+#define SSC_TFMR_FSDEN_SIZE			 1 -+#define SSC_TFMR_FSDEN_OFFSET			23 -+#define SSC_TFMR_FSEDGE_SIZE			 1 -+#define SSC_TFMR_FSEDGE_OFFSET			24 -+#define SSC_TFMR_FSLEN_SIZE			 4 -+#define SSC_TFMR_FSLEN_OFFSET			16 -+#define SSC_TFMR_FSOS_SIZE			 3 -+#define SSC_TFMR_FSOS_OFFSET			20 -+#define SSC_TFMR_MSBF_SIZE			 1 -+#define SSC_TFMR_MSBF_OFFSET			 7 -+ -+/* SSC Receive Hold Register */ -+#define SSC_RHR				0x00000020 -+#define SSC_RHR_RDAT_SIZE			32 -+#define SSC_RHR_RDAT_OFFSET			 0 -+ -+/* SSC Transmit Hold Register */ -+#define SSC_THR				0x00000024 -+#define SSC_THR_TDAT_SIZE			32 -+#define SSC_THR_TDAT_OFFSET			 0 -+ -+/* SSC Receive Sync. Holding Register */ -+#define SSC_RSHR			0x00000030 -+#define SSC_RSHR_RSDAT_SIZE			16 -+#define SSC_RSHR_RSDAT_OFFSET			 0 -+ -+/* SSC Transmit Sync. Holding Register */ -+#define SSC_TSHR			0x00000034 -+#define SSC_TSHR_TSDAT_SIZE			16 -+#define SSC_TSHR_RSDAT_OFFSET			 0 -+ -+/* SSC Receive Compare 0 Register */ -+#define SSC_RC0R			0x00000038 -+#define SSC_RC0R_CP0_SIZE			16 -+#define SSC_RC0R_CP0_OFFSET			 0 -+ -+/* SSC Receive Compare 1 Register */ -+#define SSC_RC1R			0x0000003c -+#define SSC_RC1R_CP1_SIZE			16 -+#define SSC_RC1R_CP1_OFFSET			 0 -+ -+/* SSC Status Register */ -+#define SSC_SR				0x00000040 -+#define SSC_SR_CP0_SIZE				 1 -+#define SSC_SR_CP0_OFFSET			 8 -+#define SSC_SR_CP1_SIZE				 1 -+#define SSC_SR_CP1_OFFSET			 9 -+#define SSC_SR_ENDRX_SIZE			 1 -+#define SSC_SR_ENDRX_OFFSET			 6 -+#define SSC_SR_ENDTX_SIZE			 1 -+#define SSC_SR_ENDTX_OFFSET			 2 -+#define SSC_SR_OVRUN_SIZE			 1 -+#define SSC_SR_OVRUN_OFFSET			 5 -+#define SSC_SR_RXBUFF_SIZE			 1 -+#define SSC_SR_RXBUFF_OFFSET			 7 -+#define SSC_SR_RXEN_SIZE			 1 -+#define SSC_SR_RXEN_OFFSET			17 -+#define SSC_SR_RXRDY_SIZE			 1 -+#define SSC_SR_RXRDY_OFFSET			 4 -+#define SSC_SR_RXSYN_SIZE			 1 -+#define SSC_SR_RXSYN_OFFSET			11 -+#define SSC_SR_TXBUFE_SIZE			 1 -+#define SSC_SR_TXBUFE_OFFSET			 3 -+#define SSC_SR_TXEMPTY_SIZE			 1 -+#define SSC_SR_TXEMPTY_OFFSET			 1 -+#define SSC_SR_TXEN_SIZE			 1 -+#define SSC_SR_TXEN_OFFSET			16 -+#define SSC_SR_TXRDY_SIZE			 1 -+#define SSC_SR_TXRDY_OFFSET			 0 -+#define SSC_SR_TXSYN_SIZE			 1 -+#define SSC_SR_TXSYN_OFFSET			10 -+ -+/* SSC Interrupt Enable Register */ -+#define SSC_IER				0x00000044 -+#define SSC_IER_CP0_SIZE			 1 -+#define SSC_IER_CP0_OFFSET			 8 -+#define SSC_IER_CP1_SIZE			 1 -+#define SSC_IER_CP1_OFFSET			 9 -+#define SSC_IER_ENDRX_SIZE			 1 -+#define SSC_IER_ENDRX_OFFSET			 6 -+#define SSC_IER_ENDTX_SIZE			 1 -+#define SSC_IER_ENDTX_OFFSET			 2 -+#define SSC_IER_OVRUN_SIZE			 1 -+#define SSC_IER_OVRUN_OFFSET			 5 -+#define SSC_IER_RXBUFF_SIZE			 1 -+#define SSC_IER_RXBUFF_OFFSET			 7 -+#define SSC_IER_RXRDY_SIZE			 1 -+#define SSC_IER_RXRDY_OFFSET			 4 -+#define SSC_IER_RXSYN_SIZE			 1 -+#define SSC_IER_RXSYN_OFFSET			11 -+#define SSC_IER_TXBUFE_SIZE			 1 -+#define SSC_IER_TXBUFE_OFFSET			 3 -+#define SSC_IER_TXEMPTY_SIZE			 1 -+#define SSC_IER_TXEMPTY_OFFSET			 1 -+#define SSC_IER_TXRDY_SIZE			 1 -+#define SSC_IER_TXRDY_OFFSET			 0 -+#define SSC_IER_TXSYN_SIZE			 1 -+#define SSC_IER_TXSYN_OFFSET			10 -+ -+/* SSC Interrupt Disable Register */ -+#define SSC_IDR				0x00000048 -+#define SSC_IDR_CP0_SIZE			 1 -+#define SSC_IDR_CP0_OFFSET			 8 -+#define SSC_IDR_CP1_SIZE			 1 -+#define SSC_IDR_CP1_OFFSET			 9 -+#define SSC_IDR_ENDRX_SIZE			 1 -+#define SSC_IDR_ENDRX_OFFSET			 6 -+#define SSC_IDR_ENDTX_SIZE			 1 -+#define SSC_IDR_ENDTX_OFFSET			 2 -+#define SSC_IDR_OVRUN_SIZE			 1 -+#define SSC_IDR_OVRUN_OFFSET			 5 -+#define SSC_IDR_RXBUFF_SIZE			 1 -+#define SSC_IDR_RXBUFF_OFFSET			 7 -+#define SSC_IDR_RXRDY_SIZE			 1 -+#define SSC_IDR_RXRDY_OFFSET			 4 -+#define SSC_IDR_RXSYN_SIZE			 1 -+#define SSC_IDR_RXSYN_OFFSET			11 -+#define SSC_IDR_TXBUFE_SIZE			 1 -+#define SSC_IDR_TXBUFE_OFFSET			 3 -+#define SSC_IDR_TXEMPTY_SIZE			 1 -+#define SSC_IDR_TXEMPTY_OFFSET			 1 -+#define SSC_IDR_TXRDY_SIZE			 1 -+#define SSC_IDR_TXRDY_OFFSET			 0 -+#define SSC_IDR_TXSYN_SIZE			 1 -+#define SSC_IDR_TXSYN_OFFSET			10 -+ -+/* SSC Interrupt Mask Register */ -+#define SSC_IMR				0x0000004c -+#define SSC_IMR_CP0_SIZE			 1 -+#define SSC_IMR_CP0_OFFSET			 8 -+#define SSC_IMR_CP1_SIZE			 1 -+#define SSC_IMR_CP1_OFFSET			 9 -+#define SSC_IMR_ENDRX_SIZE			 1 -+#define SSC_IMR_ENDRX_OFFSET			 6 -+#define SSC_IMR_ENDTX_SIZE			 1 -+#define SSC_IMR_ENDTX_OFFSET			 2 -+#define SSC_IMR_OVRUN_SIZE			 1 -+#define SSC_IMR_OVRUN_OFFSET			 5 -+#define SSC_IMR_RXBUFF_SIZE			 1 -+#define SSC_IMR_RXBUFF_OFFSET			 7 -+#define SSC_IMR_RXRDY_SIZE			 1 -+#define SSC_IMR_RXRDY_OFFSET			 4 -+#define SSC_IMR_RXSYN_SIZE			 1 -+#define SSC_IMR_RXSYN_OFFSET			11 -+#define SSC_IMR_TXBUFE_SIZE			 1 -+#define SSC_IMR_TXBUFE_OFFSET			 3 -+#define SSC_IMR_TXEMPTY_SIZE			 1 -+#define SSC_IMR_TXEMPTY_OFFSET			 1 -+#define SSC_IMR_TXRDY_SIZE			 1 -+#define SSC_IMR_TXRDY_OFFSET			 0 -+#define SSC_IMR_TXSYN_SIZE			 1 -+#define SSC_IMR_TXSYN_OFFSET			10 -+ -+/* SSC PDC Receive Pointer Register */ -+#define SSC_PDC_RPR			0x00000100 -+ -+/* SSC PDC Receive Counter Register */ -+#define SSC_PDC_RCR			0x00000104 -+ -+/* SSC PDC Transmit Pointer Register */ -+#define SSC_PDC_TPR			0x00000108 -+ -+/* SSC PDC Receive Next Pointer Register */ -+#define SSC_PDC_RNPR			0x00000110 -+ -+/* SSC PDC Receive Next Counter Register */ -+#define SSC_PDC_RNCR			0x00000114 -+ -+/* SSC PDC Transmit Counter Register */ -+#define SSC_PDC_TCR			0x0000010c -+ -+/* SSC PDC Transmit Next Pointer Register */ -+#define SSC_PDC_TNPR			0x00000118 -+ -+/* SSC PDC Transmit Next Counter Register */ -+#define SSC_PDC_TNCR			0x0000011c -+ -+/* SSC PDC Transfer Control Register */ -+#define SSC_PDC_PTCR			0x00000120 -+#define SSC_PDC_PTCR_RXTDIS_SIZE		 1 -+#define SSC_PDC_PTCR_RXTDIS_OFFSET		 1 -+#define SSC_PDC_PTCR_RXTEN_SIZE			 1 -+#define SSC_PDC_PTCR_RXTEN_OFFSET		 0 -+#define SSC_PDC_PTCR_TXTDIS_SIZE		 1 -+#define SSC_PDC_PTCR_TXTDIS_OFFSET		 9 -+#define SSC_PDC_PTCR_TXTEN_SIZE			 1 -+#define SSC_PDC_PTCR_TXTEN_OFFSET		 8 -+ -+/* SSC PDC Transfer Status Register */ -+#define SSC_PDC_PTSR			0x00000124 -+#define SSC_PDC_PTSR_RXTEN_SIZE			 1 -+#define SSC_PDC_PTSR_RXTEN_OFFSET		 0 -+#define SSC_PDC_PTSR_TXTEN_SIZE			 1 -+#define SSC_PDC_PTSR_TXTEN_OFFSET		 8 -+ -+/* Bit manipulation macros */ -+#define SSC_BIT(name)					\ -+	(1 << SSC_##name##_OFFSET) -+#define SSC_BF(name, value)				\ -+	(((value) & ((1 << SSC_##name##_SIZE) - 1))	\ -+	 << SSC_##name##_OFFSET) -+#define SSC_BFEXT(name, value)				\ -+	(((value) >> SSC_##name##_OFFSET)		\ -+	 & ((1 << SSC_##name##_SIZE) - 1)) -+#define SSC_BFINS(name, value, old)			\ -+	(((old) & ~(((1 << SSC_##name##_SIZE) - 1)	\ -+	<< SSC_##name##_OFFSET)) | SSC_BF(name, value)) -+ -+/* Register access macros */ -+#define ssc_readl(base, reg)		__raw_readl(base + SSC_##reg) -+#define ssc_writel(base, reg, value)	__raw_writel((value), base + SSC_##reg) -+ -+#endif /* __INCLUDE_ATMEL_SSC_H */ -diff --git a/include/linux/gpio_mouse.h b/include/linux/gpio_mouse.h -new file mode 100644 -index 0000000..44ed7aa ---- /dev/null -+++ b/include/linux/gpio_mouse.h -@@ -0,0 +1,61 @@ -+/* -+ * Driver for simulating a mouse on GPIO lines. -+ * -+ * 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 _GPIO_MOUSE_H -+#define _GPIO_MOUSE_H -+ -+#define GPIO_MOUSE_POLARITY_ACT_HIGH	0x00 -+#define GPIO_MOUSE_POLARITY_ACT_LOW	0x01 -+ -+#define GPIO_MOUSE_PIN_UP	0 -+#define GPIO_MOUSE_PIN_DOWN	1 -+#define GPIO_MOUSE_PIN_LEFT	2 -+#define GPIO_MOUSE_PIN_RIGHT	3 -+#define GPIO_MOUSE_PIN_BLEFT	4 -+#define GPIO_MOUSE_PIN_BMIDDLE	5 -+#define GPIO_MOUSE_PIN_BRIGHT	6 -+#define GPIO_MOUSE_PIN_MAX	7 -+ -+/** -+ * struct gpio_mouse_platform_data -+ * @scan_ms: integer in ms specifying the scan periode. -+ * @polarity: Pin polarity, active high or low. -+ * @up: GPIO line for up value. -+ * @down: GPIO line for down value. -+ * @left: GPIO line for left value. -+ * @right: GPIO line for right value. -+ * @bleft: GPIO line for left button. -+ * @bmiddle: GPIO line for middle button. -+ * @bright: GPIO line for right button. -+ * -+ * This struct must be added to the platform_device in the board code. -+ * It is used by the gpio_mouse driver to setup GPIO lines and to -+ * calculate mouse movement. -+ */ -+struct gpio_mouse_platform_data { -+	int scan_ms; -+	int polarity; -+ -+	union { -+		struct { -+			int up; -+			int down; -+			int left; -+			int right; -+ -+			int bleft; -+			int bmiddle; -+			int bright; -+		}; -+		int pins[GPIO_MOUSE_PIN_MAX]; -+	}; -+}; -+ -+#endif /* _GPIO_MOUSE_H */ -diff --git a/include/linux/leds.h b/include/linux/leds.h -index 88afcef..059abfe 100644 ---- a/include/linux/leds.h -+++ b/include/linux/leds.h -@@ -110,4 +110,18 @@ extern void ledtrig_ide_activity(void); - #define ledtrig_ide_activity() do {} while(0) - #endif -  -+/* For the leds-gpio driver */ -+struct gpio_led { -+	const char *name; -+	char *default_trigger; -+	unsigned 	gpio; -+	u8 		active_low; -+}; -+ -+struct gpio_led_platform_data { -+	int 		num_leds; -+	struct gpio_led *leds; -+}; -+ -+ - #endif		/* __LINUX_LEDS_H_INCLUDED */ -diff --git a/include/linux/spi/at73c213.h b/include/linux/spi/at73c213.h -new file mode 100644 -index 0000000..0f20a70 ---- /dev/null -+++ b/include/linux/spi/at73c213.h -@@ -0,0 +1,25 @@ -+/* -+ * Board-specific data used to set up AT73c213 audio DAC driver. -+ */ -+ -+#ifndef __LINUX_SPI_AT73C213_H -+#define __LINUX_SPI_AT73C213_H -+ -+/** -+ * at73c213_board_info - how the external DAC is wired to the device. -+ * -+ * @ssc_id: SSC platform_driver id the DAC shall use to stream the audio. -+ * @dac_clk: the external clock used to provide master clock to the DAC. -+ * @shortname: a short discription for the DAC, seen by userspace tools. -+ * -+ * This struct contains the configuration of the hardware connection to the -+ * external DAC. The DAC needs a master clock and a I2S audio stream. It also -+ * provides a name which is used to identify it in userspace tools. -+ */ -+struct at73c213_board_info { -+	int		ssc_id; -+	struct clk	*dac_clk; -+	char		shortname[32]; -+}; -+ -+#endif /* __LINUX_SPI_AT73C213_H */ -diff --git a/include/linux/usb/Kbuild b/include/linux/usb/Kbuild -index 43f160c..6ce42bf 100644 ---- a/include/linux/usb/Kbuild -+++ b/include/linux/usb/Kbuild -@@ -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 --git a/include/linux/usb/gadgetfs.h b/include/linux/usb/gadgetfs.h -new file mode 100644 -index 0000000..e8654c3 ---- /dev/null -+++ b/include/linux/usb/gadgetfs.h -@@ -0,0 +1,81 @@ -+#ifndef __LINUX_USB_GADGETFS_H -+#define __LINUX_USB_GADGETFS_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) -+ -+#endif /* __LINUX_USB_GADGETFS_H */ -diff --git a/include/linux/usb_gadgetfs.h b/include/linux/usb_gadgetfs.h -deleted file mode 100644 -index 8086d5a..0000000 ---- a/include/linux/usb_gadgetfs.h -+++ /dev/null -@@ -1,75 +0,0 @@ -- --#include <asm/types.h> --#include <asm/ioctl.h> -- --#include <linux/usb/ch9.h> -- --/* -- * 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. -- */ -- --/* -- * 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. -- */ -- --enum usb_gadgetfs_event_type { --	GADGETFS_NOP = 0, -- --	GADGETFS_CONNECT, --	GADGETFS_DISCONNECT, --	GADGETFS_SETUP, --	GADGETFS_SUSPEND, --	// and likely more ! --}; -- --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 --git a/init/do_mounts.c b/init/do_mounts.c -index 46fe407..efc134c 100644 ---- a/init/do_mounts.c -+++ b/init/do_mounts.c -@@ -25,6 +25,7 @@ int __initdata rd_doload;	/* 1 = load RAM disk, 0 = don't load */ - int root_mountflags = MS_RDONLY | MS_SILENT; - char * __initdata root_device_name; - static char __initdata saved_root_name[64]; -+int __initdata root_wait; -  - dev_t ROOT_DEV; -  -@@ -216,6 +217,14 @@ static int __init root_dev_setup(char *line) -  - __setup("root=", root_dev_setup); -  -+static int __init rootwait_setup(char *line) -+{ -+	root_wait = simple_strtol(line,NULL,0); -+	return 1; -+} -+ -+__setup("rootwait=", rootwait_setup); -+ - static char * __initdata root_mount_data; - static int __init root_data_setup(char *str) - { -@@ -438,11 +447,24 @@ void __init prepare_namespace(void) - 			root_device_name += 5; - 	} -  --	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); -+	} -+ -+	is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR; -+ - 	if (is_floppy && rd_doload && rd_load_disk(0)) - 		ROOT_DEV = Root_RAM0; -  -diff --git a/scripts/checkstack.pl b/scripts/checkstack.pl -index f7844f6..6631586 100755 ---- a/scripts/checkstack.pl -+++ b/scripts/checkstack.pl -@@ -12,6 +12,7 @@ - #	sh64 port by Paul Mundt - #	Random bits by Matt Mackall <mpm@selenic.com> - #	M68k port by Geert Uytterhoeven and Andreas Schwab -+#	AVR32 port by Haavard Skinnemoen <hskinnemoen@atmel.com> - # - #	Usage: - #	objdump -d vmlinux | stackcheck.pl [arch] -@@ -37,6 +38,10 @@ my (@stack, $re, $x, $xs); - 	if ($arch eq 'arm') { - 		#c0008ffc:	e24dd064	sub	sp, sp, #100	; 0x64 - 		$re = qr/.*sub.*sp, sp, #(([0-9]{2}|[3-9])[0-9]{2})/o; -+	} elsif ($arch eq 'avr32') { -+		#8000008a:       20 1d           sub sp,4 -+		#80000ca8:       fa cd 05 b0     sub sp,sp,1456 -+		$re = qr/^.*sub.*sp.*,([0-9]{1,8})/o; - 	} elsif ($arch =~ /^i[3456]86$/) { - 		#c0105234:       81 ec ac 05 00 00       sub    $0x5ac,%esp - 		$re = qr/^.*[as][du][db]    \$(0x$x{1,8}),\%esp$/o; -diff --git a/sound/Kconfig b/sound/Kconfig -index 9ea4738..9217739 100644 ---- a/sound/Kconfig -+++ b/sound/Kconfig -@@ -63,9 +63,13 @@ source "sound/aoa/Kconfig" -  - source "sound/arm/Kconfig" -  -+if SPI -+source "sound/spi/Kconfig" -+endif -+ - source "sound/mips/Kconfig" -  --# the following will depend on the order of config. -+# tee following will depend on the order of config. - # here assuming USB is defined before ALSA - source "sound/usb/Kconfig" -  -diff --git a/sound/Makefile b/sound/Makefile -index b7c7fb7..581ea5e 100644 ---- a/sound/Makefile -+++ b/sound/Makefile -@@ -5,7 +5,8 @@ obj-$(CONFIG_SOUND) += soundcore.o - obj-$(CONFIG_SOUND_PRIME) += sound_firmware.o - obj-$(CONFIG_SOUND_PRIME) += oss/ - obj-$(CONFIG_DMASOUND) += oss/ --obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ synth/ usb/ sparc/ parisc/ pcmcia/ mips/ soc/ -+obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ synth/ usb/ \ -+		      sparc/ spi/ parisc/ pcmcia/ mips/ soc/ - obj-$(CONFIG_SND_AOA) += aoa/ -  - # This one must be compilable even if sound is configured out -diff --git a/sound/spi/Kconfig b/sound/spi/Kconfig -new file mode 100644 -index 0000000..0d08c29 ---- /dev/null -+++ b/sound/spi/Kconfig -@@ -0,0 +1,31 @@ -+#SPI drivers -+ -+menu "SPI devices" -+	depends on SND != n -+ -+config SND_AT73C213 -+	tristate "Atmel AT73C213 DAC driver" -+	depends on ATMEL_SSC -+	select SND_PCM -+	help -+	  Say Y here if you want to use the Atmel AT73C213 external DAC. This -+	  DAC can be found on Atmel development boards. -+ -+	  This driver requires the Atmel SSC driver for sound sink, a -+	  peripheral found on most AT91 and AVR32 microprocessors. -+ -+	  To compile this driver as a module, choose M here: the module will be -+	  called snd-at73c213. -+ -+config SND_AT73C213_TARGET_BITRATE -+	int "Target bitrate for AT73C213" -+	depends on SND_AT73C213 -+	default "48000" -+	range 8000 50000 -+	help -+	  Sets the target bitrate for the bitrate calculator in the driver. -+	  Limited by hardware to be between 8000 Hz and 50000 Hz. -+ -+	  Set to 48000 Hz by default. -+ -+endmenu -diff --git a/sound/spi/Makefile b/sound/spi/Makefile -new file mode 100644 -index 0000000..026fb73 ---- /dev/null -+++ b/sound/spi/Makefile -@@ -0,0 +1,5 @@ -+# Makefile for SPI drivers -+ -+snd-at73c213-objs		:= at73c213.o -+ -+obj-$(CONFIG_SND_AT73C213)	+= snd-at73c213.o -diff --git a/sound/spi/at73c213.c b/sound/spi/at73c213.c -new file mode 100644 -index 0000000..f514f47 ---- /dev/null -+++ b/sound/spi/at73c213.c -@@ -0,0 +1,1121 @@ -+/* -+ * Driver for AT73C213 16-bit stereo DAC connected to Atmel SSC -+ * -+ * Copyright (C) 2006-2007 Atmel Norway -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published by -+ * the Free Software Foundation. -+ */ -+ -+/*#define DEBUG*/ -+ -+#include <linux/clk.h> -+#include <linux/err.h> -+#include <linux/delay.h> -+#include <linux/device.h> -+#include <linux/dma-mapping.h> -+#include <linux/init.h> -+#include <linux/interrupt.h> -+#include <linux/module.h> -+#include <linux/platform_device.h> -+#include <linux/io.h> -+ -+#include <sound/driver.h> -+#include <sound/initval.h> -+#include <sound/control.h> -+#include <sound/core.h> -+#include <sound/pcm.h> -+ -+#include <linux/atmel-ssc.h> -+ -+#include <linux/spi/spi.h> -+#include <linux/spi/at73c213.h> -+ -+#include "at73c213.h" -+ -+#define BITRATE_MIN	 8000 /* Hardware limit? */ -+#define BITRATE_TARGET	CONFIG_SND_AT73C213_TARGET_BITRATE -+#define BITRATE_MAX	50000 /* Hardware limit. */ -+ -+/* Initial (hardware reset) AT73C213 register values. */ -+static u8 snd_at73c213_original_image[18] = -+{ -+	0x00,	/* 00 - CTRL    */ -+	0x05,	/* 01 - LLIG    */ -+	0x05,	/* 02 - RLIG    */ -+	0x08,	/* 03 - LPMG    */ -+	0x08,	/* 04 - RPMG    */ -+	0x00,	/* 05 - LLOG    */ -+	0x00,	/* 06 - RLOG    */ -+	0x22,	/* 07 - OLC     */ -+	0x09,	/* 08 - MC      */ -+	0x00,	/* 09 - CSFC    */ -+	0x00,	/* 0A - MISC    */ -+	0x00,	/* 0B -         */ -+	0x00,	/* 0C - PRECH   */ -+	0x05,	/* 0D - AUXG    */ -+	0x00,	/* 0E -         */ -+	0x00,	/* 0F -         */ -+	0x00,	/* 10 - RST     */ -+	0x00,	/* 11 - PA_CTRL */ -+}; -+ -+struct snd_at73c213 { -+	struct snd_card			*card; -+	struct snd_pcm			*pcm; -+	struct snd_pcm_substream	*substream; -+	struct at73c213_board_info	*board; -+	int				irq; -+	int				period; -+	unsigned long			bitrate; -+	struct clk			*bitclk; -+	struct ssc_device		*ssc; -+	struct spi_device		*spi; -+	u8				spi_wbuffer[2]; -+	u8				spi_rbuffer[2]; -+	/* Image of the SPI registers in AT73C213. */ -+	u8				reg_image[18]; -+	/* Protect registers against concurrent access. */ -+	spinlock_t			lock; -+}; -+ -+#define get_chip(card) ((struct snd_at73c213 *)card->private_data) -+ -+static int -+snd_at73c213_write_reg(struct snd_at73c213 *chip, u8 reg, u8 val) -+{ -+	struct spi_message msg; -+	struct spi_transfer msg_xfer = { -+		.len		= 2, -+		.cs_change	= 0, -+	}; -+	int retval; -+ -+	spi_message_init(&msg); -+ -+	chip->spi_wbuffer[0] = reg; -+	chip->spi_wbuffer[1] = val; -+ -+	msg_xfer.tx_buf = chip->spi_wbuffer; -+	msg_xfer.rx_buf = chip->spi_rbuffer; -+	spi_message_add_tail(&msg_xfer, &msg); -+ -+	retval = spi_sync(chip->spi, &msg); -+ -+	if (!retval) -+		chip->reg_image[reg] = val; -+ -+	return retval; -+} -+ -+static struct snd_pcm_hardware snd_at73c213_playback_hw = { -+	.info		= SNDRV_PCM_INFO_INTERLEAVED | -+			  SNDRV_PCM_INFO_BLOCK_TRANSFER, -+	.formats	= SNDRV_PCM_FMTBIT_S16_BE, -+	.rates		= SNDRV_PCM_RATE_CONTINUOUS, -+	.rate_min	= 8000,  /* Replaced by chip->bitrate later. */ -+	.rate_max	= 50000, /* Replaced by chip->bitrate later. */ -+	.channels_min	= 2, -+	.channels_max	= 2, -+	.buffer_bytes_max = 64 * 1024 - 1, -+	.period_bytes_min = 512, -+	.period_bytes_max = 64 * 1024 - 1, -+	.periods_min	= 4, -+	.periods_max	= 1024, -+}; -+ -+/* -+ * Calculate and set bitrate and divisions. -+ */ -+static int snd_at73c213_set_bitrate(struct snd_at73c213 *chip) -+{ -+	unsigned long ssc_rate = clk_get_rate(chip->ssc->clk); -+	unsigned long dac_rate_new, ssc_div, status; -+	unsigned long ssc_div_max, ssc_div_min; -+	int max_tries; -+ -+	/* -+	 * We connect two clocks here, picking divisors so the I2S clocks -+	 * out data at the same rate the DAC clocks it in ... and as close -+	 * as practical to the desired target rate. -+	 * -+	 * The DAC master clock (MCLK) is programmable, and is either 256 -+	 * or (not here) 384 times the I2S output clock (BCLK). -+	 */ -+ -+	/* SSC clock / (bitrate * stereo * 16-bit). */ -+	ssc_div = ssc_rate / (BITRATE_TARGET * 2 * 16); -+	ssc_div_min = ssc_rate / (BITRATE_MAX * 2 * 16); -+	ssc_div_max = ssc_rate / (BITRATE_MIN * 2 * 16); -+	max_tries = (ssc_div_max - ssc_div_min) / 2; -+ -+	if (max_tries < 1) -+		max_tries = 1; -+ -+	/* ssc_div must be a power of 2. */ -+	ssc_div = (ssc_div + 1) & ~1UL; -+ -+	if ((ssc_rate / (ssc_div * 2 * 16)) < BITRATE_MIN) { -+		ssc_div -= 2; -+		if ((ssc_rate / (ssc_div * 2 * 16)) > BITRATE_MAX) -+			return -ENXIO; -+	} -+ -+	/* Search for a possible bitrate. */ -+	do { -+		/* SSC clock / (ssc divider * 16-bit * stereo). */ -+		if ((ssc_rate / (ssc_div * 2 * 16)) < BITRATE_MIN) -+			return -ENXIO; -+ -+		/* 256 / (2 * 16) = 8 */ -+		dac_rate_new = 8 * (ssc_rate / ssc_div); -+ -+		status = clk_round_rate(chip->board->dac_clk, dac_rate_new); -+		if (status < 0) -+			return status; -+ -+		/* Ignore difference smaller than 256 Hz. */ -+		if ((status/256) == (dac_rate_new/256)) -+			goto set_rate; -+ -+		ssc_div += 2; -+	} while (--max_tries); -+ -+	/* Not able to find a valid bitrate. */ -+	return -ENXIO; -+ -+set_rate: -+	status = clk_set_rate(chip->board->dac_clk, status); -+	if (status < 0) -+		return status; -+ -+	/* Set divider in SSC device. */ -+	ssc_writel(chip->ssc->regs, CMR, ssc_div/2); -+ -+	/* SSC clock / (ssc divider * 16-bit * stereo). */ -+	chip->bitrate = ssc_rate / (ssc_div * 16 * 2); -+ -+	dev_info(&chip->spi->dev, -+			"at73c213: supported bitrate is %lu (%lu divider)\n", -+			chip->bitrate, ssc_div); -+ -+	return 0; -+} -+ -+static int snd_at73c213_pcm_open(struct snd_pcm_substream *substream) -+{ -+	struct snd_at73c213 *chip = snd_pcm_substream_chip(substream); -+	struct snd_pcm_runtime *runtime = substream->runtime; -+ -+	snd_at73c213_playback_hw.rate_min = chip->bitrate; -+	snd_at73c213_playback_hw.rate_max = chip->bitrate; -+	runtime->hw = snd_at73c213_playback_hw; -+	chip->substream = substream; -+ -+	return 0; -+} -+ -+static int snd_at73c213_pcm_close(struct snd_pcm_substream *substream) -+{ -+	struct snd_at73c213 *chip = snd_pcm_substream_chip(substream); -+	chip->substream = NULL; -+	return 0; -+} -+ -+static int snd_at73c213_pcm_hw_params(struct snd_pcm_substream *substream, -+				 struct snd_pcm_hw_params *hw_params) -+{ -+	return snd_pcm_lib_malloc_pages(substream, -+					params_buffer_bytes(hw_params)); -+} -+ -+static int snd_at73c213_pcm_hw_free(struct snd_pcm_substream *substream) -+{ -+	return snd_pcm_lib_free_pages(substream); -+} -+ -+static int snd_at73c213_pcm_prepare(struct snd_pcm_substream *substream) -+{ -+	struct snd_at73c213 *chip = snd_pcm_substream_chip(substream); -+	struct snd_pcm_runtime *runtime = substream->runtime; -+	int block_size; -+ -+	block_size = frames_to_bytes(runtime, runtime->period_size); -+ -+	chip->period = 0; -+ -+	ssc_writel(chip->ssc->regs, PDC_TPR, -+			(long)runtime->dma_addr); -+	ssc_writel(chip->ssc->regs, PDC_TCR, runtime->period_size * 2); -+	ssc_writel(chip->ssc->regs, PDC_TNPR, -+			(long)runtime->dma_addr + block_size); -+	ssc_writel(chip->ssc->regs, PDC_TNCR, runtime->period_size * 2); -+ -+	return 0; -+} -+ -+static int snd_at73c213_pcm_trigger(struct snd_pcm_substream *substream, -+				   int cmd) -+{ -+	struct snd_at73c213 *chip = snd_pcm_substream_chip(substream); -+	int retval = 0; -+ -+	spin_lock(&chip->lock); -+ -+	switch (cmd) { -+	case SNDRV_PCM_TRIGGER_START: -+		ssc_writel(chip->ssc->regs, IER, SSC_BIT(IER_ENDTX)); -+		ssc_writel(chip->ssc->regs, PDC_PTCR, SSC_BIT(PDC_PTCR_TXTEN)); -+		break; -+	case SNDRV_PCM_TRIGGER_STOP: -+		ssc_writel(chip->ssc->regs, PDC_PTCR, SSC_BIT(PDC_PTCR_TXTDIS)); -+		ssc_writel(chip->ssc->regs, IDR, SSC_BIT(IDR_ENDTX)); -+		break; -+	default: -+		dev_dbg(&chip->spi->dev, "spurious command %x\n", cmd); -+		retval = -EINVAL; -+		break; -+	} -+ -+	spin_unlock(&chip->lock); -+ -+	return retval; -+} -+ -+static snd_pcm_uframes_t -+snd_at73c213_pcm_pointer(struct snd_pcm_substream *substream) -+{ -+	struct snd_at73c213 *chip = snd_pcm_substream_chip(substream); -+	struct snd_pcm_runtime *runtime = substream->runtime; -+	snd_pcm_uframes_t pos; -+	unsigned long bytes; -+ -+	bytes = ssc_readl(chip->ssc->regs, PDC_TPR) -+		- (unsigned long)runtime->dma_addr; -+ -+	pos = bytes_to_frames(runtime, bytes); -+	if (pos >= runtime->buffer_size) -+		pos -= runtime->buffer_size; -+ -+	return pos; -+} -+ -+static struct snd_pcm_ops at73c213_playback_ops = { -+	.open		= snd_at73c213_pcm_open, -+	.close		= snd_at73c213_pcm_close, -+	.ioctl		= snd_pcm_lib_ioctl, -+	.hw_params	= snd_at73c213_pcm_hw_params, -+	.hw_free	= snd_at73c213_pcm_hw_free, -+	.prepare	= snd_at73c213_pcm_prepare, -+	.trigger	= snd_at73c213_pcm_trigger, -+	.pointer	= snd_at73c213_pcm_pointer, -+}; -+ -+static void snd_at73c213_pcm_free(struct snd_pcm *pcm) -+{ -+	struct snd_at73c213 *chip = snd_pcm_chip(pcm); -+	if (chip->pcm) { -+		snd_pcm_lib_preallocate_free_for_all(chip->pcm); -+		chip->pcm = NULL; -+	} -+} -+ -+static int __devinit snd_at73c213_pcm_new(struct snd_at73c213 *chip, int device) -+{ -+	struct snd_pcm *pcm; -+	int retval; -+ -+	retval = snd_pcm_new(chip->card, chip->card->shortname, -+			device, 1, 0, &pcm); -+	if (retval < 0) -+		goto out; -+ -+	pcm->private_data = chip; -+	pcm->private_free = snd_at73c213_pcm_free; -+	pcm->info_flags = SNDRV_PCM_INFO_BLOCK_TRANSFER; -+	strcpy(pcm->name, "at73c213"); -+	chip->pcm = pcm; -+ -+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &at73c213_playback_ops); -+ -+	retval = snd_pcm_lib_preallocate_pages_for_all(chip->pcm, -+			SNDRV_DMA_TYPE_DEV, &chip->ssc->pdev->dev, -+			64 * 1024, 64 * 1024); -+out: -+	return retval; -+} -+ -+static irqreturn_t snd_at73c213_interrupt(int irq, void *dev_id) -+{ -+	struct snd_at73c213 *chip = dev_id; -+	struct snd_pcm_runtime *runtime = chip->substream->runtime; -+	u32 status; -+	int offset; -+	int block_size; -+	int next_period; -+	int retval = IRQ_NONE; -+ -+	spin_lock(&chip->lock); -+ -+	block_size = frames_to_bytes(runtime, runtime->period_size); -+	status = ssc_readl(chip->ssc->regs, IMR); -+ -+	if (status & SSC_BIT(IMR_ENDTX)) { -+		chip->period++; -+		if (chip->period == runtime->periods) -+			chip->period = 0; -+		next_period = chip->period + 1; -+		if (next_period == runtime->periods) -+			next_period = 0; -+ -+		offset = block_size * next_period; -+ -+		ssc_writel(chip->ssc->regs, PDC_TNPR, -+				(long)runtime->dma_addr + offset); -+		ssc_writel(chip->ssc->regs, PDC_TNCR, runtime->period_size * 2); -+		retval = IRQ_HANDLED; -+	} -+ -+	ssc_readl(chip->ssc->regs, IMR); -+	spin_unlock(&chip->lock); -+ -+	if (status & SSC_BIT(IMR_ENDTX)) -+		snd_pcm_period_elapsed(chip->substream); -+ -+	return retval; -+} -+ -+/* -+ * Mixer functions. -+ */ -+static int snd_at73c213_mono_get(struct snd_kcontrol *kcontrol, -+				 struct snd_ctl_elem_value *ucontrol) -+{ -+	struct snd_at73c213 *chip = snd_kcontrol_chip(kcontrol); -+	int reg = kcontrol->private_value & 0xff; -+	int shift = (kcontrol->private_value >> 8) & 0xff; -+	int mask = (kcontrol->private_value >> 16) & 0xff; -+	int invert = (kcontrol->private_value >> 24) & 0xff; -+ -+	spin_lock_irq(&chip->lock); -+ -+	ucontrol->value.integer.value[0] = (chip->reg_image[reg] >> shift) & mask; -+ -+	if (invert) -+		ucontrol->value.integer.value[0] = -+			(mask - ucontrol->value.integer.value[0]); -+ -+	spin_unlock_irq(&chip->lock); -+ -+	return 0; -+} -+ -+static int snd_at73c213_mono_put(struct snd_kcontrol *kcontrol, -+				 struct snd_ctl_elem_value *ucontrol) -+{ -+	struct snd_at73c213 *chip = snd_kcontrol_chip(kcontrol); -+	int reg = kcontrol->private_value & 0xff; -+	int shift = (kcontrol->private_value >> 8) & 0xff; -+	int mask = (kcontrol->private_value >> 16) & 0xff; -+	int invert = (kcontrol->private_value >> 24) & 0xff; -+	int change, retval; -+	unsigned short val; -+ -+	val = (ucontrol->value.integer.value[0] & mask); -+	if (invert) -+		val = mask - val; -+	val <<= shift; -+ -+	spin_lock_irq(&chip->lock); -+ -+	val = (chip->reg_image[reg] & ~(mask << shift)) | val; -+	change = val != chip->reg_image[reg]; -+	retval = snd_at73c213_write_reg(chip, reg, val); -+ -+	spin_unlock_irq(&chip->lock); -+ -+	if (retval) -+		return retval; -+ -+	return change; -+} -+ -+static int snd_at73c213_stereo_info(struct snd_kcontrol *kcontrol, -+				  struct snd_ctl_elem_info *uinfo) -+{ -+	int mask = (kcontrol->private_value >> 24) & 0xff; -+ -+	if (mask == 1) -+		uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; -+	else -+		uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; -+ -+	uinfo->count = 2; -+	uinfo->value.integer.min = 0; -+	uinfo->value.integer.max = mask; -+ -+	return 0; -+} -+ -+static int snd_at73c213_stereo_get(struct snd_kcontrol *kcontrol, -+				 struct snd_ctl_elem_value *ucontrol) -+{ -+	struct snd_at73c213 *chip = snd_kcontrol_chip(kcontrol); -+	int left_reg = kcontrol->private_value & 0xff; -+	int right_reg = (kcontrol->private_value >> 8) & 0xff; -+	int shift_left = (kcontrol->private_value >> 16) & 0x07; -+	int shift_right = (kcontrol->private_value >> 19) & 0x07; -+	int mask = (kcontrol->private_value >> 24) & 0xff; -+	int invert = (kcontrol->private_value >> 22) & 1; -+ -+	spin_lock_irq(&chip->lock); -+ -+	ucontrol->value.integer.value[0] = -+		(chip->reg_image[left_reg] >> shift_left) & mask; -+	ucontrol->value.integer.value[1] = -+		(chip->reg_image[right_reg] >> shift_right) & mask; -+ -+	if (invert) { -+		ucontrol->value.integer.value[0] = -+			(mask - ucontrol->value.integer.value[0]); -+		ucontrol->value.integer.value[1] = -+			(mask - ucontrol->value.integer.value[1]); -+	} -+ -+	spin_unlock_irq(&chip->lock); -+ -+	return 0; -+} -+ -+static int snd_at73c213_stereo_put(struct snd_kcontrol *kcontrol, -+				 struct snd_ctl_elem_value *ucontrol) -+{ -+	struct snd_at73c213 *chip = snd_kcontrol_chip(kcontrol); -+	int left_reg = kcontrol->private_value & 0xff; -+	int right_reg = (kcontrol->private_value >> 8) & 0xff; -+	int shift_left = (kcontrol->private_value >> 16) & 0x07; -+	int shift_right = (kcontrol->private_value >> 19) & 0x07; -+	int mask = (kcontrol->private_value >> 24) & 0xff; -+	int invert = (kcontrol->private_value >> 22) & 1; -+	int change, retval; -+	unsigned short val1, val2; -+ -+	val1 = ucontrol->value.integer.value[0] & mask; -+	val2 = ucontrol->value.integer.value[1] & mask; -+	if (invert) { -+		val1 = mask - val1; -+		val2 = mask - val2; -+	} -+	val1 <<= shift_left; -+	val2 <<= shift_right; -+ -+	spin_lock_irq(&chip->lock); -+ -+	val1 = (chip->reg_image[left_reg] & ~(mask << shift_left)) | val1; -+	val2 = (chip->reg_image[right_reg] & ~(mask << shift_right)) | val2; -+	change = val1 != chip->reg_image[left_reg] -+		|| val2 != chip->reg_image[right_reg]; -+	retval = snd_at73c213_write_reg(chip, left_reg, val1); -+	if (retval) { -+		spin_unlock_irq(&chip->lock); -+		goto out; -+	} -+	retval = snd_at73c213_write_reg(chip, right_reg, val2); -+	if (retval) { -+		spin_unlock_irq(&chip->lock); -+		goto out; -+	} -+ -+	spin_unlock_irq(&chip->lock); -+ -+	return change; -+ -+out: -+	return retval; -+} -+ -+static int snd_at73c213_mono_switch_info(struct snd_kcontrol *kcontrol, -+				  struct snd_ctl_elem_info *uinfo) -+{ -+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; -+	uinfo->count = 1; -+	uinfo->value.integer.min = 0; -+	uinfo->value.integer.max = 1; -+ -+	return 0; -+} -+ -+static int snd_at73c213_mono_switch_get(struct snd_kcontrol *kcontrol, -+				 struct snd_ctl_elem_value *ucontrol) -+{ -+	struct snd_at73c213 *chip = snd_kcontrol_chip(kcontrol); -+	int reg = kcontrol->private_value & 0xff; -+	int shift = (kcontrol->private_value >> 8) & 0xff; -+	int invert = (kcontrol->private_value >> 24) & 0xff; -+ -+	spin_lock_irq(&chip->lock); -+ -+	ucontrol->value.integer.value[0] = (chip->reg_image[reg] >> shift) & 0x01; -+ -+	if (invert) -+		ucontrol->value.integer.value[0] = -+			(0x01 - ucontrol->value.integer.value[0]); -+ -+	spin_unlock_irq(&chip->lock); -+ -+	return 0; -+} -+ -+static int snd_at73c213_mono_switch_put(struct snd_kcontrol *kcontrol, -+				 struct snd_ctl_elem_value *ucontrol) -+{ -+	struct snd_at73c213 *chip = snd_kcontrol_chip(kcontrol); -+	int reg = kcontrol->private_value & 0xff; -+	int shift = (kcontrol->private_value >> 8) & 0xff; -+	int mask = (kcontrol->private_value >> 16) & 0xff; -+	int invert = (kcontrol->private_value >> 24) & 0xff; -+	int change, retval; -+	unsigned short val; -+ -+	if (ucontrol->value.integer.value[0]) -+		val = mask; -+	else -+		val = 0; -+ -+	if (invert) -+		val = mask - val; -+	val <<= shift; -+ -+	spin_lock_irq(&chip->lock); -+ -+	val |= (chip->reg_image[reg] & ~(mask << shift)); -+	change = val != chip->reg_image[reg]; -+ -+	retval = snd_at73c213_write_reg(chip, reg, val); -+ -+	spin_unlock_irq(&chip->lock); -+ -+	if (retval) -+		return retval; -+ -+	return change; -+} -+ -+static int snd_at73c213_pa_volume_info(struct snd_kcontrol *kcontrol, -+				  struct snd_ctl_elem_info *uinfo) -+{ -+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; -+	uinfo->count = 1; -+	uinfo->value.integer.min = 0; -+	uinfo->value.integer.max = ((kcontrol->private_value >> 16) & 0xff) - 1; -+ -+	return 0; -+} -+ -+static int snd_at73c213_line_capture_volume_info( -+		struct snd_kcontrol *kcontrol, -+		struct snd_ctl_elem_info *uinfo) -+{ -+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; -+	uinfo->count = 2; -+	/* When inverted will give values 0x10001 => 0. */ -+	uinfo->value.integer.min = 14; -+	uinfo->value.integer.max = 31; -+ -+	return 0; -+} -+ -+static int snd_at73c213_aux_capture_volume_info( -+		struct snd_kcontrol *kcontrol, -+		struct snd_ctl_elem_info *uinfo) -+{ -+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; -+	uinfo->count = 1; -+	/* When inverted will give values 0x10001 => 0. */ -+	uinfo->value.integer.min = 14; -+	uinfo->value.integer.max = 31; -+ -+	return 0; -+} -+ -+#define AT73C213_MONO_SWITCH(xname, xindex, reg, shift, mask, invert)	\ -+{									\ -+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,				\ -+	.name = xname,							\ -+	.index = xindex,						\ -+	.info = snd_at73c213_mono_switch_info,				\ -+	.get = snd_at73c213_mono_switch_get,				\ -+	.put = snd_at73c213_mono_switch_put,				\ -+	.private_value = (reg | (shift << 8) | (mask << 16) | (invert << 24)) \ -+} -+ -+#define AT73C213_STEREO(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \ -+{									\ -+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,				\ -+	.name = xname,							\ -+	.index = xindex,						\ -+	.info = snd_at73c213_stereo_info,				\ -+	.get = snd_at73c213_stereo_get,					\ -+	.put = snd_at73c213_stereo_put,					\ -+	.private_value = (left_reg | (right_reg << 8)			\ -+			| (shift_left << 16) | (shift_right << 19)	\ -+			| (mask << 24) | (invert << 22))		\ -+} -+ -+static struct snd_kcontrol_new snd_at73c213_controls[] __devinitdata = { -+AT73C213_STEREO("Master Playback Volume", 0, DAC_LMPG, DAC_RMPG, 0, 0, 0x1f, 1), -+AT73C213_STEREO("Master Playback Switch", 0, DAC_LMPG, DAC_RMPG, 5, 5, 1, 1), -+AT73C213_STEREO("PCM Playback Volume", 0, DAC_LLOG, DAC_RLOG, 0, 0, 0x1f, 1), -+AT73C213_STEREO("PCM Playback Switch", 0, DAC_LLOG, DAC_RLOG, 5, 5, 1, 1), -+AT73C213_MONO_SWITCH("Mono PA Playback Switch", 0, DAC_CTRL, DAC_CTRL_ONPADRV, 0x01, 0), -+{ -+	.iface	= SNDRV_CTL_ELEM_IFACE_MIXER, -+	.name	= "PA Playback Volume", -+	.index	= 0, -+	.info	= snd_at73c213_pa_volume_info, -+	.get	= snd_at73c213_mono_get, -+	.put	= snd_at73c213_mono_put, -+	.private_value	= PA_CTRL | (PA_CTRL_APAGAIN << 8) | (0x0f << 16) | (1 << 24), -+}, -+AT73C213_MONO_SWITCH("PA High Gain Playback Switch", 0, PA_CTRL, PA_CTRL_APALP, 0x01, 1), -+AT73C213_MONO_SWITCH("PA Playback Switch", 0, PA_CTRL, PA_CTRL_APAON, 0x01, 0), -+{ -+	.iface	= SNDRV_CTL_ELEM_IFACE_MIXER, -+	.name	= "Aux Capture Volume", -+	.index	= 0, -+	.info	= snd_at73c213_aux_capture_volume_info, -+	.get	= snd_at73c213_mono_get, -+	.put	= snd_at73c213_mono_put, -+	.private_value	= DAC_AUXG | (0 << 8) | (0x1f << 16) | (1 << 24), -+}, -+AT73C213_MONO_SWITCH("Aux Capture Switch", 0, DAC_CTRL, DAC_CTRL_ONAUXIN, 0x01, 0), -+{ -+	.iface	= SNDRV_CTL_ELEM_IFACE_MIXER, -+	.name	= "Line Capture Volume", -+	.index	= 0, -+	.info	= snd_at73c213_line_capture_volume_info, -+	.get	= snd_at73c213_stereo_get, -+	.put	= snd_at73c213_stereo_put, -+	.private_value	= DAC_LLIG | (DAC_RLIG << 8) | (0 << 16) | (0 << 19) -+		| (0x1f << 24) | (1 << 22), -+}, -+AT73C213_MONO_SWITCH("Line Capture Switch", 0, DAC_CTRL, 0, 0x03, 0), -+}; -+ -+static int __devinit snd_at73c213_mixer(struct snd_at73c213 *chip) -+{ -+	struct snd_card *card; -+	int errval, idx; -+ -+	if (chip == NULL || chip->pcm == NULL) -+		return -EINVAL; -+ -+	card = chip->card; -+ -+	strcpy(card->mixername, chip->pcm->name); -+ -+	for (idx = 0; idx < ARRAY_SIZE(snd_at73c213_controls); idx++) { -+		errval = snd_ctl_add(card, -+				snd_ctl_new1(&snd_at73c213_controls[idx], -+					chip)); -+		if (errval < 0) -+			goto cleanup; -+	} -+ -+	return 0; -+ -+cleanup: -+	for (idx = 1; idx < ARRAY_SIZE(snd_at73c213_controls) + 1; idx++) { -+		struct snd_kcontrol *kctl; -+		kctl = snd_ctl_find_numid(card, idx); -+		if (kctl) -+			snd_ctl_remove(card, kctl); -+	} -+	return errval; -+} -+ -+/* -+ * Device functions -+ */ -+static int snd_at73c213_ssc_init(struct snd_at73c213 *chip) -+{ -+	/* -+	 * Continuous clock output. -+	 * Starts on falling TF. -+	 * Delay 1 cycle (1 bit). -+	 * Periode is 16 bit (16 - 1). -+	 */ -+	ssc_writel(chip->ssc->regs, TCMR, -+			SSC_BF(TCMR_CKO, 1) -+			| SSC_BF(TCMR_START, 4) -+			| SSC_BF(TCMR_STTDLY, 1) -+			| SSC_BF(TCMR_PERIOD, 16 - 1)); -+	/* -+	 * Data length is 16 bit (16 - 1). -+	 * Transmit MSB first. -+	 * Transmit 2 words each transfer. -+	 * Frame sync length is 16 bit (16 - 1). -+	 * Frame starts on negative pulse. -+	 */ -+	ssc_writel(chip->ssc->regs, TFMR, -+			SSC_BF(TFMR_DATLEN, 16 - 1) -+			| SSC_BIT(TFMR_MSBF) -+			| SSC_BF(TFMR_DATNB, 1) -+			| SSC_BF(TFMR_FSLEN, 16 - 1) -+			| SSC_BF(TFMR_FSOS, 1)); -+ -+	return 0; -+} -+ -+static int snd_at73c213_chip_init(struct snd_at73c213 *chip) -+{ -+	int retval; -+	unsigned char dac_ctrl = 0; -+ -+	retval = snd_at73c213_set_bitrate(chip); -+	if (retval) -+		goto out; -+ -+	/* Enable DAC master clock. */ -+	clk_enable(chip->board->dac_clk); -+ -+	/* Initialize at73c213 on SPI bus. */ -+	retval = snd_at73c213_write_reg(chip, DAC_RST, 0x04); -+	if (retval) -+		goto out_clk; -+	msleep(1); -+	retval = snd_at73c213_write_reg(chip, DAC_RST, 0x03); -+	if (retval) -+		goto out_clk; -+ -+	/* Precharge everything. */ -+	retval = snd_at73c213_write_reg(chip, DAC_PRECH, 0xff); -+	if (retval) -+		goto out_clk; -+	retval = snd_at73c213_write_reg(chip, PA_CTRL, (1<<PA_CTRL_APAPRECH)); -+	if (retval) -+		goto out_clk; -+	retval = snd_at73c213_write_reg(chip, DAC_CTRL, -+			(1<<DAC_CTRL_ONLNOL) | (1<<DAC_CTRL_ONLNOR)); -+	if (retval) -+		goto out_clk; -+ -+	msleep(50); -+ -+	/* Stop precharging PA. */ -+	retval = snd_at73c213_write_reg(chip, PA_CTRL, -+			(1<<PA_CTRL_APALP) | 0x0f); -+	if (retval) -+		goto out_clk; -+ -+	msleep(450); -+ -+	/* Stop precharging DAC, turn on master power. */ -+	retval = snd_at73c213_write_reg(chip, DAC_PRECH, (1<<DAC_PRECH_ONMSTR)); -+	if (retval) -+		goto out_clk; -+ -+	msleep(1); -+ -+	/* Turn on DAC. */ -+	dac_ctrl = (1<<DAC_CTRL_ONDACL) | (1<<DAC_CTRL_ONDACR) -+		| (1<<DAC_CTRL_ONLNOL) | (1<<DAC_CTRL_ONLNOR); -+ -+	retval = snd_at73c213_write_reg(chip, DAC_CTRL, dac_ctrl); -+	if (retval) -+		goto out_clk; -+ -+	/* Mute sound. */ -+	retval = snd_at73c213_write_reg(chip, DAC_LMPG, 0x3f); -+	if (retval) -+		goto out_clk; -+	retval = snd_at73c213_write_reg(chip, DAC_RMPG, 0x3f); -+	if (retval) -+		goto out_clk; -+	retval = snd_at73c213_write_reg(chip, DAC_LLOG, 0x3f); -+	if (retval) -+		goto out_clk; -+	retval = snd_at73c213_write_reg(chip, DAC_RLOG, 0x3f); -+	if (retval) -+		goto out_clk; -+	retval = snd_at73c213_write_reg(chip, DAC_LLIG, 0x11); -+	if (retval) -+		goto out_clk; -+	retval = snd_at73c213_write_reg(chip, DAC_RLIG, 0x11); -+	if (retval) -+		goto out_clk; -+	retval = snd_at73c213_write_reg(chip, DAC_AUXG, 0x11); -+	if (retval) -+		goto out_clk; -+ -+	/* Enable I2S device, i.e. clock output. */ -+	ssc_writel(chip->ssc->regs, CR, SSC_BIT(CR_TXEN)); -+ -+	goto out; -+ -+out_clk: -+	clk_disable(chip->board->dac_clk); -+out: -+	return retval; -+} -+ -+static int snd_at73c213_dev_free(struct snd_device *device) -+{ -+	struct snd_at73c213 *chip = device->device_data; -+ -+	ssc_writel(chip->ssc->regs, CR, SSC_BIT(CR_TXDIS)); -+	if (chip->irq >= 0) { -+		free_irq(chip->irq, chip); -+		chip->irq = -1; -+	} -+ -+	return 0; -+} -+ -+static int __devinit snd_at73c213_dev_init(struct snd_card *card, -+					 struct spi_device *spi) -+{ -+	static struct snd_device_ops ops = { -+		.dev_free	= snd_at73c213_dev_free, -+	}; -+	struct snd_at73c213 *chip = get_chip(card); -+	int irq, retval; -+ -+	irq = chip->ssc->irq; -+	if (irq < 0) -+		return irq; -+ -+	spin_lock_init(&chip->lock); -+	chip->card = card; -+	chip->irq = -1; -+ -+	retval = request_irq(irq, snd_at73c213_interrupt, 0, "at73c213", chip); -+	if (retval) { -+		dev_dbg(&chip->spi->dev, "unable to request irq %d\n", irq); -+		goto out; -+	} -+	chip->irq = irq; -+ -+	memcpy(&chip->reg_image, &snd_at73c213_original_image, -+			sizeof(snd_at73c213_original_image)); -+ -+	retval = snd_at73c213_ssc_init(chip); -+	if (retval) -+		goto out_irq; -+ -+	retval = snd_at73c213_chip_init(chip); -+	if (retval) -+		goto out_irq; -+ -+	retval = snd_at73c213_pcm_new(chip, 0); -+	if (retval) -+		goto out_irq; -+ -+	retval = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); -+	if (retval) -+		goto out_irq; -+ -+	retval = snd_at73c213_mixer(chip); -+	if (retval) -+		goto out_snd_dev; -+ -+	snd_card_set_dev(card, &spi->dev); -+ -+	goto out; -+ -+out_snd_dev: -+	snd_device_free(card, chip); -+out_irq: -+	free_irq(chip->irq, chip); -+	chip->irq = -1; -+out: -+	return retval; -+} -+ -+static int snd_at73c213_probe(struct spi_device *spi) -+{ -+	struct snd_card			*card; -+	struct snd_at73c213		*chip; -+	struct at73c213_board_info	*board; -+	int				retval; -+	char				id[16]; -+ -+	board = spi->dev.platform_data; -+	if (!board) { -+		dev_dbg(&spi->dev, "no platform_data\n"); -+		return -ENXIO; -+	} -+ -+	if (!board->dac_clk) { -+		dev_dbg(&spi->dev, "no DAC clk\n"); -+		return -ENXIO; -+	} -+ -+	if (IS_ERR(board->dac_clk)) { -+		dev_dbg(&spi->dev, "no DAC clk\n"); -+		return PTR_ERR(board->dac_clk); -+	} -+ -+	retval = -ENOMEM; -+ -+	/* Allocate "card" using some unused identifiers. */ -+	snprintf(id, sizeof id, "at73c213_%d", board->ssc_id); -+	card = snd_card_new(-1, id, THIS_MODULE, sizeof(struct snd_at73c213)); -+	if (!card) -+		goto out; -+ -+	chip = card->private_data; -+	chip->spi = spi; -+	chip->board = board; -+ -+	chip->ssc = ssc_request(board->ssc_id); -+	if (IS_ERR(chip->ssc)) { -+		dev_dbg(&spi->dev, "could not get ssc%d device\n", -+				board->ssc_id); -+		retval = PTR_ERR(chip->ssc); -+		goto out_card; -+	} -+ -+	retval = snd_at73c213_dev_init(card, spi); -+	if (retval) -+		goto out_ssc; -+ -+	strcpy(card->driver, "at73c213"); -+	strcpy(card->shortname, board->shortname); -+	sprintf(card->longname, "%s on irq %d", card->shortname, chip->irq); -+ -+	retval = snd_card_register(card); -+	if (retval) -+		goto out_ssc; -+ -+	dev_set_drvdata(&spi->dev, card); -+ -+	goto out; -+ -+out_ssc: -+	ssc_free(chip->ssc); -+out_card: -+	snd_card_free(card); -+out: -+	return retval; -+} -+ -+static int __devexit snd_at73c213_remove(struct spi_device *spi) -+{ -+	struct snd_card *card = dev_get_drvdata(&spi->dev); -+	struct snd_at73c213 *chip = card->private_data; -+	int retval; -+ -+	/* Stop playback. */ -+	ssc_writel(chip->ssc->regs, CR, SSC_BIT(CR_TXDIS)); -+ -+	/* Mute sound. */ -+	retval = snd_at73c213_write_reg(chip, DAC_LMPG, 0x3f); -+	if (retval) -+		goto out; -+	retval = snd_at73c213_write_reg(chip, DAC_RMPG, 0x3f); -+	if (retval) -+		goto out; -+	retval = snd_at73c213_write_reg(chip, DAC_LLOG, 0x3f); -+	if (retval) -+		goto out; -+	retval = snd_at73c213_write_reg(chip, DAC_RLOG, 0x3f); -+	if (retval) -+		goto out; -+	retval = snd_at73c213_write_reg(chip, DAC_LLIG, 0x11); -+	if (retval) -+		goto out; -+	retval = snd_at73c213_write_reg(chip, DAC_RLIG, 0x11); -+	if (retval) -+		goto out; -+	retval = snd_at73c213_write_reg(chip, DAC_AUXG, 0x11); -+	if (retval) -+		goto out; -+ -+	/* Turn off PA. */ -+	retval = snd_at73c213_write_reg(chip, PA_CTRL, (chip->reg_image[PA_CTRL]|0x0f)); -+	if (retval) -+		goto out; -+	msleep(10); -+	retval = snd_at73c213_write_reg(chip, PA_CTRL, (1<<PA_CTRL_APALP)|0x0f); -+	if (retval) -+		goto out; -+ -+	/* Turn off external DAC. */ -+	retval = snd_at73c213_write_reg(chip, DAC_CTRL, 0x0c); -+	if (retval) -+		goto out; -+	msleep(2); -+	retval = snd_at73c213_write_reg(chip, DAC_CTRL, 0x00); -+	if (retval) -+		goto out; -+ -+	/* Turn off master power. */ -+	retval = snd_at73c213_write_reg(chip, DAC_PRECH, 0x00); -+	if (retval) -+		goto out; -+ -+out: -+	/* Stop DAC master clock. */ -+	clk_disable(chip->board->dac_clk); -+ -+	ssc_free(chip->ssc); -+	snd_card_free(card); -+	dev_set_drvdata(&spi->dev, NULL); -+ -+	return 0; -+} -+ -+#ifdef CONFIG_PM -+static int snd_at73c213_suspend(struct spi_device *spi, pm_message_t msg) -+{ -+	struct snd_card *card = dev_get_drvdata(&spi->dev); -+	struct snd_at73c213 *chip = card->private_data; -+ -+	ssc_writel(chip->ssc->regs, CR, SSC_BIT(CR_TXDIS)); -+	clk_disable(chip->board->dac_clk); -+ -+	return 0; -+} -+ -+static int snd_at73c213_resume(struct spi_device *spi) -+{ -+	struct snd_card *card = dev_get_drvdata(&spi->dev); -+	struct snd_at73c213 *chip = card->private_data; -+ -+	clk_enable(chip->board->dac_clk); -+	ssc_writel(chip->ssc->regs, CR, SSC_BIT(CR_TXEN)); -+ -+	return 0; -+} -+#else -+#define snd_at73c213_suspend NULL -+#define snd_at73c213_resume NULL -+#endif -+ -+static struct spi_driver at73c213_driver = { -+	.driver		= { -+		.name	= "at73c213", -+	}, -+	.probe		= snd_at73c213_probe, -+	.suspend	= snd_at73c213_suspend, -+	.resume		= snd_at73c213_resume, -+	.remove		= __devexit_p(snd_at73c213_remove), -+}; -+ -+static int __init at73c213_init(void) -+{ -+	return spi_register_driver(&at73c213_driver); -+} -+module_init(at73c213_init); -+ -+static void __exit at73c213_exit(void) -+{ -+	spi_unregister_driver(&at73c213_driver); -+} -+module_exit(at73c213_exit); -+ -+MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>"); -+MODULE_DESCRIPTION("Sound driver for AT73C213 with Atmel SSC"); -+MODULE_LICENSE("GPL"); -diff --git a/sound/spi/at73c213.h b/sound/spi/at73c213.h -new file mode 100644 -index 0000000..fd8b372 ---- /dev/null -+++ b/sound/spi/at73c213.h -@@ -0,0 +1,119 @@ -+/* -+ * Driver for the AT73C213 16-bit stereo DAC on Atmel ATSTK1000 -+ * -+ * 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 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. -+ * -+ * The full GNU General Public License is included in this -+ * distribution in the file called COPYING. -+ */ -+ -+#ifndef _SND_AT73C213_H -+#define _SND_AT73C213_H -+ -+/* DAC control register */ -+#define DAC_CTRL		0x00 -+#define DAC_CTRL_ONPADRV	7 -+#define DAC_CTRL_ONAUXIN	6 -+#define DAC_CTRL_ONDACR		5 -+#define DAC_CTRL_ONDACL		4 -+#define DAC_CTRL_ONLNOR		3 -+#define DAC_CTRL_ONLNOL		2 -+#define DAC_CTRL_ONLNIR		1 -+#define DAC_CTRL_ONLNIL		0 -+ -+/* DAC left line in gain register */ -+#define DAC_LLIG		0x01 -+#define DAC_LLIG_LLIG		0 -+ -+/* DAC right line in gain register */ -+#define DAC_RLIG		0x02 -+#define DAC_RLIG_RLIG		0 -+ -+/* DAC Left Master Playback Gain Register */ -+#define DAC_LMPG		0x03 -+#define DAC_LMPG_LMPG		0 -+ -+/* DAC Right Master Playback Gain Register */ -+#define DAC_RMPG		0x04 -+#define DAC_RMPG_RMPG		0 -+ -+/* DAC Left Line Out Gain Register */ -+#define DAC_LLOG		0x05 -+#define DAC_LLOG_LLOG		0 -+ -+/* DAC Right Line Out Gain Register */ -+#define DAC_RLOG		0x06 -+#define DAC_RLOG_RLOG		0 -+ -+/* DAC Output Level Control Register */ -+#define DAC_OLC			0x07 -+#define DAC_OLC_RSHORT		7 -+#define DAC_OLC_ROLC		4 -+#define DAC_OLC_LSHORT		3 -+#define DAC_OLC_LOLC		0 -+ -+/* DAC Mixer Control Register */ -+#define DAC_MC			0x08 -+#define DAC_MC_INVR		5 -+#define DAC_MC_INVL		4 -+#define DAC_MC_RMSMIN2		3 -+#define DAC_MC_RMSMIN1		2 -+#define DAC_MC_LMSMIN2		1 -+#define DAC_MC_LMSMIN1		0 -+ -+/* DAC Clock and Sampling Frequency Control Register */ -+#define DAC_CSFC		0x09 -+#define DAC_CSFC_OVRSEL		4 -+ -+/* DAC Miscellaneous Register */ -+#define DAC_MISC		0x0A -+#define DAC_MISC_VCMCAPSEL	7 -+#define DAC_MISC_DINTSEL	4 -+#define DAC_MISC_DITHEN		3 -+#define DAC_MISC_DEEMPEN	2 -+#define DAC_MISC_NBITS		0 -+ -+/* DAC Precharge Control Register */ -+#define DAC_PRECH		0x0C -+#define DAC_PRECH_PRCHGPDRV	7 -+#define DAC_PRECH_PRCHGAUX1	6 -+#define DAC_PRECH_PRCHGLNOR	5 -+#define DAC_PRECH_PRCHGLNOL	4 -+#define DAC_PRECH_PRCHGLNIR	3 -+#define DAC_PRECH_PRCHGLNIL	2 -+#define DAC_PRECH_PRCHG		1 -+#define DAC_PRECH_ONMSTR	0 -+ -+/* DAC Auxiliary Input Gain Control Register */ -+#define DAC_AUXG		0x0D -+#define DAC_AUXG_AUXG		0 -+ -+/* DAC Reset Register */ -+#define DAC_RST			0x10 -+#define DAC_RST_RESMASK		2 -+#define DAC_RST_RESFILZ		1 -+#define DAC_RST_RSTZ		0 -+ -+/* Power Amplifier Control Register */ -+#define PA_CTRL			0x11 -+#define PA_CTRL_APAON		6 -+#define PA_CTRL_APAPRECH	5 -+#define PA_CTRL_APALP		4 -+#define PA_CTRL_APAGAIN		0 -+ -+#endif /* _SND_AT73C213_H */  | 
