diff options
| -rw-r--r-- | target/device/Atmel/arch-avr32/kernel-patches-2.6.22.1/linux-2.6.22.1-008-atmel-gpio_mouse-setup-for-atstk1000-board.patch | 130 | ||||
| -rw-r--r-- | target/device/Atmel/linux/kernel-patches-2.6.22.1/linux-2.6.22.1-001-at91+avr32.patch (renamed from target/device/Atmel/arch-avr32/kernel-patches-2.6.22.1/linux-2.6.22.1-003-atmel.3-avr32-updates.patch) | 23513 | ||||
| -rw-r--r-- | target/device/Atmel/linux/kernel-patches-2.6.22.1/linux-2.6.22.1-005-atags-support.patch | 122 | 
3 files changed, 16756 insertions, 7009 deletions
diff --git a/target/device/Atmel/arch-avr32/kernel-patches-2.6.22.1/linux-2.6.22.1-008-atmel-gpio_mouse-setup-for-atstk1000-board.patch b/target/device/Atmel/arch-avr32/kernel-patches-2.6.22.1/linux-2.6.22.1-008-atmel-gpio_mouse-setup-for-atstk1000-board.patch deleted file mode 100644 index 5683be6f3..000000000 --- a/target/device/Atmel/arch-avr32/kernel-patches-2.6.22.1/linux-2.6.22.1-008-atmel-gpio_mouse-setup-for-atstk1000-board.patch +++ /dev/null @@ -1,130 +0,0 @@ ->From 9c5fa914202d20756c56e0c4fd76035ed8f8ced8 Mon Sep 17 00:00:00 2001 -From: Hans-Christian Egtvedt <hcegtvedt@atmel.com> -Date: Mon, 6 Aug 2007 08:31:14 +0200 -Subject: [PATCH 1/1] Add gpio_mouse board setup to atstk1000 board - -This patch adds a gpio_mouse_platform_data to the atstk1000 board code and -registers a gpio_mouse platform_device. This will enable a GPIO mouse on header -J1 on GPIO of the ATSTK1000 development kit. The board code is enabled/disabled -in menuconfig. - -By connecting J1 (GPIO) to J25 (SWITCH) you can use the following keys to -simulate a mouse: - -SW0: right -SW1: down -SW2: up -SW3: left -SW5: right button -SW6: middle button -SW7: left button - -Signed-off-by: Hans-Christian Egtvedt <hcegtvedt@atmel.com> ---- - arch/avr32/boards/atstk1000/Kconfig     |   16 ++++++++++ - arch/avr32/boards/atstk1000/atstk1002.c |   48 +++++++++++++++++++++++++++++++ - 2 files changed, 64 insertions(+), 0 deletions(-) - -diff --git a/arch/avr32/boards/atstk1000/Kconfig b/arch/avr32/boards/atstk1000/Kconfig -index 718578f..d99d4bd 100644 ---- a/arch/avr32/boards/atstk1000/Kconfig -+++ b/arch/avr32/boards/atstk1000/Kconfig -@@ -50,6 +50,22 @@ config BOARD_ATSTK1002_SPI1 - 	  GPIO lines and accessed through the J1 jumper block.  Say "y" - 	  here to configure that SPI controller. -  -+config BOARD_ATSTK1002_GPIO_MOUSE -+	bool "Configure gpio_mouse on GPIO J1 header" -+	depends on !BOARD_ATSTK1002_SW4_CUSTOM -+	help -+	  Enable gpio_mouse board configuration on GPIO 0 to 7. Connecting a -+	  10-pin flat cable from J1 (GPIO) to J25 (SWITCH) will let a user give -+	  mouse inputs using the the switches SW0 to SW7. -+ -+	  SW0: right -+	  SW1: down -+	  SW2: up -+	  SW3: left -+	  SW5: right button -+	  SW6: middle button -+	  SW7: left button -+ - config BOARD_ATSTK1002_J2_LED - 	bool - 	default BOARD_ATSTK1002_J2_LED8 || BOARD_ATSTK1002_J2_RGB -diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c -index c958fd4..c7560e5 100644 ---- a/arch/avr32/boards/atstk1000/atstk1002.c -+++ b/arch/avr32/boards/atstk1000/atstk1002.c -@@ -17,6 +17,7 @@ - #include <linux/types.h> - #include <linux/spi/spi.h> - #include <linux/spi/at73c213.h> -+#include <linux/gpio_mouse.h> -  - #include <video/atmel_lcdc.h> -  -@@ -91,6 +92,49 @@ static struct mci_platform_data __initdata mci0_data = { - 	.wp_pin		= GPIO_PIN_NONE, - }; -  -+#ifdef CONFIG_BOARD_ATSTK1002_GPIO_MOUSE -+static struct gpio_mouse_platform_data gpio_mouse0_data = { -+	.polarity	= GPIO_MOUSE_POLARITY_ACT_LOW, -+	{ -+		{ -+			.up		= GPIO_PIN_PB(2), -+			.down		= GPIO_PIN_PB(1), -+			.left		= GPIO_PIN_PB(3), -+			.right		= GPIO_PIN_PB(0), -+			.bleft		= GPIO_PIN_PB(7), -+			.bmiddle	= GPIO_PIN_PB(6), -+			.bright		= GPIO_PIN_PB(5), -+		}, -+	}, -+	.scan_ms	= 10, -+}; -+ -+static struct platform_device gpio_mouse0_device = { -+	.name		= "gpio_mouse", -+	.id		= 0, -+	.dev		= { -+		.platform_data = &gpio_mouse0_data, -+	}, -+}; -+ -+static void __init add_device_gpio_mouse0(void) -+{ -+	struct platform_device *pdev = &gpio_mouse0_device; -+	struct gpio_mouse_platform_data *data = pdev->dev.platform_data; -+ -+	at32_select_gpio(data->up, 0); -+	at32_select_gpio(data->down, 0); -+	at32_select_gpio(data->left, 0); -+	at32_select_gpio(data->right, 0); -+ -+	at32_select_gpio(data->bleft, 0); -+	at32_select_gpio(data->bmiddle, 0); -+	at32_select_gpio(data->bright, 0); -+ -+	platform_device_register(pdev); -+} -+#endif -+ - /* -  * The next two functions should go away as the boot loader is -  * supposed to initialize the macb address registers with a valid -@@ -317,6 +361,10 @@ static int __init atstk1002_init(void) - #endif - #endif -  -+#ifdef CONFIG_BOARD_ATSTK1002_GPIO_MOUSE -+	add_device_gpio_mouse0(); -+#endif -+ - 	return 0; - } - postcore_initcall(atstk1002_init); ---  -1.5.2.3 - diff --git a/target/device/Atmel/arch-avr32/kernel-patches-2.6.22.1/linux-2.6.22.1-003-atmel.3-avr32-updates.patch b/target/device/Atmel/linux/kernel-patches-2.6.22.1/linux-2.6.22.1-001-at91+avr32.patch index 9da7547b3..adc8189a6 100644 --- a/target/device/Atmel/arch-avr32/kernel-patches-2.6.22.1/linux-2.6.22.1-003-atmel.3-avr32-updates.patch +++ b/target/device/Atmel/linux/kernel-patches-2.6.22.1/linux-2.6.22.1-001-at91+avr32.patch @@ -1,2279 +1,8603 @@ -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 +Index: linux-2.6.22.1/include/asm-arm/arch-at91/at91sam9260_matrix.h +=================================================================== +--- linux-2.6.22.1/include/asm-arm/arch-at91/at91sam9260_matrix.h	(revision 1) ++++ linux-2.6.22.1/include/asm-arm/arch-at91/at91sam9260_matrix.h	(arbetskopia) +@@ -67,7 +67,7 @@ + #define		AT91_MATRIX_CS4A		(1 << 4)	/* Chip Select 4 Assignment */ + #define			AT91_MATRIX_CS4A_SMC		(0 << 4) + #define			AT91_MATRIX_CS4A_SMC_CF1	(1 << 4) +-#define		AT91_MATRIX_CS5A		(1 << 5 )	/* Chip Select 5 Assignment */ ++#define		AT91_MATRIX_CS5A		(1 << 5)	/* Chip Select 5 Assignment */ + #define			AT91_MATRIX_CS5A_SMC		(0 << 5) + #define			AT91_MATRIX_CS5A_SMC_CF2	(1 << 5) + #define		AT91_MATRIX_DBPUC		(1 << 8)	/* Data Bus Pull-up Configuration */ +Index: linux-2.6.22.1/include/asm-arm/arch-at91/ics1523.h +=================================================================== +--- linux-2.6.22.1/include/asm-arm/arch-at91/ics1523.h	(revision 0) ++++ linux-2.6.22.1/include/asm-arm/arch-at91/ics1523.h	(revision 0) +@@ -0,0 +1,154 @@ ++//*---------------------------------------------------------------------------- ++//*         ATMEL Microcontroller Software Support  -  ROUSSET  - ++//*---------------------------------------------------------------------------- ++//* The software is delivered "AS IS" without warranty or condition of any ++//* kind, either express, implied or statutory. This includes without ++//* limitation any warranty or condition with respect to merchantability or ++//* fitness for any particular purpose, or against the infringements of ++//* intellectual property rights of others. ++//*---------------------------------------------------------------------------- ++//* File Name           : ics1523.h ++//* Object              : Clock Generator Prototyping File. ++//* ++//* 1.0 08/28/02 ED     : Creation ++//* 1.2 13/01/03 FB		: Update on lib V3 ++//*---------------------------------------------------------------------------- ++ ++#ifndef ics1523_h ++#define ics1523_h ++ ++/*-------------------------------------------*/ ++/* ICS1523 TWI Serial Clock Definition       */ ++/*-------------------------------------------*/ ++ ++#define		ICS_MIN_CLOCK		100		/* Min Frequency Access Clock KHz */ ++#define		ICS_MAX_CLOCK		400		/* Max Frequency Access Clock KHz */ ++#define		ICS_TRANSFER_RATE	ICS_MAX_CLOCK	/* Transfer speed to apply */ ++ ++#define		ICS_WRITE_CLK_PNB	30		/* TWCK Clock Periods required to write */ ++#define		ICS_READ_CLK_PNB	40		/* TWCK Clock Periods required to read */ ++ ++/*-------------------------------------------*/ ++/* ICS1523 Write Operation Definition        */ ++/*-------------------------------------------*/ ++ ++#define		ICS1523_ACCESS_OK	0		/* OK */ ++#define		ICS1523_ACCESS_ERROR	-1		/* NOK */ ++ ++/*-------------------------------------------*/ ++/* ICS1523 Device Addresses Definition       */ ++/*-------------------------------------------*/ ++ ++#define		ICS_ADDR		0x26		/* Device Address */ ++ ++/*--------------------------------------------------*/ ++/* ICS1523 Registers Internal Addresses Definition  */ ++/*--------------------------------------------------*/ ++ ++#define		ICS_ICR			0x0		/* Input Control Register */ ++#define		ICS_LCR			0x1		/* Loop Control Register */ ++#define		ICS_FD0			0x2		/* PLL FeedBack Divider LSBs */ ++#define		ICS_FD1			0x3		/* PLL FeedBack Divider MSBs */ ++#define		ICS_DPAO		0x4		/* Dynamic Phase Aligner Offset */ ++#define		ICS_DPAC		0x5		/* Dynamic Phase Aligner Resolution */ ++#define		ICS_OE			0x6		/* Output Enables Register */ ++#define		ICS_OD			0x7		/* Osc Divider Register */ ++#define		ICS_SWRST		0x8		/* DPA & PLL Reset Register */ ++#define		ICS_VID			0x10		/* Chip Version Register */ ++#define		ICS_RID			0x11		/* Chip Revision Register */ ++#define		ICS_SR			0x12		/* Status Register */ ++ ++/*------------------------------------------------------*/ ++/* ICS1523 Input Control Register Bits Definition       */ ++/*------------------------------------------------------*/ ++ ++#define		ICS_PDEN		0x1		/* Phase Detector Enable */ ++#define		ICS_PDPOL		0x2		/* Phase Detector Enable Polarity */ ++#define		ICS_REFPOL		0x4		/* External Reference Polarity */ ++#define		ICS_FBKPOL		0x8		/* External Feedback Polarity */ ++#define		ICS_FBKSEL		0x10		/* External Feedback Select */ ++#define		ICS_FUNCSEL		0x20		/* Function Out Select */ ++#define		ICS_ENPLS		0x40		/* Enable PLL Lock/Ref Status Output */ ++#define		ICS_ENDLS		0x80		/* Enable DPA Lock/Ref Status Output */ ++ ++/*-----------------------------------------------------*/ ++/* ICS1523 Loop Control Register Bits Definition       */ ++/*-----------------------------------------------------*/ ++ ++#define		ICS_PFD			0x7		/* Phase Detector Gain */ ++#define		ICS_PSD			0x30		/* Post-Scaler Divider */ ++ ++/*----------------------------------------------------*/ ++/* ICS1523 PLL FeedBack Divider LSBs Definition       */ ++/*----------------------------------------------------*/ ++ ++#define		ICS_FBDL		0xFF		/* PLL FeedBack Divider LSBs */ ++ ++/*----------------------------------------------------*/ ++/* ICS1523 PLL FeedBack Divider MSBs Definition       */ ++/*----------------------------------------------------*/ ++ ++#define		ICS_FBDM		0xF		/* PLL FeedBack Divider MSBs */ ++ ++/*------------------------------------------------------------*/ ++/* ICS1523 Dynamic Phase Aligner Offset Bits Definition       */ ++/*------------------------------------------------------------*/ ++ ++#define		ICS_DPAOS		0x2F		/* Dynamic Phase Aligner Offset */ ++#define		ICS_FILSEL		0x80		/* Loop Filter Select */ ++ ++/*----------------------------------------------------------------*/ ++/* ICS1523 Dynamic Phase Aligner Resolution Bits Definition       */ ++/*----------------------------------------------------------------*/ ++ ++#define		ICS_DPARES		0x3		/* Dynamic Phase Aligner Resolution */ ++#define		ICS_MMREV		0xFC		/* Metal Mask Revision Number */ ++ ++/*-------------------------------------------------------*/ ++/* ICS1523 Output Enables Register Bits Definition       */ ++/*-------------------------------------------------------*/ ++ ++#define		ICS_OEPCK		0x1		/* Output Enable for PECL PCLK Outputs */ ++#define		ICS_OETCK		0x2		/* Output Enable for STTL CLK Output */ ++#define		ICS_OEP2		0x4		/* Output Enable for PECL CLK/2 Outputs */ ++#define		ICS_OET2		0x8		/* Output Enable for STTL CLK/2 Output */ ++#define		ICS_OEF			0x10		/* Output Enable for STTL FUNC Output */ ++#define		ICS_CLK2INV		0x20		/* CLK/2 Invert */ ++#define		ICS_OSCL		0xC0		/* SSTL Clock Scaler */ ++ ++/*----------------------------------------------------*/ ++/* ICS1523 Osc Divider Register Bits Definition       */ ++/*----------------------------------------------------*/ ++ ++#define		ICS_OSCDIV		0x7F		/* Oscillator Divider Modulus */ ++#define		ICS_INSEL		0x80		/* Input Select */ ++ ++/*---------------------------------------------------*/ ++/* ICS1523 DPA & PLL Reset Register Definition       */ ++/*---------------------------------------------------*/ ++ ++#define		ICS_DPAR		0x0A		/* DPA Reset Command */ ++#define		ICS_PLLR		0x50		/* PLL Reset Command */ ++ ++/*------------------------------------------------*/ ++/* ICS1523 Chip Version Register Definition       */ ++/*------------------------------------------------*/ ++ ++#define		ICS_CHIPV		0xFF		/* Chip Version */ ++ ++/*-------------------------------------------------*/ ++/* ICS1523 Chip Revision Register Definition       */ ++/*-------------------------------------------------*/ ++ ++#define		ICS_CHIPR		0xFF		/* Chip Revision */ ++ ++/*------------------------------------------*/ ++/* ICS1523 Status Register Definition       */ ++/*------------------------------------------*/ ++ ++#define		ICS_DPALOCK		0x1		/* DPA Lock Status */ ++#define		ICS_PLLLOCK		0x2		/* PLL Lock Status */ ++ ++int at91_ics1523_init(void); ++ ++#endif /* ics1523_h */ +Index: linux-2.6.22.1/include/asm-arm/arch-at91/spi.h +=================================================================== +--- linux-2.6.22.1/include/asm-arm/arch-at91/spi.h	(revision 0) ++++ linux-2.6.22.1/include/asm-arm/arch-at91/spi.h	(revision 0) +@@ -0,0 +1,54 @@ ++/* ++ * Serial Peripheral Interface (SPI) driver for the Atmel AT91RM9200 ++ * ++ * (c) SAN People (Pty) Ltd ++ * ++ * 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. ++ */ ++ ++#ifndef AT91_LEGACY_SPI_H ++#define AT91_LEGACY_SPI_H ++ ++#define SPI_MAJOR		153	/* registered device number */ ++ ++#define DEFAULT_SPI_CLK		6000000 ++ ++ ++/* Maximum number of buffers in a single SPI transfer. ++ *  DataFlash uses maximum of 2 ++ *  spidev interface supports up to 8. ++ */ ++#define MAX_SPI_TRANSFERS	8 ++#define NR_SPI_DEVICES		4	/* number of devices on SPI bus */ ++ ++/* ++ * Describes the buffers for a SPI transfer. ++ * A transmit & receive buffer must be specified for each transfer ++ */ ++struct spi_transfer_list { ++	void* tx[MAX_SPI_TRANSFERS];	/* transmit */ ++	int txlen[MAX_SPI_TRANSFERS]; ++	void* rx[MAX_SPI_TRANSFERS];	/* receive */ ++	int rxlen[MAX_SPI_TRANSFERS]; ++	int nr_transfers;		/* number of transfers */ ++	int curr;			/* current transfer */ ++}; ++ ++struct spi_local { ++	unsigned int pcs;		/* Peripheral Chip Select value */ ++ ++	struct spi_transfer_list *xfers;	/* current transfer list */ ++	dma_addr_t tx, rx;		/* DMA address for current transfer */ ++	dma_addr_t txnext, rxnext;	/* DMA address for next transfer */ ++}; ++ ++ ++/* Exported functions */ ++extern void spi_access_bus(short device); ++extern void spi_release_bus(short device); ++extern int spi_transfer(struct spi_transfer_list* list); ++ ++#endif +Index: linux-2.6.22.1/include/asm-arm/arch-at91/at91_mci.h +=================================================================== +--- linux-2.6.22.1/include/asm-arm/arch-at91/at91_mci.h	(revision 1) ++++ linux-2.6.22.1/include/asm-arm/arch-at91/at91_mci.h	(arbetskopia) +@@ -26,6 +26,9 @@ + #define AT91_MCI_MR		0x04		/* Mode Register */ + #define		AT91_MCI_CLKDIV		(0xff  <<  0)	/* Clock Divider */ + #define		AT91_MCI_PWSDIV		(7     <<  8)	/* Power Saving Divider */ ++#define		AT91_MCI_RDPROOF	(1     << 11)	/* Read Proof Enable [SAM926[03] only] */ ++#define		AT91_MCI_WRPROOF	(1     << 12)	/* Write Proof Enable [SAM926[03] only] */ ++#define		AT91_MCI_PDCFBYTE	(1     << 13)	/* PDC Force Byte Transfer [SAM926[03] only] */ + #define		AT91_MCI_PDCPADV	(1     << 14)	/* PDC Padding Value */ + #define		AT91_MCI_PDCMODE	(1     << 15)	/* PDC-orientated Mode */ + #define		AT91_MCI_BLKLEN		(0xfff << 18)	/* Data Block Length */ +Index: linux-2.6.22.1/include/asm-arm/arch-at91/at91_pmc.h +=================================================================== +--- linux-2.6.22.1/include/asm-arm/arch-at91/at91_pmc.h	(revision 1) ++++ linux-2.6.22.1/include/asm-arm/arch-at91/at91_pmc.h	(arbetskopia) +@@ -37,7 +37,9 @@ + #define	AT91_PMC_PCDR		(AT91_PMC + 0x14)	/* Peripheral Clock Disable Register */ + #define	AT91_PMC_PCSR		(AT91_PMC + 0x18)	/* Peripheral Clock Status Register */ +  +-#define	AT91_CKGR_MOR		(AT91_PMC + 0x20)	/* Main Oscillator Register */ ++#define AT91_CKGR_UCKR		(AT91_PMC + 0x1C)	/* UTMI Clock Register [SAM9RL only] */ ++ ++#define	AT91_CKGR_MOR		(AT91_PMC + 0x20)	/* Main Oscillator Register [not on SAM9RL] */ + #define		AT91_PMC_MOSCEN		(1    << 0)		/* Main Oscillator Enable */ + #define		AT91_PMC_OSCBYPASS	(1    << 1)		/* Oscillator Bypass [AT91SAM926x only] */ + #define		AT91_PMC_OSCOUNT	(0xff << 8)		/* Main Oscillator Start-up Time */ +Index: linux-2.6.22.1/include/asm-arm/arch-at91/board.h +=================================================================== +--- linux-2.6.22.1/include/asm-arm/arch-at91/board.h	(revision 1) ++++ linux-2.6.22.1/include/asm-arm/arch-at91/board.h	(arbetskopia) +@@ -64,6 +64,7 @@ -+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 +  /* Ethernet (EMAC & MACB) */ + struct at91_eth_data { ++	u32		phy_mask; + 	u8		phy_irq_pin;	/* PHY IRQ */ + 	u8		is_rmii;	/* using RMII interface? */ + }; +@@ -124,9 +125,21 @@ + }; + extern void __init at91_add_device_ac97(struct atmel_ac97_data *data); +  ++ /* ISI */ ++extern void __init at91_add_device_isi(void); ++ +  /* LEDs */ + extern u8 at91_leds_cpu; + extern u8 at91_leds_timer; + extern void __init at91_init_leds(u8 cpu_led, u8 timer_led); +  ++struct at91_gpio_led { ++	u8		index;		/* index of LED */ ++	char*		name;		/* name of LED */ ++	u8		gpio;		/* AT91_PIN_xx */ ++	u8		flags;		/* 1=active-high */ ++	char*		trigger;	/* default trigger */ ++}; ++extern void __init at91_gpio_leds(struct at91_gpio_led *leds, int nr);  + - 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 + #endif +Index: linux-2.6.22.1/include/linux/spi/at73c213.h +=================================================================== +--- linux-2.6.22.1/include/linux/spi/at73c213.h	(revision 0) ++++ linux-2.6.22.1/include/linux/spi/at73c213.h	(revision 0) +@@ -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 */ +Index: linux-2.6.22.1/include/linux/leds.h +=================================================================== +--- linux-2.6.22.1/include/linux/leds.h	(revision 1) ++++ linux-2.6.22.1/include/linux/leds.h	(arbetskopia) +@@ -110,4 +110,18 @@ + #define ledtrig_ide_activity() do {} while(0) + #endif -+if BOARD_ATSTK1000 -+source "arch/avr32/boards/atstk1000/Kconfig" -+endif -+if BOARD_ATNGW100 -+source "arch/avr32/boards/atngw100/Kconfig" -+endif ++/* For the leds-gpio driver */ ++struct gpio_led { ++	const char *name; ++	char *default_trigger; ++	unsigned 	gpio; ++	u8 		active_low; ++};  + - 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. ++struct gpio_led_platform_data { ++	int 		num_leds; ++	struct gpio_led *leds; ++}; ++ ++ + #endif		/* __LINUX_LEDS_H_INCLUDED */ +Index: linux-2.6.22.1/include/linux/clk.h +=================================================================== +--- linux-2.6.22.1/include/linux/clk.h	(revision 1) ++++ linux-2.6.22.1/include/linux/clk.h	(arbetskopia) +@@ -121,4 +121,24 @@ +  */ + struct clk *clk_get_parent(struct clk *clk); -+config DW_DMAC -+	tristate "Synopsys DesignWare DMA Controller support" -+	default y if CPU_AT32AP7000 ++/** ++ * clk_must_disable - report whether a clock's users must disable it ++ * @clk: one node in the clock tree ++ * ++ * This routine returns true only if the upcoming system state requires ++ * disabling the specified clock. ++ * ++ * It's common for platform power states to constrain certain clocks (and ++ * their descendants) to be unavailable, while other states allow that ++ * clock to be active.  A platform's power states often include an "all on" ++ * mode; system wide sleep states like "standby" or "suspend-to-RAM"; and ++ * operating states which sacrifice functionality for lower power usage. ++ * ++ * The constraint value is commonly tested in device driver suspend(), to ++ * leave clocks active if they are needed for features like wakeup events. ++ * On platforms that support reduced functionality operating states, the ++ * constraint may also need to be tested during resume() and probe() calls. ++ */ ++int clk_must_disable(struct clk *clk);  + - # FPU emulation goes here + #endif +Index: linux-2.6.22.1/include/linux/usb/Kbuild +=================================================================== +--- linux-2.6.22.1/include/linux/usb/Kbuild	(revision 1) ++++ linux-2.6.22.1/include/linux/usb/Kbuild	(arbetskopia) +@@ -1,5 +1,6 @@ + unifdef-y += audio.h + unifdef-y += cdc.h + unifdef-y += ch9.h ++unifdef-y += gadgetfs.h + unifdef-y += midi.h - source "kernel/Kconfig.hz" -@@ -185,6 +196,27 @@ config CMDLINE +Index: linux-2.6.22.1/include/linux/usb/gadgetfs.h +=================================================================== +--- linux-2.6.22.1/include/linux/usb/gadgetfs.h	(revision 0) ++++ linux-2.6.22.1/include/linux/usb/gadgetfs.h	(revision 0) +@@ -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 */ +Index: linux-2.6.22.1/include/linux/usb_gadgetfs.h +=================================================================== +--- linux-2.6.22.1/include/linux/usb_gadgetfs.h	(revision 1) ++++ linux-2.6.22.1/include/linux/usb_gadgetfs.h	(arbetskopia) +@@ -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) +- +- +Index: linux-2.6.22.1/include/linux/atmel-ssc.h +=================================================================== +--- linux-2.6.22.1/include/linux/atmel-ssc.h	(revision 0) ++++ linux-2.6.22.1/include/linux/atmel-ssc.h	(revision 0) +@@ -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 */ +Index: linux-2.6.22.1/include/linux/gpio_mouse.h +=================================================================== +--- linux-2.6.22.1/include/linux/gpio_mouse.h	(revision 0) ++++ linux-2.6.22.1/include/linux/gpio_mouse.h	(revision 0) +@@ -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 */ +Index: linux-2.6.22.1/include/linux/i2c-id.h +=================================================================== +--- linux-2.6.22.1/include/linux/i2c-id.h	(revision 1) ++++ linux-2.6.22.1/include/linux/i2c-id.h	(arbetskopia) +@@ -203,6 +203,7 @@ +  + /* --- PCA 9564 based algorithms */ + #define I2C_HW_A_ISA		0x1a0000 /* generic ISA Bus interface card */ ++#define I2C_HW_A_PLAT		0x1a0001 /* generic platform_bus interface */ +  + /* --- ACPI Embedded controller algorithms                              */ + #define I2C_HW_ACPI_EC          0x1f0000 +Index: linux-2.6.22.1/include/asm-avr32/unaligned.h +=================================================================== +--- linux-2.6.22.1/include/asm-avr32/unaligned.h	(revision 1) ++++ linux-2.6.22.1/include/asm-avr32/unaligned.h	(arbetskopia) +@@ -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. +  */ - endmenu +-#include <linux/string.h> ++#include <asm-generic/unaligned.h> -+menu "Power managment options" +-/* 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; }) +- + #endif /* __ASM_AVR32_UNALIGNED_H */ +Index: linux-2.6.22.1/include/asm-avr32/atomic.h +=================================================================== +--- linux-2.6.22.1/include/asm-avr32/atomic.h	(revision 1) ++++ linux-2.6.22.1/include/asm-avr32/atomic.h	(arbetskopia) +@@ -101,7 +101,7 @@ + 		"	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 @@ + 			"	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"); + 	} +  +Index: linux-2.6.22.1/include/asm-avr32/dma-controller.h +=================================================================== +--- linux-2.6.22.1/include/asm-avr32/dma-controller.h	(revision 0) ++++ linux-2.6.22.1/include/asm-avr32/dma-controller.h	(revision 0) +@@ -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  + -+menu "CPU Frequency scaling" ++#include <linux/device.h>  + -+source "drivers/cpufreq/Kconfig" ++#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  + -+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. ++#define DMA_WIDTH_8BIT			0 ++#define DMA_WIDTH_16BIT			1 ++#define DMA_WIDTH_32BIT			2  + -+	  For details, take a look in <file:Documentation/cpu-freq>. ++struct dma_request { ++	struct dma_controller *dmac; ++	struct list_head list;  + -+	  If in doubt, say N. ++	unsigned short channel;  + -+endmenu ++	void (*xfer_complete)(struct dma_request *req); ++	void (*block_complete)(struct dma_request *req); ++	void (*error)(struct dma_request *req); ++};  + -+endmenu ++struct dma_request_sg { ++	struct dma_request req;  + - 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/ ++	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 */ +Index: linux-2.6.22.1/include/asm-avr32/arch-at32ap/portmux.h +=================================================================== +--- linux-2.6.22.1/include/asm-avr32/arch-at32ap/portmux.h	(revision 1) ++++ linux-2.6.22.1/include/asm-avr32/arch-at32ap/portmux.h	(arbetskopia) +@@ -25,4 +25,16 @@ + void at32_select_gpio(unsigned int pin, unsigned long flags); + void at32_reserve_pin(unsigned int pin); - 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 ++#ifdef CONFIG_GPIO_DEV  + -+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. ++/* 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);  + -+	  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> ++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__ */ +Index: linux-2.6.22.1/include/asm-avr32/arch-at32ap/board.h +=================================================================== +--- linux-2.6.22.1/include/asm-avr32/arch-at32ap/board.h	(revision 1) ++++ linux-2.6.22.1/include/asm-avr32/arch-at32ap/board.h	(arbetskopia) +@@ -6,6 +6,8 @@ +    #include <linux/types.h> -+#include <linux/leds.h> - #include <linux/spi/spi.h> - #include <asm/io.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 @@ - #include <asm/arch/at32ap7000.h> - #include <asm/arch/board.h> - #include <asm/arch/init.h> -+#include <asm/arch/portmux.h> + struct platform_device *at32_add_device_usart(unsigned int id); - /* Initialized by bootloader-specific startup code. */ - struct tag *bootloader_tags __initdata; -@@ -39,6 +42,11 @@ static struct spi_board_info spi0_board_info[] __initdata = { - 	}, + struct eth_platform_data { ++	u32	phy_mask; + 	u8	is_rmii;   }; + struct platform_device * +@@ -30,9 +33,41 @@ + struct platform_device * + at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n); -+static struct mci_platform_data __initdata mci0_data = { -+	.detect_pin	= GPIO_PIN_PC(25), -+	.wp_pin		= GPIO_PIN_PE(0), ++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);  + - /* -  * 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); - } ++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); -+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, }, ++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 */ +Index: linux-2.6.22.1/scripts/checkstack.pl +=================================================================== +--- linux-2.6.22.1/scripts/checkstack.pl	(revision 1) ++++ linux-2.6.22.1/scripts/checkstack.pl	(arbetskopia) +@@ -12,6 +12,7 @@ + #	sh64 port by Paul Mundt + #	Random bits by Matt Mackall <mpm@selenic.com> + #	M68k port by Geert Uytterhoeven and Andreas Schwab ++#	AVR32 port by Haavard Skinnemoen <hskinnemoen@atmel.com> + # + #	Usage: + #	objdump -d vmlinux | stackcheck.pl [arch] +@@ -37,6 +38,10 @@ + 	if ($arch eq 'arm') { + 		#c0008ffc:	e24dd064	sub	sp, sp, #100	; 0x64 + 		$re = qr/.*sub.*sp, sp, #(([0-9]{2}|[3-9])[0-9]{2})/o; ++	} elsif ($arch eq 'avr32') { ++		#8000008a:       20 1d           sub sp,4 ++		#80000ca8:       fa cd 05 b0     sub sp,sp,1456 ++		$re = qr/^.*sub.*sp.*,([0-9]{1,8})/o; + 	} elsif ($arch =~ /^i[3456]86$/) { + 		#c0105234:       81 ec ac 05 00 00       sub    $0x5ac,%esp + 		$re = qr/^.*[as][du][db]    \$(0x$x{1,8}),\%esp$/o; +Index: linux-2.6.22.1/sound/Kconfig +=================================================================== +--- linux-2.6.22.1/sound/Kconfig	(revision 1) ++++ linux-2.6.22.1/sound/Kconfig	(arbetskopia) +@@ -63,9 +63,13 @@ +  + 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" +  +Index: linux-2.6.22.1/sound/soc/at91/eti_b1_wm8731.c +=================================================================== +--- linux-2.6.22.1/sound/soc/at91/eti_b1_wm8731.c	(revision 1) ++++ linux-2.6.22.1/sound/soc/at91/eti_b1_wm8731.c	(arbetskopia) +@@ -34,8 +34,7 @@ + #include <sound/soc.h> + #include <sound/soc-dapm.h> +  +-#include <asm/arch/hardware.h> +-#include <asm/arch/at91_pio.h> ++#include <asm/hardware.h> + #include <asm/arch/gpio.h> +  + #include "../codecs/wm8731.h" +@@ -48,13 +47,6 @@ + #define	DBG(x...) + #endif +  +-#define AT91_PIO_TF1	(1 << (AT91_PIN_PB6 - PIN_BASE) % 32) +-#define AT91_PIO_TK1	(1 << (AT91_PIN_PB7 - PIN_BASE) % 32) +-#define AT91_PIO_TD1	(1 << (AT91_PIN_PB8 - PIN_BASE) % 32) +-#define AT91_PIO_RD1	(1 << (AT91_PIN_PB9 - PIN_BASE) % 32) +-#define AT91_PIO_RK1	(1 << (AT91_PIN_PB10 - PIN_BASE) % 32) +-#define AT91_PIO_RF1	(1 << (AT91_PIN_PB11 - PIN_BASE) % 32) +- + static struct clk *pck1_clk; + static struct clk *pllb_clk; +  +@@ -277,7 +269,6 @@ + static int __init eti_b1_init(void) + { + 	int ret; +-	u32 ssc_pio_lines; + 	struct at91_ssc_periph *ssc = eti_b1_dai.cpu_dai->private_data; +  + 	if (!request_mem_region(AT91RM9200_BASE_SSC1, SZ_16K, "soc-audio")) { +@@ -311,20 +302,13 @@ + 		goto fail_io_unmap; + 	} +  +- 	ssc_pio_lines = AT91_PIO_TF1 | AT91_PIO_TK1 | AT91_PIO_TD1 +-			| AT91_PIO_RD1 /* | AT91_PIO_RK1 */ | AT91_PIO_RF1; ++ 	at91_set_A_periph(AT91_PIN_PB6, 0);	/* TF1 */ ++ 	at91_set_A_periph(AT91_PIN_PB7, 0);	/* TK1 */ ++ 	at91_set_A_periph(AT91_PIN_PB8, 0);	/* TD1 */ ++ 	at91_set_A_periph(AT91_PIN_PB9, 0);	/* RD1 */ ++/* 	at91_set_A_periph(AT91_PIN_PB10, 0);*/	/* RK1 */ 	 ++ 	at91_set_A_periph(AT91_PIN_PB11, 0);	/* RF1 */ +  +-	/* Reset all PIO registers and assign lines to peripheral A */ +- 	at91_sys_write(AT91_PIOB + PIO_PDR,  ssc_pio_lines); +- 	at91_sys_write(AT91_PIOB + PIO_ODR,  ssc_pio_lines); +- 	at91_sys_write(AT91_PIOB + PIO_IFDR, ssc_pio_lines); +- 	at91_sys_write(AT91_PIOB + PIO_CODR, ssc_pio_lines); +- 	at91_sys_write(AT91_PIOB + PIO_IDR,  ssc_pio_lines); +- 	at91_sys_write(AT91_PIOB + PIO_MDDR, ssc_pio_lines); +- 	at91_sys_write(AT91_PIOB + PIO_PUDR, ssc_pio_lines); +- 	at91_sys_write(AT91_PIOB + PIO_ASR,  ssc_pio_lines); +- 	at91_sys_write(AT91_PIOB + PIO_OWDR, ssc_pio_lines); +- + 	/* + 	 * Set PCK1 parent to PLLB and its rate to 12 Mhz. + 	 */ +Index: linux-2.6.22.1/sound/spi/Kconfig +=================================================================== +--- linux-2.6.22.1/sound/spi/Kconfig	(revision 0) ++++ linux-2.6.22.1/sound/spi/Kconfig	(revision 0) +@@ -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 +Index: linux-2.6.22.1/sound/spi/at73c213.c +=================================================================== +--- linux-2.6.22.1/sound/spi/at73c213.c	(revision 0) ++++ linux-2.6.22.1/sound/spi/at73c213.c	(revision 0) +@@ -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 */  +};  + -+static const struct gpio_led_platform_data ngw_led_data = { -+	.num_leds =	ARRAY_SIZE(ngw_leds), -+	.leds =		(void *) ngw_leds, ++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;  +};  + -+static struct platform_device ngw_gpio_leds = { -+	.name =		"leds-gpio", -+	.id =		-1, -+	.dev = { -+		.platform_data = (void *) &ngw_led_data, ++#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,  +};  + -+#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 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 struct platform_device i2c_gpio_device = { -+	.name		= "i2c-gpio", -+	.id		= 0, -+	.dev		= { -+		.platform_data	= &i2c_gpio_data, ++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),  +}; -+#endif  + - static int __init atngw100_init(void) - { -+	unsigned	i; ++static int __init at73c213_init(void) ++{ ++	return spi_register_driver(&at73c213_driver); ++} ++module_init(at73c213_init);  + - 	/* - 	 * 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])); ++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"); +Index: linux-2.6.22.1/sound/spi/Makefile +=================================================================== +--- linux-2.6.22.1/sound/spi/Makefile	(revision 0) ++++ linux-2.6.22.1/sound/spi/Makefile	(revision 0) +@@ -0,0 +1,5 @@ ++# Makefile for SPI drivers ++ ++snd-at73c213-objs		:= at73c213.o ++ ++obj-$(CONFIG_SND_AT73C213)	+= snd-at73c213.o +Index: linux-2.6.22.1/sound/spi/at73c213.h +=================================================================== +--- linux-2.6.22.1/sound/spi/at73c213.h	(revision 0) ++++ linux-2.6.22.1/sound/spi/at73c213.h	(revision 0) +@@ -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 */ +Index: linux-2.6.22.1/sound/Makefile +=================================================================== +--- linux-2.6.22.1/sound/Makefile	(revision 1) ++++ linux-2.6.22.1/sound/Makefile	(arbetskopia) +@@ -5,7 +5,8 @@ + 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/ - 	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); + # This one must be compilable even if sound is configured out +Index: linux-2.6.22.1/init/do_mounts.c +=================================================================== +--- linux-2.6.22.1/init/do_mounts.c	(revision 1) ++++ linux-2.6.22.1/init/do_mounts.c	(arbetskopia) +@@ -25,6 +25,7 @@ + int root_mountflags = MS_RDONLY | MS_SILENT; + char * __initdata root_device_name; + static char __initdata saved_root_name[64]; ++int __initdata root_wait; +  + dev_t ROOT_DEV; +  +@@ -216,6 +217,14 @@ +  + __setup("root=", root_dev_setup); +  ++static int __init rootwait_setup(char *line) ++{ ++	root_wait = simple_strtol(line,NULL,0); ++	return 1; ++}  + -+	for (i = 0; i < ARRAY_SIZE(ngw_leds); i++) { -+		at32_select_gpio(ngw_leds[i].gpio, -+				AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH); ++__setup("rootwait=", rootwait_setup); ++ + static char * __initdata root_mount_data; + static int __init root_data_setup(char *str) + { +@@ -438,11 +447,24 @@ + 			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);  +	} -+	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 ++	is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR; ++ + 	if (is_floppy && rd_doload && rd_load_disk(0)) + 		ROOT_DEV = Root_RAM0; - 	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 +Index: linux-2.6.22.1/MAINTAINERS +=================================================================== +--- linux-2.6.22.1/MAINTAINERS	(revision 1) ++++ linux-2.6.22.1/MAINTAINERS	(arbetskopia) +@@ -674,6 +674,13 @@ + 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  + -+if BOARD_ATSTK1002 + ATMEL WIRELESS DRIVER + P:	Simon Kelley + M:	simon@thekelleys.org.uk +Index: linux-2.6.22.1/arch/arm/boot/compressed/head-at91rm9200.S +=================================================================== +--- linux-2.6.22.1/arch/arm/boot/compressed/head-at91rm9200.S	(revision 1) ++++ linux-2.6.22.1/arch/arm/boot/compressed/head-at91rm9200.S	(arbetskopia) +@@ -73,6 +73,12 @@ + 		cmp	r7, r3 + 		beq	99f +  ++		@ Promwad Chub : 1181 ++		mov	r3,	#(MACH_TYPE_CHUB & 0xff) ++		orr	r3, r3, #(MACH_TYPE_CHUB & 0xff00) ++		cmp	r7, r3 ++		beq	99f ++ + 		@ Unknown board, use the AT91RM9200DK board + 		@ mov	r7, #MACH_TYPE_AT91RM9200 + 		mov	r7,	#(MACH_TYPE_AT91RM9200DK & 0xff) +Index: linux-2.6.22.1/arch/arm/mach-at91/board-kb9202.c +=================================================================== +--- linux-2.6.22.1/arch/arm/mach-at91/board-kb9202.c	(revision 1) ++++ linux-2.6.22.1/arch/arm/mach-at91/board-kb9202.c	(arbetskopia) +@@ -37,6 +37,8 @@ + #include <asm/arch/board.h> + #include <asm/arch/gpio.h> +  ++#include <asm/arch/at91rm9200_mc.h>  + -+config BOARD_ATSTK1002_CUSTOM -+	bool "Non-default STK-1002 jumper settings" + #include "generic.h" +  +  +@@ -111,6 +113,48 @@ + 	.partition_info	= nand_partitions, + }; +  ++ ++#if defined(CONFIG_FB_S1D15605) ++#warning "Rather pass reset pin via platform_data" ++static struct resource kb9202_lcd_resources[] = { ++	[0] = { ++		.start	= AT91_CHIPSELECT_2, ++		.end	= AT91_CHIPSELECT_2 + 0x200FF, ++		.flags	= IORESOURCE_MEM ++	}, ++	[1] = {	/* reset pin */ ++		.start	= AT91_PIN_PC22, ++		.end	= AT91_PIN_PC22, ++		.flags	= IORESOURCE_MEM ++	}, ++}; ++ ++static struct platform_device kb9202_lcd_device = { ++	.name		= "s1d15605fb", ++	.id		= 0, ++	.num_resources	= ARRAY_SIZE(kb9202_lcd_resources), ++	.resource	= kb9202_lcd_resources, ++}; ++ ++static void __init kb9202_add_device_lcd(void) ++{ ++ 	/* In case the boot loader did not set the chip select mode and timing */ ++	at91_sys_write(AT91_SMC_CSR(2), ++		AT91_SMC_WSEN | AT91_SMC_NWS_(18) | AT91_SMC_TDF_(1) | AT91_SMC_DBW_8 | ++		AT91_SMC_RWSETUP_(1) | AT91_SMC_RWHOLD_(1)); ++ ++	/* Backlight pin = output, off */ ++	at91_set_gpio_output(AT91_PIN_PC23, 0); ++ ++	/* Reset pin = output, in reset */ ++	at91_set_gpio_output(AT91_PIN_PC22, 0); ++ ++	platform_device_register(&kb9202_lcd_device); ++} ++#else ++static void __init kb9202_add_device_lcd(void) {} ++#endif ++ + static void __init kb9202_board_init(void) + { + 	/* Serial */ +@@ -129,6 +173,8 @@ + 	at91_add_device_spi(NULL, 0); + 	/* NAND */ + 	at91_add_device_nand(&kb9202_nand_data); ++	/* LCD	*/ ++	kb9202_add_device_lcd(); + } +  + MACHINE_START(KB9200, "KB920x") +Index: linux-2.6.22.1/arch/arm/mach-at91/Kconfig +=================================================================== +--- linux-2.6.22.1/arch/arm/mach-at91/Kconfig	(revision 1) ++++ linux-2.6.22.1/arch/arm/mach-at91/Kconfig	(arbetskopia) +@@ -97,6 +97,12 @@ + 	help + 	  Select this if you are using Sperry-Sun's KAFA board. +  ++config MACH_CHUB ++	bool "Promwad Chub board" ++	depends on ARCH_AT91RM9200  +	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. ++	  Select this if you are using Promwad's Chub board.  + -+if BOARD_ATSTK1002_CUSTOM + endif +  + # ---------------------------------------------------------- +@@ -121,6 +127,13 @@ + 	  Select this if you are using Atmel's AT91SAM9260-EK or AT91SAM9XE Evaluation Kit + 	  <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3933> +  ++config MACH_CAM60 ++	bool "KwikByte CAM60 board" ++	depends on ARCH_AT91SAM9260 ++	help ++	  Select this if you are using KwikByte's CAM60 board based on the Atmel AT91SAM9260. ++	  <http://www.kwikbyte.com>  + -+config BOARD_ATSTK1002_SW1_CUSTOM -+	bool "SW1: use SSC1 (not SPI0)" + endif +  + # ---------------------------------------------------------- +@@ -184,6 +197,20 @@ + 	  On AT91SAM926x boards both types of NAND flash can be present + 	  (8 and 16 bit data bus width). +  ++config CSB300_WAKE_SW0 ++	bool "CSB300 SW0 irq0 wakeup" ++	depends on MACH_CSB337 && PM  +	help -+	  This also prevents using the external DAC as an audio interface, -+	  and means you can't initialize the on-board QVGA display. ++	  If you have a CSB300 connected to your CSB337, this lets ++	  SW0 serve as a wakeup button.  It uses IRQ0.  + -+config BOARD_ATSTK1002_SW2_CUSTOM -+	bool "SW2: use IRDA or TIMER0 (not UART-A, MMC/SD, and PS2-A)" ++config CSB300_WAKE_SW1 ++	bool "CSB300 SW1 gpio wakeup" ++	depends on MACH_CSB337 && PM  +	help -+	  If you change this you'll want an updated boot loader putting -+	  the console on UART-C not UART-A. ++	  If you have a CSB300 connected to your CSB337, this lets ++	  SW1 serve as a wakeup button.  It uses GPIO.  + -+config BOARD_ATSTK1002_SW3_CUSTOM -+	bool "SW3: use TIMER1 (not SSC0 and GCLK)" + # ---------------------------------------------------------- +  + comment "AT91 Feature Selections" +@@ -194,6 +221,20 @@ + 	  Select this if you need to program one or more of the PCK0..PCK3 + 	  programmable clock outputs. +  ++config ATMEL_TCLIB ++	bool "Timer/Counter Library"  +	help -+	  This also prevents using the external DAC as an audio interface. ++	  Select this if you want a library to allocate the Timer/Counter ++	  blocks found on many Atmel processors.  This facilitates using ++	  these modules despite processor differences.  + -+config BOARD_ATSTK1002_SW4_CUSTOM -+	bool "SW4: use ISI/Camera (not GPIOs, SPI1, and PS2-B)" ++config AT91_SLOW_CLOCK ++	bool "Suspend-to-RAM uses slow clock mode (EXPERIMENTAL)" ++	depends on PM && EXPERIMENTAL  +	help -+	  To use the camera interface you'll need a custom card (on the -+	  PCI-format connector) connect a video sensor. ++	  Select this if you wish to put the CPU into slow clock mode ++	  while in the "Suspend to RAM" state, to save more power.  + -+config BOARD_ATSTK1002_SW5_CUSTOM -+	bool "SW5: use MACB1 (not LCDC)" + endmenu +  + endif +Index: linux-2.6.22.1/arch/arm/mach-at91/at91sam9260.c +=================================================================== +--- linux-2.6.22.1/arch/arm/mach-at91/at91sam9260.c	(revision 1) ++++ linux-2.6.22.1/arch/arm/mach-at91/at91sam9260.c	(arbetskopia) +@@ -269,6 +269,33 @@ +  +  + /* -------------------------------------------------------------------- ++ *  Timer/Counter library initialization ++ * -------------------------------------------------------------------- */ ++#ifdef CONFIG_ATMEL_TCLIB  + -+config BOARD_ATSTK1002_SW6_CUSTOM -+	bool "SW6: more GPIOs (not MACB0)" ++#include "tclib.h"  + -+endif	# custom ++static struct atmel_tcblock at91sam9260_tcblocks[] = { ++	[0] = { ++		.physaddr	= AT91SAM9260_BASE_TCB0, ++		.irq		= { AT91SAM9260_ID_TC0, AT91SAM9260_ID_TC1, AT91SAM9260_ID_TC2 }, ++		.clk		= { &tc0_clk, &tc1_clk, &tc2_clk }, ++	}, ++	[1] = { ++		.physaddr	= AT91SAM9260_BASE_TCB1, ++		.irq		= { AT91SAM9260_ID_TC3, AT91SAM9260_ID_TC4, AT91SAM9260_ID_TC5 }, ++		.clk		= { &tc3_clk, &tc4_clk, &tc5_clk }, ++	}, ++};  + -+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. ++#define at91sam9260_tc_init()	atmel_tc_init(at91sam9260_tcblocks, ARRAY_SIZE(at91sam9260_tcblocks))  + -+config BOARD_ATSTK1002_J2_LED -+	bool -+	default BOARD_ATSTK1002_J2_LED8 || BOARD_ATSTK1002_J2_RGB ++#else ++#define at91sam9260_tc_init()	do {} while(0) ++#endif  + -+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. ++/* -------------------------------------------------------------------- +  *  AT91SAM9260 processor initialization +  * -------------------------------------------------------------------- */ +  +@@ -315,6 +342,9 @@ +  + 	/* Register GPIO subsystem */ + 	at91_gpio_init(at91sam9260_gpio, 3);  + -+config BOARD_ATSTK1002_J2_RGB -+	bool "RGB leds" -+	help -+	  Select this if J2 is jumpered to the RGB leds. ++	/* Initialize the Timer/Counter blocks */ ++	at91sam9260_tc_init(); + } +  + /* -------------------------------------------------------------------- +@@ -327,30 +357,30 @@ + static unsigned int at91sam9260_default_irq_priority[NR_AIC_IRQS] __initdata = { + 	7,	/* Advanced Interrupt Controller */ + 	7,	/* System Peripherals */ +-	0,	/* Parallel IO Controller A */ +-	0,	/* Parallel IO Controller B */ +-	0,	/* Parallel IO Controller C */ ++	1,	/* Parallel IO Controller A */ ++	1,	/* Parallel IO Controller B */ ++	1,	/* Parallel IO Controller C */ + 	0,	/* Analog-to-Digital Converter */ +-	6,	/* USART 0 */ +-	6,	/* USART 1 */ +-	6,	/* USART 2 */ ++	5,	/* USART 0 */ ++	5,	/* USART 1 */ ++	5,	/* USART 2 */ + 	0,	/* Multimedia Card Interface */ +-	4,	/* USB Device Port */ +-	0,	/* Two-Wire Interface */ +-	6,	/* Serial Peripheral Interface 0 */ +-	6,	/* Serial Peripheral Interface 1 */ ++	2,	/* USB Device Port */ ++	6,	/* Two-Wire Interface */ ++	5,	/* Serial Peripheral Interface 0 */ ++	5,	/* Serial Peripheral Interface 1 */ + 	5,	/* Serial Synchronous Controller */ + 	0, + 	0, + 	0,	/* Timer Counter 0 */ + 	0,	/* Timer Counter 1 */ + 	0,	/* Timer Counter 2 */ +-	3,	/* USB Host port */ ++	2,	/* USB Host port */ + 	3,	/* Ethernet */ + 	0,	/* Image Sensor Interface */ +-	6,	/* USART 3 */ +-	6,	/* USART 4 */ +-	6,	/* USART 5 */ ++	5,	/* USART 3 */ ++	5,	/* USART 4 */ ++	5,	/* USART 5 */ + 	0,	/* Timer Counter 3 */ + 	0,	/* Timer Counter 4 */ + 	0,	/* Timer Counter 5 */ +Index: linux-2.6.22.1/arch/arm/mach-at91/at91sam9261.c +=================================================================== +--- linux-2.6.22.1/arch/arm/mach-at91/at91sam9261.c	(revision 1) ++++ linux-2.6.22.1/arch/arm/mach-at91/at91sam9261.c	(arbetskopia) +@@ -247,6 +247,28 @@ +  +  + /* -------------------------------------------------------------------- ++ *  Timer/Counter library initialization ++ * -------------------------------------------------------------------- */ ++#ifdef CONFIG_ATMEL_TCLIB  + -+endchoice ++#include "tclib.h"  + -+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> ++static struct atmel_tcblock at91sam9261_tcblocks[] = { ++	[0] = { ++		.physaddr	= AT91SAM9261_BASE_TCB0, ++		.irq		= { AT91SAM9261_ID_TC0, AT91SAM9261_ID_TC1, AT91SAM9261_ID_TC2 }, ++		.clk		= { &tc0_clk, &tc1_clk, &tc2_clk }, ++	} ++}; ++ ++#define at91sam9261_tc_init()	atmel_tc_init(at91sam9261_tcblocks, ARRAY_SIZE(at91sam9261_tcblocks)) ++ ++#else ++#define at91sam9261_tc_init()	do {} while(0) ++#endif ++ ++ ++/* -------------------------------------------------------------------- +  *  AT91SAM9261 processor initialization +  * -------------------------------------------------------------------- */ +  +@@ -267,6 +289,9 @@ +  + 	/* Register GPIO subsystem */ + 	at91_gpio_init(at91sam9261_gpio, 3); ++ ++	/* Initialize the Timer/Counter blocks */ ++	at91sam9261_tc_init(); + } +  + /* -------------------------------------------------------------------- +@@ -279,25 +304,25 @@ + static unsigned int at91sam9261_default_irq_priority[NR_AIC_IRQS] __initdata = { + 	7,	/* Advanced Interrupt Controller */ + 	7,	/* System Peripherals */ +-	0,	/* Parallel IO Controller A */ +-	0,	/* Parallel IO Controller B */ +-	0,	/* Parallel IO Controller C */ ++	1,	/* Parallel IO Controller A */ ++	1,	/* Parallel IO Controller B */ ++	1,	/* Parallel IO Controller C */ + 	0, +-	6,	/* USART 0 */ +-	6,	/* USART 1 */ +-	6,	/* USART 2 */ ++	5,	/* USART 0 */ ++	5,	/* USART 1 */ ++	5,	/* USART 2 */ + 	0,	/* Multimedia Card Interface */ +-	4,	/* USB Device Port */ +-	0,	/* Two-Wire Interface */ +-	6,	/* Serial Peripheral Interface 0 */ +-	6,	/* Serial Peripheral Interface 1 */ +-	5,	/* Serial Synchronous Controller 0 */ +-	5,	/* Serial Synchronous Controller 1 */ +-	5,	/* Serial Synchronous Controller 2 */ ++	2,	/* USB Device Port */ ++	6,	/* Two-Wire Interface */ ++	5,	/* Serial Peripheral Interface 0 */ ++	5,	/* Serial Peripheral Interface 1 */ ++	4,	/* Serial Synchronous Controller 0 */ ++	4,	/* Serial Synchronous Controller 1 */ ++	4,	/* Serial Synchronous Controller 2 */ + 	0,	/* Timer Counter 0 */ + 	0,	/* Timer Counter 1 */ + 	0,	/* Timer Counter 2 */ +-	3,	/* USB Host port */ ++	2,	/* USB Host port */ + 	3,	/* LCD Controller */ + 	0, + 	0, +Index: linux-2.6.22.1/arch/arm/mach-at91/at91sam9260_devices.c +=================================================================== +--- linux-2.6.22.1/arch/arm/mach-at91/at91sam9260_devices.c	(revision 1) ++++ linux-2.6.22.1/arch/arm/mach-at91/at91sam9260_devices.c	(arbetskopia) +@@ -524,6 +524,32 @@ + #endif +  +  ++#if defined(CONFIG_NEW_LEDS) ++ ++static struct platform_device at91_leds = { ++	.name		= "at91_leds", ++	.id		= -1, ++}; ++ ++void __init at91_gpio_leds(struct at91_gpio_led *leds, int nr) ++{ ++	if (!nr) ++		return; ++ ++	at91_leds.dev.platform_data = leds; ++ ++	for ( ; nr; nr--, leds++) { ++		leds->index = nr;	/* first record stores number of leds */ ++		at91_set_gpio_output(leds->gpio, (leds->flags & 1) == 0); ++	} ++ ++	platform_device_register(&at91_leds); ++} ++#else ++void __init at91_gpio_leds(struct at91_gpio_led *leds, int nr) {} ++#endif ++ ++ + /* -------------------------------------------------------------------- +  *  UART +  * -------------------------------------------------------------------- */ +Index: linux-2.6.22.1/arch/arm/mach-at91/at91sam9261_devices.c +=================================================================== +--- linux-2.6.22.1/arch/arm/mach-at91/at91sam9261_devices.c	(revision 1) ++++ linux-2.6.22.1/arch/arm/mach-at91/at91sam9261_devices.c	(arbetskopia) +@@ -14,7 +14,10 @@ + #include <asm/mach/map.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 <linux/fb.h> - #include <video/atmel_lcdc.h> ++#include <video/atmel_lcdc.h> ++ + #include <asm/arch/board.h> + #include <asm/arch/gpio.h> + #include <asm/arch/at91sam9261.h> +@@ -522,6 +525,32 @@ + #endif -@@ -27,16 +29,47 @@ - #include "atstk1000.h" ++#if defined(CONFIG_NEW_LEDS) ++ ++static struct platform_device at91_leds = { ++	.name		= "at91_leds", ++	.id		= -1, ++}; ++ ++void __init at91_gpio_leds(struct at91_gpio_led *leds, int nr) ++{ ++	if (!nr) ++		return; ++ ++	at91_leds.dev.platform_data = leds; ++ ++	for ( ; nr; nr--, leds++) { ++		leds->index = nr;	/* first record stores number of leds */ ++		at91_set_gpio_output(leds->gpio, (leds->flags & 1) == 0); ++	} ++ ++	platform_device_register(&at91_leds); ++} ++#else ++void __init at91_gpio_leds(struct at91_gpio_led *leds, int nr) {} ++#endif ++ ++ + /* -------------------------------------------------------------------- +  *  UART +  * -------------------------------------------------------------------- */ +Index: linux-2.6.22.1/arch/arm/mach-at91/at91sam9263.c +=================================================================== +--- linux-2.6.22.1/arch/arm/mach-at91/at91sam9263.c	(revision 1) ++++ linux-2.6.22.1/arch/arm/mach-at91/at91sam9263.c	(arbetskopia) +@@ -273,6 +273,28 @@ --#define	SW2_DEFAULT		/* MMCI and UART_A available */ - struct eth_addr { - 	u8 addr[6]; + /* -------------------------------------------------------------------- ++ *  Timer/Counter library initialization ++ * -------------------------------------------------------------------- */ ++#ifdef CONFIG_ATMEL_TCLIB ++ ++#include "tclib.h" ++ ++static struct atmel_tcblock at91sam9263_tcblocks[] = { ++	[0] = { ++		.physaddr	= AT91SAM9263_BASE_TCB0, ++		.irq		= { AT91SAM9263_ID_TCB, AT91SAM9263_ID_TCB, AT91SAM9263_ID_TCB }, ++		.clk		= { &tcb_clk, &tcb_clk, &tcb_clk }, ++	} ++}; ++ ++#define at91sam9263_tc_init()	atmel_tc_init(at91sam9263_tcblocks, ARRAY_SIZE(at91sam9263_tcblocks)) ++ ++#else ++#define at91sam9263_tc_init()	do {} while(0) ++#endif ++ ++ ++/* -------------------------------------------------------------------- +  *  AT91SAM9263 processor initialization +  * -------------------------------------------------------------------- */ +  +@@ -292,6 +314,9 @@ +  + 	/* Register GPIO subsystem */ + 	at91_gpio_init(at91sam9263_gpio, 5); ++ ++	/* Initialize the Timer/Counter blocks */ ++	at91sam9263_tc_init(); + } +  + /* -------------------------------------------------------------------- +@@ -304,34 +329,34 @@ + static unsigned int at91sam9263_default_irq_priority[NR_AIC_IRQS] __initdata = { + 	7,	/* Advanced Interrupt Controller (FIQ) */ + 	7,	/* System Peripherals */ +-	0,	/* Parallel IO Controller A */ +-	0,	/* Parallel IO Controller B */ +-	0,	/* Parallel IO Controller C, D and E */ ++	1,	/* Parallel IO Controller A */ ++	1,	/* Parallel IO Controller B */ ++	1,	/* Parallel IO Controller C, D and E */ + 	0, + 	0, +-	6,	/* USART 0 */ +-	6,	/* USART 1 */ +-	6,	/* USART 2 */ ++	5,	/* USART 0 */ ++	5,	/* USART 1 */ ++	5,	/* USART 2 */ + 	0,	/* Multimedia Card Interface 0 */ + 	0,	/* Multimedia Card Interface 1 */ +-	4,	/* CAN */ +-	0,	/* Two-Wire Interface */ +-	6,	/* Serial Peripheral Interface 0 */ +-	6,	/* Serial Peripheral Interface 1 */ +-	5,	/* Serial Synchronous Controller 0 */ +-	5,	/* Serial Synchronous Controller 1 */ +-	6,	/* AC97 Controller */ ++	3,	/* CAN */ ++	6,	/* Two-Wire Interface */ ++	5,	/* Serial Peripheral Interface 0 */ ++	5,	/* Serial Peripheral Interface 1 */ ++	4,	/* Serial Synchronous Controller 0 */ ++	4,	/* Serial Synchronous Controller 1 */ ++	5,	/* AC97 Controller */ + 	0,	/* Timer Counter 0, 1 and 2 */ + 	0,	/* Pulse Width Modulation Controller */ + 	3,	/* Ethernet */ + 	0, + 	0,	/* 2D Graphic Engine */ +-	3,	/* USB Device Port */ ++	2,	/* USB Device Port */ + 	0,	/* Image Sensor Interface */ + 	3,	/* LDC Controller */ + 	0,	/* DMA Controller */ + 	0, +-	3,	/* USB Host port */ ++	2,	/* USB Host port */ + 	0,	/* Advanced Interrupt Controller (IRQ0) */ + 	0,	/* Advanced Interrupt Controller (IRQ1) */   }; +Index: linux-2.6.22.1/arch/arm/mach-at91/at91sam9263_devices.c +=================================================================== +--- linux-2.6.22.1/arch/arm/mach-at91/at91sam9263_devices.c	(revision 1) ++++ linux-2.6.22.1/arch/arm/mach-at91/at91sam9263_devices.c	(arbetskopia) +@@ -13,7 +13,10 @@ + #include <asm/mach/map.h> - 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), + #include <linux/platform_device.h> ++#include <linux/fb.h> +  ++#include <video/atmel_lcdc.h> ++ + #include <asm/arch/board.h> + #include <asm/arch/gpio.h> + #include <asm/arch/at91sam9263.h> +@@ -625,6 +628,56 @@ +  +  + /* -------------------------------------------------------------------- ++ *  Image Sensor Interface ++ * -------------------------------------------------------------------- */ ++ ++#if defined(CONFIG_VIDEO_AT91_ISI) || defined(CONFIG_VIDEO_AT91_ISI_MODULE) ++ ++struct resource isi_resources[] = { ++	[0] = { ++		.start	= AT91SAM9263_BASE_ISI, ++		.end	= AT91SAM9263_BASE_ISI + SZ_16K - 1, ++		.flags	= IORESOURCE_MEM,  +	}, -+	{ -+		.phy_mask	= ~(1U << 17), ++	[1] = { ++		.start	= AT91SAM9263_ID_ISI, ++		.end	= AT91SAM9263_ID_ISI, ++		.flags	= IORESOURCE_IRQ,  +	},  +};  + -+#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", ++static struct platform_device at91sam9263_isi_device = { ++	.name		= "at91_isi", ++	.id		= -1, ++	.resource	= isi_resources, ++	.num_resources	= ARRAY_SIZE(isi_resources),  +}; ++ ++void __init at91_add_device_isi(void) ++{ ++	at91_set_A_periph(AT91_PIN_PE0, 0);	/* ISI_D0 */ ++	at91_set_A_periph(AT91_PIN_PE1, 0);	/* ISI_D1 */ ++	at91_set_A_periph(AT91_PIN_PE2, 0);	/* ISI_D2 */ ++	at91_set_A_periph(AT91_PIN_PE3, 0);	/* ISI_D3 */ ++	at91_set_A_periph(AT91_PIN_PE4, 0);	/* ISI_D4 */ ++	at91_set_A_periph(AT91_PIN_PE5, 0);	/* ISI_D5 */ ++	at91_set_A_periph(AT91_PIN_PE6, 0);	/* ISI_D6 */ ++	at91_set_A_periph(AT91_PIN_PE7, 0);	/* ISI_D7 */ ++	at91_set_A_periph(AT91_PIN_PE8, 0);	/* ISI_PCK */ ++	at91_set_A_periph(AT91_PIN_PE9, 0);	/* ISI_HSYNC */ ++	at91_set_A_periph(AT91_PIN_PE10, 0);	/* ISI_VSYNC */ ++	at91_set_B_periph(AT91_PIN_PE11, 0);	/* ISI_MCK (PCK3) */ ++	at91_set_B_periph(AT91_PIN_PE12, 0);	/* ISI_PD8 */ ++	at91_set_B_periph(AT91_PIN_PE13, 0);	/* ISI_PD9 */ ++	at91_set_B_periph(AT91_PIN_PE14, 0);	/* ISI_PD10 */ ++	at91_set_B_periph(AT91_PIN_PE15, 0);	/* ISI_PD11 */ ++} ++#else ++void __init at91_add_device_isi(void) {}  +#endif -+#endif ++ ++ ++/* -------------------------------------------------------------------- +  *  LCD Controller +  * -------------------------------------------------------------------- */ -+#ifndef CONFIG_BOARD_ATSTK1002_SW1_CUSTOM - static struct spi_board_info spi0_board_info[] __initdata = { -+#ifndef CONFIG_BOARD_ATSTK1002_SW3_CUSTOM +@@ -715,6 +768,32 @@ + #endif +  +  ++#if defined(CONFIG_NEW_LEDS) ++ ++static struct platform_device at91_leds = { ++	.name		= "at91_leds", ++	.id		= -1, ++}; ++ ++void __init at91_gpio_leds(struct at91_gpio_led *leds, int nr) ++{ ++	if (!nr) ++		return; ++ ++	at91_leds.dev.platform_data = leds; ++ ++	for ( ; nr; nr--, leds++) { ++		leds->index = nr;	/* first record stores number of leds */ ++		at91_set_gpio_output(leds->gpio, (leds->flags & 1) == 0); ++	} ++ ++	platform_device_register(&at91_leds); ++} ++#else ++void __init at91_gpio_leds(struct at91_gpio_led *leds, int nr) {} ++#endif ++ ++ + /* -------------------------------------------------------------------- +  *  UART +  * -------------------------------------------------------------------- */ +Index: linux-2.6.22.1/arch/arm/mach-at91/board-chub.c +=================================================================== +--- linux-2.6.22.1/arch/arm/mach-at91/board-chub.c	(revision 0) ++++ linux-2.6.22.1/arch/arm/mach-at91/board-chub.c	(revision 0) +@@ -0,0 +1,132 @@ ++/* ++ * linux/arch/arm/mach-at91/board-chub.c ++ * ++ *  Copyright (C) 2005 SAN People, adapted for Promwad Chub board ++ *  by Kuten Ivan ++ * ++ * 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 ++ */ ++ ++#include <linux/types.h> ++#include <linux/init.h> ++#include <linux/mm.h> ++#include <linux/module.h> ++#include <linux/platform_device.h> ++ ++#include <asm/hardware.h> ++#include <asm/setup.h> ++#include <asm/mach-types.h> ++#include <asm/irq.h> ++ ++#include <asm/mach/arch.h> ++#include <asm/mach/map.h> ++#include <asm/mach/irq.h> ++ ++#include <asm/arch/board.h> ++#include <asm/arch/gpio.h> ++ ++#include "generic.h" ++ ++/* ++ * Serial port configuration. ++ *    0 .. 3 = USART0 .. USART3 ++ *    4      = DBGU ++ */ ++static struct at91_uart_config __initdata chub_uart_config = { ++	.console_tty	= 0,				/* ttyS0 */ ++	.nr_tty		= 5, ++	.tty_map	= { 4, 0, 1, 2, 3 }		/* ttyS0, ..., ttyS4 */ ++}; ++ ++static void __init chub_init_irq(void) ++{ ++	at91rm9200_init_interrupts(NULL); ++} ++ ++static void __init chub_map_io(void) ++{ ++	/* Initialize clocks: 18.432 MHz crystal */ ++	at91rm9200_initialize(18432000, AT91RM9200_PQFP); ++ ++	/* Setup the serial ports and console */ ++	at91_init_serial(&chub_uart_config); ++} ++ ++static struct at91_eth_data __initdata chub_eth_data = { ++	.phy_irq_pin	= AT91_PIN_PB29, ++	.is_rmii	= 0, ++}; ++ ++static struct mtd_partition __initdata chub_nand_partition[] = {  +	{ -+		/* AT73C213 */ -+		.modalias	= "at73c213", -+		.max_speed_hz	= 200000, ++		.name	= "NAND Partition 1", ++		.offset = 0, ++		.size	= MTDPART_SIZ_FULL, ++	}, ++}; ++ ++static struct mtd_partition * __init nand_partitions(int size, int *num_partitions) ++{ ++	*num_partitions = ARRAY_SIZE(chub_nand_partition); ++	return chub_nand_partition; ++} ++ ++static struct at91_nand_data __initdata chub_nand_data = { ++	.ale		= 22, ++	.cle		= 21, ++	.enable_pin	= AT91_PIN_PA27, ++	.partition_info	= nand_partitions, ++}; ++ ++static struct spi_board_info chub_spi_devices[] = { ++	{	/* DataFlash chip */ ++		.modalias	= "mtd_dataflash",  +		.chip_select	= 0, -+		.mode		= SPI_MODE_1, -+		.platform_data	= &at73c213_data, ++		.max_speed_hz	= 15 * 1000 * 1000,  +	}, -+#endif - 	{ - 		/* QVGA display */ - 		.modalias	= "ltv350qv", -@@ -45,6 +78,18 @@ static struct spi_board_info spi0_board_info[] __initdata = { - 		.mode		= SPI_MODE_3, ++}; ++ ++static void __init chub_board_init(void) ++{ ++	/* Serial */ ++	at91_add_device_serial(); ++	/* I2C */ ++	at91_add_device_i2c(); ++	/* Ethernet */ ++	at91_add_device_eth(&chub_eth_data); ++	/* SPI */ ++	at91_add_device_spi(chub_spi_devices, ARRAY_SIZE(chub_spi_devices)); ++	/* NAND Flash */ ++	at91_add_device_nand(&chub_nand_data); ++	/* Disable write protect for NAND */ ++	at91_set_gpio_output(AT91_PIN_PB7, 1); ++	/* Power enable for 3x RS-232 and 1x RS-485 */ ++	at91_set_gpio_output(AT91_PIN_PB9, 1); ++	/* Disable write protect for FRAM */ ++	at91_set_gpio_output(AT91_PIN_PA21, 1); ++	/* Disable write protect for Dataflash */ ++	at91_set_gpio_output(AT91_PIN_PA19, 1); ++} ++ ++MACHINE_START(CHUB, "Promwad Chub") ++	/* Maintainer: Ivan Kuten AT Promwad DOT com */ ++	.phys_io	= AT91_BASE_SYS, ++	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc, ++	.boot_params	= AT91_SDRAM_BASE + 0x100, ++	.timer		= &at91rm9200_timer, ++	.map_io		= chub_map_io, ++	.init_irq	= chub_init_irq, ++	.init_machine	= chub_board_init, ++MACHINE_END +Index: linux-2.6.22.1/arch/arm/mach-at91/board-sam9261ek.c +=================================================================== +--- linux-2.6.22.1/arch/arm/mach-at91/board-sam9261ek.c	(revision 1) ++++ linux-2.6.22.1/arch/arm/mach-at91/board-sam9261ek.c	(arbetskopia) +@@ -27,7 +27,10 @@ + #include <linux/spi/spi.h> + #include <linux/spi/ads7846.h> + #include <linux/dm9000.h> ++#include <linux/fb.h> +  ++#include <video/atmel_lcdc.h> ++ + #include <asm/hardware.h> + #include <asm/setup.h> + #include <asm/mach-types.h> +@@ -251,6 +254,7 @@ + 		.bus_num	= 0, + 		.platform_data	= &ads_info, + 		.irq		= AT91SAM9261_ID_IRQ0, ++		.controller_data = AT91_PIN_PA28,	/* CS pin */   	}, + #endif + #if defined(CONFIG_MTD_AT91_DATAFLASH_CARD) +@@ -271,6 +275,65 @@   }; -+#endif +  +  ++/* ++ * LCD Controller ++ */ ++#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE) ++static struct fb_videomode at91_tft_vga_modes[] = { ++	{ ++	        .name           = "TX09D50VM1CCA @ 60", ++		.refresh	= 60, ++		.xres		= 240,		.yres		= 320, ++		.pixclock	= KHZ2PICOS(4965),  + -+#ifdef CONFIG_BOARD_ATSTK1002_SPI1 -+static struct spi_board_info spi1_board_info[] __initdata = { { -+	/* patch in custom entries here */ -+} }; -+#endif ++		.left_margin	= 1,		.right_margin	= 33, ++		.upper_margin	= 1,		.lower_margin	= 0, ++		.hsync_len	= 5,		.vsync_len	= 1,  + -+static struct mci_platform_data __initdata mci0_data = { -+	.detect_pin	= GPIO_PIN_NONE, -+	.wp_pin		= GPIO_PIN_NONE, ++		.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, ++		.vmode		= FB_VMODE_NONINTERLACED, ++	},  +}; -  - /* -  * 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); ++ ++static struct fb_monspecs at91fb_default_monspecs = { ++	.manufacturer	= "HIT", ++	.monitor        = "TX09D50VM1CCA", ++ ++	.modedb		= at91_tft_vga_modes, ++	.modedb_len	= ARRAY_SIZE(at91_tft_vga_modes), ++	.hfmin		= 15000, ++	.hfmax		= 64000, ++	.vfmin		= 50, ++	.vfmax		= 150, ++}; ++ ++#define AT91SAM9261_DEFAULT_LCDCON2 	(ATMEL_LCDC_MEMOR_LITTLE \ ++					| ATMEL_LCDC_DISTYPE_TFT    \ ++					| ATMEL_LCDC_CLKMOD_ALWAYSACTIVE) ++ ++static void at91_lcdc_power_control(int on) ++{ ++	if (on) ++		at91_set_gpio_value(AT91_PIN_PA12, 0);	/* power up */ ++	else ++		at91_set_gpio_value(AT91_PIN_PA12, 1);	/* power down */ ++} ++ ++/* Driver datas */ ++static struct atmel_lcdfb_info __initdata ek_lcdc_data = { ++	.default_bpp			= 16, ++	.default_dmacon			= ATMEL_LCDC_DMAEN, ++	.default_lcdcon2		= AT91SAM9261_DEFAULT_LCDCON2, ++	.default_monspecs		= &at91fb_default_monspecs, ++	.atmel_lcdfb_power_control	= at91_lcdc_power_control, ++	.guard_time			= 1, ++}; ++ ++#else ++static struct atmel_lcdfb_info __initdata ek_lcdc_data; ++#endif ++ ++ + static void __init ek_board_init(void) + { + 	/* Serial */ +@@ -296,6 +359,8 @@ + 	/* MMC */ + 	at91_add_device_mmc(0, &ek_mmc_data); + #endif ++	/* LCD Controller */ ++	at91_add_device_lcdc(&ek_lcdc_data);   } --void __init setup_board(void) -+#ifdef CONFIG_BOARD_ATSTK1002_J2_LED + MACHINE_START(AT91SAM9261EK, "Atmel AT91SAM9261-EK") +Index: linux-2.6.22.1/arch/arm/mach-at91/board-sam9263ek.c +=================================================================== +--- linux-2.6.22.1/arch/arm/mach-at91/board-sam9263ek.c	(revision 1) ++++ linux-2.6.22.1/arch/arm/mach-at91/board-sam9263ek.c	(arbetskopia) +@@ -26,7 +26,10 @@ + #include <linux/platform_device.h> + #include <linux/spi/spi.h> + #include <linux/spi/ads7846.h> ++#include <linux/fb.h> +  ++#include <video/atmel_lcdc.h>  + -+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), }, + #include <asm/hardware.h> + #include <asm/setup.h> + #include <asm/mach-types.h> +@@ -202,6 +205,65 @@ +  +  + /* ++ * LCD Controller ++ */ ++#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE) ++static struct fb_videomode at91_tft_vga_modes[] = { ++	{ ++	        .name           = "TX09D50VM1CCA @ 60", ++		.refresh	= 60, ++		.xres		= 240,		.yres		= 320, ++		.pixclock	= KHZ2PICOS(4965),  + -+	{ .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 */ ++		.left_margin	= 1,		.right_margin	= 33, ++		.upper_margin	= 1,		.lower_margin	= 0, ++		.hsync_len	= 5,		.vsync_len	= 1, ++ ++		.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, ++		.vmode		= FB_VMODE_NONINTERLACED, ++	}, ++}; ++ ++static struct fb_monspecs at91fb_default_monspecs = { ++	.manufacturer	= "HIT", ++	.monitor        = "TX09D70VM1CCA", ++ ++	.modedb		= at91_tft_vga_modes, ++	.modedb_len	= ARRAY_SIZE(at91_tft_vga_modes), ++	.hfmin		= 15000, ++	.hfmax		= 64000, ++	.vfmin		= 50, ++	.vfmax		= 150, ++}; ++ ++#define AT91SAM9263_DEFAULT_LCDCON2 	(ATMEL_LCDC_MEMOR_LITTLE \ ++					| ATMEL_LCDC_DISTYPE_TFT    \ ++					| ATMEL_LCDC_CLKMOD_ALWAYSACTIVE) ++ ++static void at91_lcdc_power_control(int on) ++{ ++	if (on) ++		at91_set_gpio_value(AT91_PIN_PD12, 0);	/* power up */ ++	else ++		at91_set_gpio_value(AT91_PIN_PD12, 1);	/* power down */ ++} ++ ++/* Driver datas */ ++static struct atmel_lcdfb_info __initdata ek_lcdc_data = { ++	.default_bpp			= 16, ++	.default_dmacon			= ATMEL_LCDC_DMAEN, ++	.default_lcdcon2		= AT91SAM9263_DEFAULT_LCDCON2, ++	.default_monspecs		= &at91fb_default_monspecs, ++	.atmel_lcdfb_power_control	= at91_lcdc_power_control, ++	.guard_time			= 1, ++}; ++ ++#else ++static struct atmel_lcdfb_info __initdata ek_lcdc_data;  +#endif ++ ++ ++/* +  * AC97 +  */ + static struct atmel_ac97_data ek_ac97_data = { +@@ -230,6 +292,8 @@ + 	at91_add_device_nand(&ek_nand_data); + 	/* I2C */ + 	at91_add_device_i2c(); ++	/* LCD Controller */ ++	at91_add_device_lcdc(&ek_lcdc_data); + 	/* AC97 */ + 	at91_add_device_ac97(&ek_ac97_data); + } +Index: linux-2.6.22.1/arch/arm/mach-at91/generic.h +=================================================================== +--- linux-2.6.22.1/arch/arm/mach-at91/generic.h	(revision 1) ++++ linux-2.6.22.1/arch/arm/mach-at91/generic.h	(arbetskopia) +@@ -36,6 +36,7 @@ +  /* Power Management */ + extern void at91_irq_suspend(void); + extern void at91_irq_resume(void); ++extern int at91_suspend_entering_slow_clock(void); +  +  /* GPIO */ + #define AT91RM9200_PQFP		3	/* AT91RM9200 PQFP package has 3 banks */ +Index: linux-2.6.22.1/arch/arm/mach-at91/board-ek.c +=================================================================== +--- linux-2.6.22.1/arch/arm/mach-at91/board-ek.c	(revision 1) ++++ linux-2.6.22.1/arch/arm/mach-at91/board-ek.c	(arbetskopia) +@@ -73,6 +73,187 @@ + 	at91rm9200_init_interrupts(NULL); + } +  ++#if defined(CONFIG_FB_S1D13XXX) || defined(CONFIG_FB_S1D13XXX_MODULE) ++#include <video/s1d13xxxfb.h> ++#include <asm/arch/ics1523.h> ++ ++/* EPSON S1D13806 FB */ ++#define AT91_FB_REG_BASE	0x40000000L ++#define	AT91_FB_REG_SIZE	0x200 ++#define AT91_FB_VMEM_BASE	0x40200000L ++#define AT91_FB_VMEM_SIZE	0x140000L ++ ++static void __init ek_init_video(void) ++{ ++	/* NWAIT Signal */ ++	at91_set_A_periph(AT91_PIN_PC6, 0); ++ ++	/* Initialization of the Static Memory Controller for Chip Select 3 */ ++	at91_sys_write(AT91_SMC_CSR(3), AT91_SMC_DBW_16			/* 16 bit */ ++				| AT91_SMC_WSEN | AT91_SMC_NWS_(5)	/* wait states */ ++				| AT91_SMC_TDF_(1)			/* float time */ ++	); ++ ++	at91_ics1523_init(); ++} ++ ++/* CRT:    (active)   640x480 60Hz (PCLK=CLKI=25.175MHz) ++   Memory: Embedded SDRAM (MCLK=CLKI3=50.000MHz) (BUSCLK=60.000MHz) */ ++static const struct s1d13xxxfb_regval ek_s1dfb_initregs[] = { ++	{S1DREG_MISC,			0x00},	/* Enable Memory/Register select bit */ ++	{S1DREG_COM_DISP_MODE,		0x00},	/* disable display output */ ++	{S1DREG_GPIO_CNF0,		0xFF},	// 0x00 ++	{S1DREG_GPIO_CNF1,		0x1F},	// 0x08 ++	{S1DREG_GPIO_CTL0,		0x00}, ++	{S1DREG_GPIO_CTL1,		0x00}, ++	{S1DREG_CLK_CNF,		0x01},	/* no divide, MCLK source is CLKI3 0x02*/ ++	{S1DREG_LCD_CLK_CNF,		0x00}, ++	{S1DREG_CRT_CLK_CNF,		0x00}, ++	{S1DREG_MPLUG_CLK_CNF,		0x00}, ++	{S1DREG_CPU2MEM_WST_SEL,	0x01},	/* 2*period(MCLK) - 4ns > period(BCLK) */ ++	{S1DREG_SDRAM_REF_RATE,		0x03},	/* 32768 <= MCLK <= 50000 (MHz) */ ++	{S1DREG_SDRAM_TC0,		0x00},	/* MCLK source freq (MHz): */ ++	{S1DREG_SDRAM_TC1,		0x01},	/* 42 <= MCLK <= 50 */ ++	{S1DREG_MEM_CNF,		0x80},	/* SDRAM Initialization - needed before mem access */ ++	{S1DREG_PANEL_TYPE,		0x25},	/* std TFT 16bit, 8bit SCP format 2, single passive LCD */ ++	{S1DREG_MOD_RATE,		0x00},	/* toggle every FPFRAME */ ++	{S1DREG_LCD_DISP_HWIDTH,	0x4F},	/* 680 pix */ ++	{S1DREG_LCD_NDISP_HPER,		0x12},	/* 152 pix */ ++	{S1DREG_TFT_FPLINE_START,	0x01},	/* 13 pix */ ++	{S1DREG_TFT_FPLINE_PWIDTH,	0x0B},	/* 96 pix */ ++	{S1DREG_LCD_DISP_VHEIGHT0,	0xDF}, ++	{S1DREG_LCD_DISP_VHEIGHT1,	0x01},	/* 480 lines */ ++	{S1DREG_LCD_NDISP_VPER,		0x2C},	/* 44 lines */ ++	{S1DREG_TFT_FPFRAME_START,	0x0A},	/* 10 lines */ ++	{S1DREG_TFT_FPFRAME_PWIDTH,	0x01},	/* 2 lines */ ++	{S1DREG_LCD_DISP_MODE,		0x05},  /* 16 bpp */ ++	{S1DREG_LCD_MISC,		0x00},	/* dithering enabled, dual panel buffer enabled */ ++	{S1DREG_LCD_DISP_START0,	0x00}, ++	{S1DREG_LCD_DISP_START1,	0xC8}, ++	{S1DREG_LCD_DISP_START2,	0x00}, ++	{S1DREG_LCD_MEM_OFF0,		0x80}, ++	{S1DREG_LCD_MEM_OFF1,		0x02}, ++	{S1DREG_LCD_PIX_PAN,		0x00}, ++	{S1DREG_LCD_DISP_FIFO_HTC,	0x3B}, ++	{S1DREG_LCD_DISP_FIFO_LTC,	0x3C}, ++	{S1DREG_CRT_DISP_HWIDTH,	0x4F},	/* 680 pix */ ++	{S1DREG_CRT_NDISP_HPER,		0x13},	/* 160 pix */ ++	{S1DREG_CRT_HRTC_START,		0x01},	/* 13 pix */ ++	{S1DREG_CRT_HRTC_PWIDTH,	0x0B},	/* 96 pix */ ++	{S1DREG_CRT_DISP_VHEIGHT0,	0xDF}, ++	{S1DREG_CRT_DISP_VHEIGHT1,	0x01},	/* 480 lines */ ++	{S1DREG_CRT_NDISP_VPER,		0x2B},	/* 44 lines */ ++	{S1DREG_CRT_VRTC_START,		0x09},	/* 10 lines */ ++	{S1DREG_CRT_VRTC_PWIDTH,	0x01},	/* 2 lines */ ++	{S1DREG_TV_OUT_CTL,		0x10}, ++	{0x005E,			0x9F}, ++	{0x005F,			0x00}, ++	{S1DREG_CRT_DISP_MODE,		0x05},	/* 16 bpp */ ++	{S1DREG_CRT_DISP_START0,	0x00}, ++	{S1DREG_CRT_DISP_START1,	0x00}, ++	{S1DREG_CRT_DISP_START2,	0x00}, ++	{S1DREG_CRT_MEM_OFF0,		0x80}, ++	{S1DREG_CRT_MEM_OFF1,		0x02}, ++	{S1DREG_CRT_PIX_PAN,		0x00}, ++	{S1DREG_CRT_DISP_FIFO_HTC,	0x3B}, ++	{S1DREG_CRT_DISP_FIFO_LTC,	0x3C}, ++	{S1DREG_LCD_CUR_CTL,		0x00},	/* inactive */ ++	{S1DREG_LCD_CUR_START,		0x01}, ++	{S1DREG_LCD_CUR_XPOS0,		0x00}, ++	{S1DREG_LCD_CUR_XPOS1,		0x00}, ++	{S1DREG_LCD_CUR_YPOS0,		0x00}, ++	{S1DREG_LCD_CUR_YPOS1,		0x00}, ++	{S1DREG_LCD_CUR_BCTL0,		0x00}, ++	{S1DREG_LCD_CUR_GCTL0,		0x00}, ++	{S1DREG_LCD_CUR_RCTL0,		0x00}, ++	{S1DREG_LCD_CUR_BCTL1,		0x1F}, ++	{S1DREG_LCD_CUR_GCTL1,		0x3F}, ++	{S1DREG_LCD_CUR_RCTL1,		0x1F}, ++	{S1DREG_LCD_CUR_FIFO_HTC,	0x00}, ++	{S1DREG_CRT_CUR_CTL,		0x00},	/* inactive */ ++	{S1DREG_CRT_CUR_START,		0x01}, ++	{S1DREG_CRT_CUR_XPOS0,		0x00}, ++	{S1DREG_CRT_CUR_XPOS1,		0x00}, ++	{S1DREG_CRT_CUR_YPOS0,		0x00}, ++	{S1DREG_CRT_CUR_YPOS1,		0x00}, ++	{S1DREG_CRT_CUR_BCTL0,		0x00}, ++	{S1DREG_CRT_CUR_GCTL0,		0x00}, ++	{S1DREG_CRT_CUR_RCTL0,		0x00}, ++	{S1DREG_CRT_CUR_BCTL1,		0x1F}, ++	{S1DREG_CRT_CUR_GCTL1,		0x3F}, ++	{S1DREG_CRT_CUR_RCTL1,		0x1F}, ++	{S1DREG_CRT_CUR_FIFO_HTC,	0x00}, ++	{S1DREG_BBLT_CTL0,		0x00}, ++	{S1DREG_BBLT_CTL0,		0x00}, ++	{S1DREG_BBLT_CC_EXP,		0x00}, ++	{S1DREG_BBLT_OP,		0x00}, ++	{S1DREG_BBLT_SRC_START0,	0x00}, ++	{S1DREG_BBLT_SRC_START1,	0x00}, ++	{S1DREG_BBLT_SRC_START2,	0x00}, ++	{S1DREG_BBLT_DST_START0,	0x00}, ++	{S1DREG_BBLT_DST_START1,	0x00}, ++	{S1DREG_BBLT_DST_START2,	0x00}, ++	{S1DREG_BBLT_MEM_OFF0,		0x00}, ++	{S1DREG_BBLT_MEM_OFF1,		0x00}, ++	{S1DREG_BBLT_WIDTH0,		0x00}, ++	{S1DREG_BBLT_WIDTH1,		0x00}, ++	{S1DREG_BBLT_HEIGHT0,		0x00}, ++	{S1DREG_BBLT_HEIGHT1,		0x00}, ++	{S1DREG_BBLT_BGC0,		0x00}, ++	{S1DREG_BBLT_BGC1,		0x00}, ++	{S1DREG_BBLT_FGC0,		0x00}, ++	{S1DREG_BBLT_FGC1,		0x00}, ++	{S1DREG_LKUP_MODE,		0x00},	/* LCD LUT r | LCD and CRT/TV LUT w */ ++	{S1DREG_LKUP_ADDR,		0x00}, ++	{S1DREG_PS_CNF,			0x10},	/* Power Save disable */ ++	{S1DREG_PS_STATUS,		0x02},	/* LCD Panel down, mem up */ ++	{S1DREG_CPU2MEM_WDOGT,		0x00}, ++	{S1DREG_COM_DISP_MODE,		0x02},	/* enable CRT display output */  +};  + -+static struct gpio_led_platform_data stk_j2_led_data = { -+	.num_leds	= ARRAY_SIZE(stk_j2_led), -+	.leds		= stk_j2_led, ++static struct s1d13xxxfb_pdata ek_s1dfb_pdata = { ++	.initregs		= ek_s1dfb_initregs, ++	.initregssize		= ARRAY_SIZE(ek_s1dfb_initregs), ++	.platform_init_video	= ek_init_video,  +};  + -+static struct platform_device stk_j2_led_dev = { -+	.name		= "leds-gpio", -+	.id		= 2,	/* gpio block J2 */ ++static u64 s1dfb_dmamask = 0xffffffffUL; ++ ++static struct resource ek_s1dfb_resource[] = { ++	[0] = {	/* video mem */ ++		.name   = "s1d13806 memory", ++		.start  = AT91_FB_VMEM_BASE, ++		.end    = AT91_FB_VMEM_BASE + AT91_FB_VMEM_SIZE -1, ++		.flags  = IORESOURCE_MEM, ++	}, ++	[1] = {	/* video registers */ ++		.name   = "s1d13806 registers", ++		.start  = AT91_FB_REG_BASE, ++		.end    = AT91_FB_REG_BASE + AT91_FB_REG_SIZE -1, ++		.flags  = IORESOURCE_MEM, ++	}, ++}; ++ ++static struct platform_device ek_s1dfb_device = { ++	.name		= "s1d13806fb", ++	.id		= -1,  +	.dev		= { -+		.platform_data	= &stk_j2_led_data, ++			.dma_mask		= &s1dfb_dmamask, ++			.coherent_dma_mask	= 0xffffffff, ++			.platform_data		= &ek_s1dfb_pdata,  +	}, ++	.resource	= ek_s1dfb_resource, ++	.num_resources	= ARRAY_SIZE(ek_s1dfb_resource),  +};  + -+static void setup_j2_leds(void) ++static void __init ek_add_device_video(void) ++{ ++	platform_device_register(&ek_s1dfb_device); ++} ++#else ++static void __init ek_add_device_video(void) {} ++#endif ++ + static struct at91_eth_data __initdata ek_eth_data = { + 	.phy_irq_pin	= AT91_PIN_PC4, + 	.is_rmii	= 1, +@@ -113,7 +294,7 @@ + #define EK_FLASH_SIZE	0x200000 +  + static struct physmap_flash_data ek_flash_data = { +-	.width	= 2, ++	.width		= 2, + }; +  + static struct resource ek_flash_resource = { +@@ -132,6 +313,18 @@ + 	.num_resources	= 1, + }; +  ++static struct at91_gpio_led ek_leds[] = { ++	{ ++		.name		= "led0", ++		.gpio		= AT91_PIN_PB1, ++		.trigger	= "heartbeat", ++	}, ++	{ ++		.name		= "led1", ++		.gpio		= AT91_PIN_PB2, ++		.trigger	= "timer", ++	} ++}; +  + static void __init ek_board_init(void)   { --#ifdef	SW2_DEFAULT --	at32_map_usart(1, 0);	/* USART 1/A: /dev/ttyS0, DB9 */ -+	unsigned	i; +@@ -158,8 +351,10 @@ + #endif + 	/* NOR Flash */ + 	platform_device_register(&ek_flash); ++	/* LEDs */ ++	at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds)); + 	/* VGA */ +-//	ek_add_device_video(); ++	ek_add_device_video(); + } +  + MACHINE_START(AT91RM9200EK, "Atmel AT91RM9200-EK") +Index: linux-2.6.22.1/arch/arm/mach-at91/at91rm9200.c +=================================================================== +--- linux-2.6.22.1/arch/arm/mach-at91/at91rm9200.c	(revision 1) ++++ linux-2.6.22.1/arch/arm/mach-at91/at91rm9200.c	(arbetskopia) +@@ -267,6 +267,33 @@ +  +  + /* -------------------------------------------------------------------- ++ *  Timer/Counter library initialization ++ * -------------------------------------------------------------------- */ ++#ifdef CONFIG_ATMEL_TCLIB  + -+	for (i = 0; i < ARRAY_SIZE(stk_j2_led); i++) -+		at32_select_gpio(stk_j2_led[i].gpio, AT32_GPIOF_OUTPUT); ++#include "tclib.h"  + -+	printk("STK1002: " LEDSTRING "\n"); -+	platform_device_register(&stk_j2_led_dev); -+} ++static struct atmel_tcblock at91rm9200_tcblocks[] = { ++	[0] = { ++		.physaddr	= AT91RM9200_BASE_TCB0, ++		.irq		= { AT91RM9200_ID_TC0, AT91RM9200_ID_TC1, AT91RM9200_ID_TC2 }, ++		.clk		= { &tc0_clk, &tc1_clk, &tc2_clk }, ++	}, ++	[1] = { ++		.physaddr	= AT91RM9200_BASE_TCB1, ++		.irq		= { AT91RM9200_ID_TC3, AT91RM9200_ID_TC4, AT91RM9200_ID_TC5 }, ++		.clk		= { &tc3_clk, &tc4_clk, &tc5_clk }, ++	}, ++};  + - #else -+static void setup_j2_leds(void) ++#define at91rm9200_tc_init()	atmel_tc_init(at91rm9200_tcblocks, ARRAY_SIZE(at91rm9200_tcblocks)) ++ ++#else ++#define at91rm9200_tc_init()	do {} while(0) ++#endif ++ ++ ++/* -------------------------------------------------------------------- +  *  AT91RM9200 processor initialization +  * -------------------------------------------------------------------- */ + void __init at91rm9200_initialize(unsigned long main_clock, unsigned short banks) +@@ -288,6 +315,9 @@ +  + 	/* Initialize GPIO subsystem */ + 	at91_gpio_init(at91rm9200_gpio, banks); ++ ++	/* Initialize the Timer/Counter blocks */ ++	at91rm9200_tc_init(); + } +  +  +@@ -301,28 +331,28 @@ + static unsigned int at91rm9200_default_irq_priority[NR_AIC_IRQS] __initdata = { + 	7,	/* Advanced Interrupt Controller (FIQ) */ + 	7,	/* System Peripherals */ +-	0,	/* Parallel IO Controller A */ +-	0,	/* Parallel IO Controller B */ +-	0,	/* Parallel IO Controller C */ +-	0,	/* Parallel IO Controller D */ +-	6,	/* USART 0 */ +-	6,	/* USART 1 */ +-	6,	/* USART 2 */ +-	6,	/* USART 3 */ ++	1,	/* Parallel IO Controller A */ ++	1,	/* Parallel IO Controller B */ ++	1,	/* Parallel IO Controller C */ ++	1,	/* Parallel IO Controller D */ ++	5,	/* USART 0 */ ++	5,	/* USART 1 */ ++	5,	/* USART 2 */ ++	5,	/* USART 3 */ + 	0,	/* Multimedia Card Interface */ +-	4,	/* USB Device Port */ +-	0,	/* Two-Wire Interface */ +-	6,	/* Serial Peripheral Interface */ +-	5,	/* Serial Synchronous Controller 0 */ +-	5,	/* Serial Synchronous Controller 1 */ +-	5,	/* Serial Synchronous Controller 2 */ ++	2,	/* USB Device Port */ ++	6,	/* Two-Wire Interface */ ++	5,	/* Serial Peripheral Interface */ ++	4,	/* Serial Synchronous Controller 0 */ ++	4,	/* Serial Synchronous Controller 1 */ ++	4,	/* Serial Synchronous Controller 2 */ + 	0,	/* Timer Counter 0 */ + 	0,	/* Timer Counter 1 */ + 	0,	/* Timer Counter 2 */ + 	0,	/* Timer Counter 3 */ + 	0,	/* Timer Counter 4 */ + 	0,	/* Timer Counter 5 */ +-	3,	/* USB Host port */ ++	2,	/* USB Host port */ + 	3,	/* Ethernet MAC */ + 	0,	/* Advanced Interrupt Controller (IRQ0) */ + 	0,	/* Advanced Interrupt Controller (IRQ1) */ +Index: linux-2.6.22.1/arch/arm/mach-at91/ics1523.c +=================================================================== +--- linux-2.6.22.1/arch/arm/mach-at91/ics1523.c	(revision 0) ++++ linux-2.6.22.1/arch/arm/mach-at91/ics1523.c	(revision 0) +@@ -0,0 +1,207 @@ ++/* ++ * arch/arm/mach-at91rm9200/ics1523.c ++ * ++ *  Copyright (C) 2003 ATMEL Rousset ++ * ++ * 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 ++ */ ++ ++#include <asm/hardware.h> ++#include <asm/io.h> ++ ++#include <linux/clk.h> ++#include <linux/delay.h> ++#include <linux/err.h> ++#include <linux/init.h> ++ ++#include <asm/arch/ics1523.h> ++#include <asm/arch/at91_twi.h> ++#include <asm/arch/gpio.h> ++ ++/* TWI Errors */ ++#define	AT91_TWI_ERROR	(AT91_TWI_NACK | AT91_TWI_UNRE | AT91_TWI_OVRE) ++ ++ ++static void __iomem *twi_base; ++ ++#define at91_twi_read(reg)		__raw_readl(twi_base + (reg)) ++#define at91_twi_write(reg, val)	__raw_writel((val), twi_base + (reg)) ++ ++ ++/* ----------------------------------------------------------------------------- ++ * Initialization of TWI CLOCK ++ * ----------------------------------------------------------------------------- */ ++ ++static void at91_ics1523_SetTwiClock(unsigned int mck_khz)  +{ ++	int sclock; ++ ++	/* Here, CKDIV = 1 and CHDIV = CLDIV  ==> CLDIV = CHDIV = 1/4*((Fmclk/FTWI) -6) */ ++	sclock = (10*mck_khz / ICS_TRANSFER_RATE); ++	if (sclock % 10 >= 5) ++		sclock = (sclock /10) - 5; ++	else ++		sclock = (sclock /10)- 6; ++	sclock = (sclock + (4 - sclock %4)) >> 2;	/* div 4 */ ++ ++	at91_twi_write(AT91_TWI_CWGR, 0x00010000 | sclock | (sclock << 8));  +} -+#endif  + -+#ifndef CONFIG_BOARD_ATSTK1002_SW1_CUSTOM -+#ifndef CONFIG_BOARD_ATSTK1002_SW3_CUSTOM -+static void __init at73c213_set_clk(struct at73c213_board_info *info) ++/* ----------------------------------------------------------------------------- ++ * Read a byte with TWI Interface from the Clock Generator ICS1523 ++ * ----------------------------------------------------------------------------- */ ++ ++static int at91_ics1523_ReadByte(unsigned char reg_address, unsigned char *data_in)  +{ -+	struct clk *gclk; -+	struct clk *pll; ++	int Status, nb_trial;  + -+	gclk = clk_get(NULL, "gclk0"); -+	if (IS_ERR(gclk)) -+		goto err_gclk; -+	pll = clk_get(NULL, "pll0"); -+	if (IS_ERR(pll)) -+		goto err_pll; ++	at91_twi_write(AT91_TWI_MMR, AT91_TWI_MREAD | AT91_TWI_IADRSZ_1 | ((ICS_ADDR << 16) & AT91_TWI_DADR)); ++	at91_twi_write(AT91_TWI_IADR, reg_address); ++	at91_twi_write(AT91_TWI_CR, AT91_TWI_START | AT91_TWI_STOP);  + -+	if (clk_set_parent(gclk, pll)) { -+		pr_debug("STK1000: failed to set pll0 as parent for DAC clock\n"); -+		goto err_set_clk; ++	/* Program temporizing period (300us) */ ++	udelay(300); ++ ++	/* Wait TXcomplete ... */ ++	nb_trial = 0; ++	Status = at91_twi_read(AT91_TWI_SR); ++	while (!(Status & AT91_TWI_TXCOMP) && (nb_trial < 10)) { ++		nb_trial++; ++		Status = at91_twi_read(AT91_TWI_SR);  +	}  + -+	at32_select_periph(GPIO_PIN_PA(30), GPIO_PERIPH_A, 0); -+	info->dac_clk = gclk; ++	if (Status & AT91_TWI_TXCOMP) { ++		*data_in = (unsigned char) at91_twi_read(AT91_TWI_RHR); ++		return ICS1523_ACCESS_OK; ++	} ++	else ++		return ICS1523_ACCESS_ERROR; ++}  + -+err_set_clk: -+	clk_put(pll); -+err_pll: -+	clk_put(gclk); -+err_gclk: -+	return; ++/* ----------------------------------------------------------------------------- ++ * Write a byte with TWI Interface to the Clock Generator ICS1523 ++ * ----------------------------------------------------------------------------- */ ++ ++static int at91_ics1523_WriteByte(unsigned char reg_address, unsigned char data_out) ++{ ++	int Status, nb_trial; ++ ++	at91_twi_write(AT91_TWI_MMR, AT91_TWI_IADRSZ_1 | ((ICS_ADDR << 16) & AT91_TWI_DADR)); ++	at91_twi_write(AT91_TWI_IADR, reg_address); ++	at91_twi_write(AT91_TWI_THR, data_out); ++	at91_twi_write(AT91_TWI_CR, AT91_TWI_START | AT91_TWI_STOP); ++ ++	/* Program temporizing period (300us) */ ++	udelay(300); ++ ++	nb_trial = 0; ++	Status = at91_twi_read(AT91_TWI_SR); ++	while (!(Status & AT91_TWI_TXCOMP) && (nb_trial < 10)) { ++		nb_trial++; ++		if (Status & AT91_TWI_ERROR) { ++			/* If Underrun OR NACK - Start again */ ++			at91_twi_write(AT91_TWI_CR, AT91_TWI_START | AT91_TWI_STOP); ++ ++			/*  Program temporizing period (300us) */ ++			udelay(300); ++		} ++		Status = at91_twi_read(AT91_TWI_SR); ++	}; ++ ++	if (Status & AT91_TWI_TXCOMP) ++		return ICS1523_ACCESS_OK; ++	else ++		return ICS1523_ACCESS_ERROR;  +} ++ ++/* ----------------------------------------------------------------------------- ++ * Initialization of the Clock Generator ICS1523 ++ * ----------------------------------------------------------------------------- */ ++ ++int at91_ics1523_init(void) ++{ ++	int		nb_trial; ++	int		ack = ICS1523_ACCESS_OK; ++	unsigned int	status = 0xffffffff; ++	struct clk	*twi_clk; ++ ++	/* Map in TWI peripheral */ ++	twi_base = ioremap(AT91RM9200_BASE_TWI, SZ_16K); ++	if (!twi_base) ++		return -ENOMEM; ++ ++	/* pins used for TWI interface */ ++	at91_set_A_periph(AT91_PIN_PA25, 0);            /* TWD */ ++	at91_set_multi_drive(AT91_PIN_PA25, 1); ++	at91_set_A_periph(AT91_PIN_PA26, 0);            /* TWCK */ ++	at91_set_multi_drive(AT91_PIN_PA26, 1); ++ ++	/* Enable the TWI clock */ ++	twi_clk = clk_get(NULL, "twi_clk"); ++	if (IS_ERR(twi_clk)) ++		return ICS1523_ACCESS_ERROR; ++	clk_enable(twi_clk); ++ ++	/* Disable interrupts */ ++	at91_twi_write(AT91_TWI_IDR, -1); ++ ++	/* Reset peripheral */ ++	at91_twi_write(AT91_TWI_CR, AT91_TWI_SWRST); ++ ++	/* Set Master mode */ ++	at91_twi_write(AT91_TWI_CR, AT91_TWI_MSEN); ++ ++	/* Set TWI Clock Waveform Generator Register */ ++	at91_ics1523_SetTwiClock(60000);     /* MCK in KHz = 60000 KHz */ ++ ++	/* ICS1523 Initialisation */ ++	ack |= at91_ics1523_WriteByte ((unsigned char) ICS_ICR, (unsigned char) 0); ++	ack |= at91_ics1523_WriteByte ((unsigned char) ICS_OE, (unsigned char) (ICS_OEF | ICS_OET2 | ICS_OETCK)); ++	ack |= at91_ics1523_WriteByte ((unsigned char) ICS_OD, (unsigned char) (ICS_INSEL | 0x7F)); ++	ack |= at91_ics1523_WriteByte ((unsigned char) ICS_DPAO, (unsigned char) 0); ++ ++	nb_trial = 0; ++	do { ++		nb_trial++; ++		ack |= at91_ics1523_WriteByte ((unsigned char) ICS_ICR, (unsigned char) (ICS_ENDLS | ICS_ENPLS | ICS_PDEN /*| ICS_FUNCSEL*/)); ++		ack |= at91_ics1523_WriteByte ((unsigned char) ICS_LCR, (unsigned char) (ICS_PSD | ICS_PFD)); ++		ack |= at91_ics1523_WriteByte ((unsigned char) ICS_FD0, (unsigned char) 0x39) ; /* 0x7A */ ++		ack |= at91_ics1523_WriteByte ((unsigned char) ICS_FD1, (unsigned char) 0x00); ++		ack |= at91_ics1523_WriteByte ((unsigned char) ICS_SWRST, (unsigned char) (ICS_PLLR)); ++ ++		/* Program 1ms temporizing period */ ++		mdelay(1); ++ ++		at91_ics1523_ReadByte ((unsigned char) ICS_SR, (char *)&status); ++	} while (!((unsigned int) status & (unsigned int) ICS_PLLLOCK) && (nb_trial < 10)); ++ ++	ack |= at91_ics1523_WriteByte ((unsigned char) ICS_DPAC, (unsigned char) 0x03) ; /* 0x01 */ ++	ack |= at91_ics1523_WriteByte ((unsigned char) ICS_SWRST, (unsigned char) (ICS_DPAR)); ++ ++	/* Program 1ms temporizing period */ ++	mdelay(1); ++ ++	ack |= at91_ics1523_WriteByte ((unsigned char) ICS_DPAO, (unsigned char) 0x00); ++ ++	/* Program 1ms temporizing period */ ++	mdelay(1); ++	 ++	/* All done - cleanup */ ++	iounmap(twi_base); ++	clk_disable(twi_clk); ++	clk_put(twi_clk); ++ ++	return ack; ++} +Index: linux-2.6.22.1/arch/arm/mach-at91/at91rm9200_devices.c +=================================================================== +--- linux-2.6.22.1/arch/arm/mach-at91/at91rm9200_devices.c	(revision 1) ++++ linux-2.6.22.1/arch/arm/mach-at91/at91rm9200_devices.c	(arbetskopia) +@@ -477,7 +477,18 @@ +  *  SPI +  * -------------------------------------------------------------------- */ +  +-#if defined(CONFIG_SPI_AT91) || defined(CONFIG_SPI_AT91_MODULE) || defined(CONFIG_AT91_SPI) || defined(CONFIG_AT91_SPI_MODULE) ++#if defined(CONFIG_AT91_SPI) || defined(CONFIG_AT91_SPI_MODULE)		/* legacy SPI driver */ ++#define SPI_DEVNAME	"at91_spi" ++ ++#elif defined(CONFIG_SPI_AT91) || defined(CONFIG_SPI_AT91_MODULE)	/* SPI bitbanging driver */ ++#define SPI_DEVNAME	"at91_spi" ++ ++#elif defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)	/* new SPI driver */ ++#define SPI_DEVNAME	"atmel_spi" ++  +#endif ++ ++#ifdef SPI_DEVNAME + static u64 spi_dmamask = 0xffffffffUL; +  + static struct resource spi_resources[] = { +@@ -494,7 +505,7 @@ + }; +  + static struct platform_device at91rm9200_spi_device = { +-	.name		= "at91_spi", ++	.name		= SPI_DEVNAME, + 	.id		= 0, + 	.dev		= { + 				.dma_mask		= &spi_dmamask, +@@ -603,6 +614,32 @@ + #endif +  +  ++#if defined(CONFIG_NEW_LEDS) ++ ++static struct platform_device at91_leds = { ++	.name		= "at91_leds", ++	.id		= -1, ++}; ++ ++void __init at91_gpio_leds(struct at91_gpio_led *leds, int nr) ++{ ++	if (!nr) ++		return; ++ ++	at91_leds.dev.platform_data = leds; ++ ++	for ( ; nr; nr--, leds++) { ++		leds->index = nr;	/* first record stores number of leds */ ++		at91_set_gpio_output(leds->gpio, (leds->flags & 1) == 0); ++	} ++ ++	platform_device_register(&at91_leds); ++} ++#else ++void __init at91_gpio_leds(struct at91_gpio_led *leds, int nr) {}  +#endif  + -+void __init setup_board(void) ++ + /* -------------------------------------------------------------------- +  *  UART +  * -------------------------------------------------------------------- */ +Index: linux-2.6.22.1/arch/arm/mach-at91/Makefile +=================================================================== +--- linux-2.6.22.1/arch/arm/mach-at91/Makefile	(revision 1) ++++ linux-2.6.22.1/arch/arm/mach-at91/Makefile	(arbetskopia) +@@ -8,6 +8,8 @@ + obj-		:= +  + obj-$(CONFIG_PM)		+= pm.o ++obj-$(CONFIG_AT91_SLOW_CLOCK)	+= pm_slowclock.o ++obj-$(CONFIG_ATMEL_TCLIB)	+= tclib.o +  + # CPU-specific support + obj-$(CONFIG_ARCH_AT91RM9200)	+= at91rm9200.o at91rm9200_time.o at91rm9200_devices.o +@@ -26,10 +28,12 @@ + obj-$(CONFIG_MACH_KB9200)	+= board-kb9202.o + obj-$(CONFIG_MACH_ATEB9200)	+= board-eb9200.o + obj-$(CONFIG_MACH_KAFA)		+= board-kafa.o ++obj-$(CONFIG_MACH_CHUB)		+= board-chub.o + obj-$(CONFIG_MACH_PICOTUX2XX)	+= board-picotux200.o +  + # AT91SAM9260 board-specific support + obj-$(CONFIG_MACH_AT91SAM9260EK) += board-sam9260ek.o ++obj-$(CONFIG_MACH_CAM60)	+= board-cam60.o +  + # AT91SAM9261 board-specific support + obj-$(CONFIG_MACH_AT91SAM9261EK) += board-sam9261ek.o +@@ -51,7 +55,7 @@ + obj-$(CONFIG_LEDS) += $(led-y) +  + # VGA support +-#obj-$(CONFIG_FB_S1D13XXX)	+= ics1523.o ++obj-$(CONFIG_FB_S1D13XXX)	+= ics1523.o +  +  + ifeq ($(CONFIG_PM_DEBUG),y) +Index: linux-2.6.22.1/arch/arm/mach-at91/tclib.c +=================================================================== +--- linux-2.6.22.1/arch/arm/mach-at91/tclib.c	(revision 0) ++++ linux-2.6.22.1/arch/arm/mach-at91/tclib.c	(revision 0) +@@ -0,0 +1,17 @@ ++#include <linux/clk.h> ++#include <linux/kernel.h> ++#include <linux/module.h> ++ ++#include "tclib.h" ++ ++static struct atmel_tcblock *blocks; ++static int nblocks; ++ ++/* ++ * Called from the processor-specific init to register the TC Blocks. ++ */ ++void __init atmel_tc_init(struct atmel_tcblock *tcblocks, int n)  +{ -+#ifdef	CONFIG_BOARD_ATSTK1002_SW2_CUSTOM - 	at32_map_usart(0, 1);	/* USART 0/B: /dev/ttyS1, IRDA */ ++	blocks = tcblocks; ++	nblocks = n; ++} +Index: linux-2.6.22.1/arch/arm/mach-at91/tclib.h +=================================================================== +--- linux-2.6.22.1/arch/arm/mach-at91/tclib.h	(revision 0) ++++ linux-2.6.22.1/arch/arm/mach-at91/tclib.h	(revision 0) +@@ -0,0 +1,11 @@ ++ ++#define TC_PER_TCB	3 ++ ++struct atmel_tcblock { ++	u32 		physaddr; ++	void __iomem	*ioaddr; ++	struct clk	*clk[TC_PER_TCB]; ++	int		irq[TC_PER_TCB]; ++}; ++ ++extern void __init atmel_tc_init(struct atmel_tcblock *tcblocks, int n); +Index: linux-2.6.22.1/arch/arm/mach-at91/at91sam9rl.c +=================================================================== +--- linux-2.6.22.1/arch/arm/mach-at91/at91sam9rl.c	(revision 1) ++++ linux-2.6.22.1/arch/arm/mach-at91/at91sam9rl.c	(arbetskopia) +@@ -246,6 +246,28 @@ +  +  + /* -------------------------------------------------------------------- ++ *  Timer/Counter library initialization ++ * -------------------------------------------------------------------- */ ++#ifdef CONFIG_ATMEL_TCLIB ++ ++#include "tclib.h" ++ ++static struct atmel_tcblock at91sam9rl_tcblocks[] = { ++	[0] = { ++		.physaddr	= AT91SAM9RL_BASE_TCB0, ++		.irq		= { AT91SAM9RL_ID_TC0, AT91SAM9RL_ID_TC1, AT91SAM9RL_ID_TC2 }, ++		.clk		= { &tc0_clk, &tc1_clk, &tc2_clk }, ++	} ++}; ++ ++#define at91sam9rl_tc_init()	atmel_tc_init(at91sam9rl_tcblocks, ARRAY_SIZE(at91sam9rl_tcblocks)) ++  +#else -+	at32_map_usart(1, 0);	/* USART 1/A: /dev/ttyS0, DB9 */ ++#define at91sam9rl_tc_init()	do {} while(0) ++#endif ++ ++ ++/* -------------------------------------------------------------------- +  *  AT91SAM9RL processor initialization +  * -------------------------------------------------------------------- */ +  +@@ -284,6 +306,9 @@ +  + 	/* Register GPIO subsystem */ + 	at91_gpio_init(at91sam9rl_gpio, 4); ++	 ++	/* Initialize the Timer/Counter blocks */ ++	at91sam9rl_tc_init(); + } +  + /* -------------------------------------------------------------------- +Index: linux-2.6.22.1/arch/arm/mach-at91/at91sam9rl_devices.c +=================================================================== +--- linux-2.6.22.1/arch/arm/mach-at91/at91sam9rl_devices.c	(revision 1) ++++ linux-2.6.22.1/arch/arm/mach-at91/at91sam9rl_devices.c	(arbetskopia) +@@ -370,6 +370,32 @@   #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); ++#if defined(CONFIG_NEW_LEDS) ++ ++static struct platform_device at91_leds = { ++	.name		= "at91_leds", ++	.id		= -1, ++}; ++ ++void __init at91_gpio_leds(struct at91_gpio_led *leds, int nr) ++{ ++	if (!nr) ++		return; ++ ++	at91_leds.dev.platform_data = leds; ++ ++	for ( ; nr; nr--, leds++) { ++		leds->index = nr;	/* first record stores number of leds */ ++		at91_set_gpio_output(leds->gpio, (leds->flags & 1) == 0); ++	} ++ ++	platform_device_register(&at91_leds); ++}  +#else -+	at32_add_device_usart(0); - #endif - 	at32_add_device_usart(2); ++void __init at91_gpio_leds(struct at91_gpio_led *leds, int nr) {} ++#endif ++ ++ + /* -------------------------------------------------------------------- +  *  UART +  * -------------------------------------------------------------------- */ +Index: linux-2.6.22.1/arch/arm/mach-at91/pm.c +=================================================================== +--- linux-2.6.22.1/arch/arm/mach-at91/pm.c	(revision 1) ++++ linux-2.6.22.1/arch/arm/mach-at91/pm.c	(arbetskopia) +@@ -63,6 +63,7 @@ +  * Verify that all the clocks are correct before entering +  * slow-clock mode. +  */ ++#warning "SAM9260 only has 3 programmable clocks." + static int at91_pm_verify_clocks(void) + { + 	unsigned long scsr; +@@ -103,20 +104,15 @@ + } -+#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)); + /* +- * Call this from platform driver suspend() to see how deeply to suspend. ++ * This is called from clk_must_disable(), to see how deeply to suspend. +  * For example, some controllers (like OHCI) need one of the PLL clocks +  * in order to act as a wakeup source, and those are not available when +  * going into slow clock mode. +- * +- * REVISIT: generalize as clk_will_be_available(clk)?  Other platforms have +- * the very same problem (but not using at91 main_clk), and it'd be better +- * to add one generic API rather than lots of platform-specific ones. +  */ + int at91_suspend_entering_slow_clock(void) + { + 	return (target_state == PM_SUSPEND_MEM); + } +-EXPORT_SYMBOL(at91_suspend_entering_slow_clock); +  +  + static void (*slow_clock)(void); +@@ -205,16 +201,23 @@ + 	.enter		= at91_pm_enter, + }; +  ++#ifdef CONFIG_AT91_SLOW_CLOCK ++extern void at91rm9200_slow_clock(void); ++extern u32 at91rm9200_slow_clock_sz;  +#endif -+#ifdef CONFIG_BOARD_ATSTK1002_SW5_CUSTOM -+	set_hw_addr(at32_add_device_eth(1, ð_data[1])); ++ + static int __init at91_pm_init(void) + { +-	printk("AT91: Power Management\n"); +- +-#ifdef CONFIG_AT91_PM_SLOW_CLOCK +-	/* REVISIT allocations of SRAM should be dynamically managed. ++#ifdef CONFIG_AT91_SLOW_CLOCK ++	/* ++	 * REVISIT allocations of SRAM should be dynamically managed. + 	 * FIQ handlers and other components will want SRAM/TCM too... + 	 */ +-	slow_clock = (void *) (AT91_VA_BASE_SRAM + (3 * SZ_4K)); ++	slow_clock = (void *) (AT91_IO_VIRT_BASE - AT91RM9200_SRAM_SIZE + (3 * SZ_4K)); + 	memcpy(slow_clock, at91rm9200_slow_clock, at91rm9200_slow_clock_sz); ++	printk("AT91: Power Management (with slow clock mode)\n");  +#else - 	at32_add_device_lcdc(0, &atstk1000_lcdc_data, - 			     fbmem_start, fbmem_size); -+#endif ++	printk("AT91: Power Management\n"); + #endif +  + 	/* Disable SDRAM low-power mode.  Cannot be used with self-refresh. */ +Index: linux-2.6.22.1/arch/arm/mach-at91/pm_slowclock.S +=================================================================== +--- linux-2.6.22.1/arch/arm/mach-at91/pm_slowclock.S	(revision 0) ++++ linux-2.6.22.1/arch/arm/mach-at91/pm_slowclock.S	(revision 0) +@@ -0,0 +1,172 @@ ++/* ++ * arch/arm/mach-at91/pm_slow_clock.S ++ * ++ *  Copyright (C) 2006 Savin Zlobec ++ * ++ * 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 CONFIG_BOARD_ATSTK1002_SW1_CUSTOM -+	at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info)); ++#include <linux/linkage.h> ++#include <asm/hardware.h> ++#include <asm/arch/at91_pmc.h> ++#include <asm/arch/at91rm9200_mc.h> ++ ++#define MCKRDY_TIMEOUT		1000 ++#define MOSCRDY_TIMEOUT 	1000 ++#define PLLALOCK_TIMEOUT	1000 ++ ++	.macro wait_mckrdy ++	mov	r2, #MCKRDY_TIMEOUT ++1:	sub	r2, r2, #1 ++	cmp	r2, #0 ++	beq	2f ++	ldr	r3, [r1, #AT91_PMC_SR] ++	tst	r3, #AT91_PMC_MCKRDY ++	beq	1b ++2: ++	.endm ++ ++	.macro wait_moscrdy ++	mov	r2, #MOSCRDY_TIMEOUT ++1:	sub	r2, r2, #1 ++	cmp	r2, #0 ++	beq	2f ++	ldr	r3, [r1, #AT91_PMC_SR] ++	tst	r3, #AT91_PMC_MOSCS ++	beq	1b ++2: ++	.endm ++ ++	.macro wait_pllalock ++	mov	r2, #PLLALOCK_TIMEOUT ++1:	sub	r2, r2, #1 ++	cmp	r2, #0 ++	beq	2f ++	ldr	r3, [r1, #AT91_PMC_SR] ++	tst	r3, #AT91_PMC_LOCKA ++	beq	1b ++2: ++	.endm ++ ++	.macro wait_plladis ++	mov	r2, #PLLALOCK_TIMEOUT ++1:	sub	r2, r2, #1 ++	cmp	r2, #0 ++	beq	2f ++	ldr	r3, [r1, #AT91_PMC_SR] ++	tst	r3, #AT91_PMC_LOCKA ++	bne	1b ++2: ++	.endm ++ ++	.text ++ ++ENTRY(at91rm9200_slow_clock) ++ ++	ldr	r1, .at91_va_base_sys ++ ++	/* Put SDRAM in self refresh mode */ ++ ++	b	1f ++	.align	5 ++1:	mcr	p15, 0, r0, c7, c10, 4 ++	mov	r2, #1 ++	str	r2, [r1, #AT91_SDRAMC_SRR] ++ ++	/* Save Master clock setting */ ++ ++	ldr	r2, [r1, #AT91_PMC_MCKR] ++	str	r2, .saved_mckr ++ ++	/* ++	 * Set the Master clock source to slow clock ++	 * ++	 * First set the CSS field, wait for MCKRDY ++	 * and than set the PRES and MDIV fields. ++	 * ++	 * See eratta #2[78] for details. ++	 */ ++ ++	bic	r2, r2, #3 ++	str	r2, [r1, #AT91_PMC_MCKR] ++ ++	wait_mckrdy ++ ++	mov	r2, #0 ++	str	r2, [r1, #AT91_PMC_MCKR] ++ ++	/* Save PLLA setting and disable it */ ++ ++	ldr	r2, [r1, #AT91_CKGR_PLLAR] ++	str	r2, .saved_pllar ++ ++	mov	r2, #0 ++	str	r2, [r1, #AT91_CKGR_PLLAR] ++ ++	wait_plladis ++ ++	/* Turn off the main oscillator */ ++ ++	ldr	r2, [r1, #AT91_CKGR_MOR] ++	bic	r2, r2, #AT91_PMC_MOSCEN ++	str	r2, [r1, #AT91_CKGR_MOR] ++ ++	/* Wait for interrupt */ ++ ++	mcr	p15, 0, r0, c7, c0, 4 ++ ++	/* Turn on the main oscillator */ ++ ++	ldr	r2, [r1, #AT91_CKGR_MOR] ++	orr	r2, r2, #AT91_PMC_MOSCEN ++	str	r2, [r1, #AT91_CKGR_MOR] ++ ++	wait_moscrdy ++ ++	/* Restore PLLA setting */ ++ ++	ldr	r2, .saved_pllar ++	str	r2, [r1, #AT91_CKGR_PLLAR] ++ ++	wait_pllalock ++ ++	/* ++	 * Restore master clock setting ++	 * ++	 * First set PRES if it was not 0, ++	 * than set CSS and MDIV fields. ++	 * After every change wait for ++	 * MCKRDY. ++	 * ++	 * See eratta #2[78] for details. ++	 */ ++ ++	ldr	r2, .saved_mckr ++	tst	r2, #0x1C ++	beq	2f ++	and	r2, r2, #0x1C ++	str	r2, [r1, #AT91_PMC_MCKR] ++ ++	wait_mckrdy ++ ++2:	ldr	r2, .saved_mckr ++	str	r2, [r1, #AT91_PMC_MCKR] ++ ++	wait_mckrdy ++ ++	mov	pc, lr ++ ++.saved_mckr: ++	.word 0 ++ ++.saved_pllar: ++	.word 0 ++ ++.at91_va_base_sys: ++	.word AT91_VA_BASE_SYS ++ ++ENTRY(at91rm9200_slow_clock_sz) ++	.word .-at91rm9200_slow_clock +Index: linux-2.6.22.1/arch/arm/mach-at91/board-dk.c +=================================================================== +--- linux-2.6.22.1/arch/arm/mach-at91/board-dk.c	(revision 1) ++++ linux-2.6.22.1/arch/arm/mach-at91/board-dk.c	(arbetskopia) +@@ -73,6 +73,185 @@ + 	at91rm9200_init_interrupts(NULL); + } +  ++#if defined(CONFIG_FB_S1D13XXX) || defined(CONFIG_FB_S1D13XXX_MODULE) ++#include <video/s1d13xxxfb.h> ++#include <asm/arch/ics1523.h> ++ ++/* EPSON S1D13806 FB */ ++#define AT91_FB_REG_BASE	0x30000000L ++#define AT91_FB_REG_SIZE	0x200 ++#define AT91_FB_VMEM_BASE	0x30200000L ++#define AT91_FB_VMEM_SIZE	0x140000L ++ ++static void __init dk_init_video(void) ++{ ++	/* NWAIT Signal */ ++	at91_set_A_periph(AT91_PIN_PC6, 0); ++ ++	/* Initialization of the Static Memory Controller for Chip Select 2 */ ++	at91_sys_write(AT91_SMC_CSR(2), AT91_SMC_DBW_16			/* 16 bit */ ++				| AT91_SMC_WSEN | AT91_SMC_NWS_(4)	/* wait states */ ++				| AT91_SMC_TDF_(1)			/* float time */ ++	); ++ ++	at91_ics1523_init(); ++} ++ ++/* CRT:    (active)   640x480 60Hz (PCLK=CLKI=25.175MHz) ++   Memory: Embedded SDRAM (MCLK=CLKI3=50.000MHz) (BUSCLK=60.000MHz) */ ++static const struct s1d13xxxfb_regval dk_s1dfb_initregs[] = { ++	{S1DREG_MISC,			0x00},	/* Enable Memory/Register select bit */ ++	{S1DREG_COM_DISP_MODE,		0x00},	/* disable display output */ ++	{S1DREG_GPIO_CNF0,		0x00}, ++	{S1DREG_GPIO_CNF1,		0x00}, ++	{S1DREG_GPIO_CTL0,		0x08}, ++	{S1DREG_GPIO_CTL1,		0x00}, ++	{S1DREG_CLK_CNF,		0x01},	/* no divide, MCLK source is CLKI3 0x02*/ ++	{S1DREG_LCD_CLK_CNF,		0x00}, ++	{S1DREG_CRT_CLK_CNF,		0x00}, ++	{S1DREG_MPLUG_CLK_CNF,		0x00}, ++	{S1DREG_CPU2MEM_WST_SEL,	0x01},	/* 2*period(MCLK) - 4ns > period(BCLK) */ ++	{S1DREG_SDRAM_REF_RATE,		0x03},	/* 32768 <= MCLK <= 50000 (MHz) */ ++	{S1DREG_SDRAM_TC0,		0x00},	/* MCLK source freq (MHz): */ ++	{S1DREG_SDRAM_TC1,		0x01},	/* 42 <= MCLK <= 50 */ ++	{S1DREG_MEM_CNF,		0x80},	/* SDRAM Initialization - needed before mem access */ ++	{S1DREG_PANEL_TYPE,		0x25},	/* std TFT 16bit, 8bit SCP format 2, single passive LCD */ ++	{S1DREG_MOD_RATE,		0x00},	/* toggle every FPFRAME */ ++	{S1DREG_LCD_DISP_HWIDTH,	0x4F},	/* 680 pix */ ++	{S1DREG_LCD_NDISP_HPER,		0x12},	/* 152 pix */ ++	{S1DREG_TFT_FPLINE_START,	0x01},	/* 13 pix */ ++	{S1DREG_TFT_FPLINE_PWIDTH,	0x0B},	/* 96 pix */ ++	{S1DREG_LCD_DISP_VHEIGHT0,	0xDF}, ++	{S1DREG_LCD_DISP_VHEIGHT1,	0x01},	/* 480 lines */ ++	{S1DREG_LCD_NDISP_VPER,		0x2C},	/* 44 lines */ ++	{S1DREG_TFT_FPFRAME_START,	0x0A},	/* 10 lines */ ++	{S1DREG_TFT_FPFRAME_PWIDTH,	0x01},	/* 2 lines */ ++	{S1DREG_LCD_DISP_MODE,		0x05},  /* 16 bpp */ ++	{S1DREG_LCD_MISC,		0x00},	/* dithering enabled, dual panel buffer enabled */ ++	{S1DREG_LCD_DISP_START0,	0x00}, ++	{S1DREG_LCD_DISP_START1,	0xC8}, ++	{S1DREG_LCD_DISP_START2,	0x00}, ++	{S1DREG_LCD_MEM_OFF0,		0x80}, ++	{S1DREG_LCD_MEM_OFF1,		0x02}, ++	{S1DREG_LCD_PIX_PAN,		0x00}, ++	{S1DREG_LCD_DISP_FIFO_HTC,	0x3B}, ++	{S1DREG_LCD_DISP_FIFO_LTC,	0x3C}, ++	{S1DREG_CRT_DISP_HWIDTH,	0x4F},	/* 680 pix */ ++	{S1DREG_CRT_NDISP_HPER,		0x13},	/* 160 pix */ ++	{S1DREG_CRT_HRTC_START,		0x01},	/* 13 pix */ ++	{S1DREG_CRT_HRTC_PWIDTH,	0x0B},	/* 96 pix */ ++	{S1DREG_CRT_DISP_VHEIGHT0,	0xDF}, ++	{S1DREG_CRT_DISP_VHEIGHT1,	0x01},	/* 480 lines */ ++	{S1DREG_CRT_NDISP_VPER,		0x2B},	/* 44 lines */ ++	{S1DREG_CRT_VRTC_START,		0x09},	/* 10 lines */ ++	{S1DREG_CRT_VRTC_PWIDTH,	0x01},	/* 2 lines */ ++	{S1DREG_TV_OUT_CTL,		0x10}, ++	{S1DREG_CRT_DISP_MODE,		0x05},	/* 16 bpp */ ++	{S1DREG_CRT_DISP_START0,	0x00}, ++	{S1DREG_CRT_DISP_START1,	0x00}, ++	{S1DREG_CRT_DISP_START2,	0x00}, ++	{S1DREG_CRT_MEM_OFF0,		0x80}, ++	{S1DREG_CRT_MEM_OFF1,		0x02}, ++	{S1DREG_CRT_PIX_PAN,		0x00}, ++	{S1DREG_CRT_DISP_FIFO_HTC,	0x3B}, ++	{S1DREG_CRT_DISP_FIFO_LTC,	0x3C}, ++	{S1DREG_LCD_CUR_CTL,		0x00},	/* inactive */ ++	{S1DREG_LCD_CUR_START,		0x01}, ++	{S1DREG_LCD_CUR_XPOS0,		0x00}, ++	{S1DREG_LCD_CUR_XPOS1,		0x00}, ++	{S1DREG_LCD_CUR_YPOS0,		0x00}, ++	{S1DREG_LCD_CUR_YPOS1,		0x00}, ++	{S1DREG_LCD_CUR_BCTL0,		0x00}, ++	{S1DREG_LCD_CUR_GCTL0,		0x00}, ++	{S1DREG_LCD_CUR_RCTL0,		0x00}, ++	{S1DREG_LCD_CUR_BCTL1,		0x1F}, ++	{S1DREG_LCD_CUR_GCTL1,		0x3F}, ++	{S1DREG_LCD_CUR_RCTL1,		0x1F}, ++	{S1DREG_LCD_CUR_FIFO_HTC,	0x00}, ++	{S1DREG_CRT_CUR_CTL,		0x00},	/* inactive */ ++	{S1DREG_CRT_CUR_START,		0x01}, ++	{S1DREG_CRT_CUR_XPOS0,		0x00}, ++	{S1DREG_CRT_CUR_XPOS1,		0x00}, ++	{S1DREG_CRT_CUR_YPOS0,		0x00}, ++	{S1DREG_CRT_CUR_YPOS1,		0x00}, ++	{S1DREG_CRT_CUR_BCTL0,		0x00}, ++	{S1DREG_CRT_CUR_GCTL0,		0x00}, ++	{S1DREG_CRT_CUR_RCTL0,		0x00}, ++	{S1DREG_CRT_CUR_BCTL1,		0x1F}, ++	{S1DREG_CRT_CUR_GCTL1,		0x3F}, ++	{S1DREG_CRT_CUR_RCTL1,		0x1F}, ++	{S1DREG_CRT_CUR_FIFO_HTC,	0x00}, ++	{S1DREG_BBLT_CTL0,		0x00}, ++	{S1DREG_BBLT_CTL0,		0x00}, ++	{S1DREG_BBLT_CC_EXP,		0x00}, ++	{S1DREG_BBLT_OP,		0x00}, ++	{S1DREG_BBLT_SRC_START0,	0x00}, ++	{S1DREG_BBLT_SRC_START1,	0x00}, ++	{S1DREG_BBLT_SRC_START2,	0x00}, ++	{S1DREG_BBLT_DST_START0,	0x00}, ++	{S1DREG_BBLT_DST_START1,	0x00}, ++	{S1DREG_BBLT_DST_START2,	0x00}, ++	{S1DREG_BBLT_MEM_OFF0,		0x00}, ++	{S1DREG_BBLT_MEM_OFF1,		0x00}, ++	{S1DREG_BBLT_WIDTH0,		0x00}, ++	{S1DREG_BBLT_WIDTH1,		0x00}, ++	{S1DREG_BBLT_HEIGHT0,		0x00}, ++	{S1DREG_BBLT_HEIGHT1,		0x00}, ++	{S1DREG_BBLT_BGC0,		0x00}, ++	{S1DREG_BBLT_BGC1,		0x00}, ++	{S1DREG_BBLT_FGC0,		0x00}, ++	{S1DREG_BBLT_FGC1,		0x00}, ++	{S1DREG_LKUP_MODE,		0x00},	/* LCD LUT r | LCD and CRT/TV LUT w */ ++	{S1DREG_LKUP_ADDR,		0x00}, ++	{S1DREG_PS_CNF,			0x00},	/* Power Save disable */ ++	{S1DREG_PS_STATUS,		0x02},	/* LCD Panel down, mem up */ ++	{S1DREG_CPU2MEM_WDOGT,		0x00}, ++	{S1DREG_COM_DISP_MODE,		0x02},	/* enable CRT display output */ ++}; ++ ++static struct s1d13xxxfb_pdata dk_s1dfb_pdata = { ++	.initregs		= dk_s1dfb_initregs, ++	.initregssize		= ARRAY_SIZE(dk_s1dfb_initregs), ++	.platform_init_video	= dk_init_video, ++}; ++ ++static u64 s1dfb_dmamask = 0xffffffffUL; ++ ++static struct resource dk_s1dfb_resource[] = { ++	[0] = {	/* video mem */ ++		.name   = "s1d13806 memory", ++		.start  = AT91_FB_VMEM_BASE, ++		.end    = AT91_FB_VMEM_BASE + AT91_FB_VMEM_SIZE -1, ++		.flags  = IORESOURCE_MEM, ++	}, ++	[1] = {	/* video registers */ ++		.name   = "s1d13806 registers", ++		.start  = AT91_FB_REG_BASE, ++		.end    = AT91_FB_REG_BASE + AT91_FB_REG_SIZE -1, ++		.flags  = IORESOURCE_MEM, ++	}, ++}; ++ ++static struct platform_device dk_s1dfb_device = { ++	.name		= "s1d13806fb", ++	.id		= -1, ++	.dev		= { ++			.dma_mask		= &s1dfb_dmamask, ++			.coherent_dma_mask	= 0xffffffff, ++			.platform_data		= &dk_s1dfb_pdata, ++	}, ++	.resource	= dk_s1dfb_resource, ++	.num_resources	= ARRAY_SIZE(dk_s1dfb_resource), ++}; ++ ++static void __init dk_add_device_video(void) ++{ ++	platform_device_register(&dk_s1dfb_device); ++} ++#else ++static void __init dk_add_device_video(void) {}  +#endif -+#ifdef CONFIG_BOARD_ATSTK1002_SPI1 -+	at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info)); ++ + static struct at91_eth_data __initdata dk_eth_data = { + 	.phy_irq_pin	= AT91_PIN_PC4, + 	.is_rmii	= 1, +@@ -151,7 +330,7 @@ + #define DK_FLASH_SIZE	0x200000 +  + static struct physmap_flash_data dk_flash_data = { +-	.width	= 2, ++	.width		= 2, + }; +  + static struct resource dk_flash_resource = { +@@ -170,6 +349,13 @@ + 	.num_resources	= 1, + }; +  ++static struct at91_gpio_led dk_leds[] = { ++	{ ++		.name		= "led0", ++		.gpio		= AT91_PIN_PB2, ++		.trigger	= "timer", ++	} ++}; +  + static void __init dk_board_init(void) + { +@@ -200,8 +386,10 @@ + 	at91_add_device_nand(&dk_nand_data); + 	/* NOR Flash */ + 	platform_device_register(&dk_flash); ++	/* LEDs */ ++	at91_gpio_leds(dk_leds, ARRAY_SIZE(dk_leds)); + 	/* VGA */ +-//	dk_add_device_video(); ++	dk_add_device_video(); + } +  + MACHINE_START(AT91RM9200DK, "Atmel AT91RM9200-DK") +Index: linux-2.6.22.1/arch/arm/mach-at91/board-csb337.c +=================================================================== +--- linux-2.6.22.1/arch/arm/mach-at91/board-csb337.c	(revision 1) ++++ linux-2.6.22.1/arch/arm/mach-at91/board-csb337.c	(arbetskopia) +@@ -24,6 +24,7 @@ + #include <linux/module.h> + #include <linux/platform_device.h> + #include <linux/spi/spi.h> ++#include <linux/interrupt.h> + #include <linux/mtd/physmap.h> +  + #include <asm/hardware.h> +@@ -59,6 +60,7 @@ +  + 	/* Setup the LEDs */ + 	at91_init_leds(AT91_PIN_PB0, AT91_PIN_PB1); ++	at91_set_gpio_output(AT91_PIN_PB2, 1);		/* third (unused) LED */ +  + 	/* Setup the serial ports and console */ + 	at91_init_serial(&csb337_uart_config); +@@ -149,6 +151,55 @@ + 	.num_resources	= ARRAY_SIZE(csb_flash_resources), + }; +  ++static struct at91_gpio_led csb337_leds[] = { ++	{ ++		.name		= "led0", ++		.gpio		= AT91_PIN_PB0, ++		.trigger	= "heartbeat", ++	}, ++	{ ++		.name		= "led1", ++		.gpio		= AT91_PIN_PB1, ++		.trigger	= "timer", ++	}, ++	{ ++		.name		= "led2", ++		.gpio		= AT91_PIN_PB2, ++	} ++}; ++ ++#if defined(CONFIG_CSB300_WAKE_SW0) || defined(CONFIG_CSB300_WAKE_SW1) ++static irqreturn_t switch_irq_handler(int irq, void *context) ++{ ++	return IRQ_HANDLED; ++} ++ ++static inline void __init switch_irq_setup(int irq, char *name, unsigned long mode) ++{ ++	int res; ++ ++	res = request_irq(irq, switch_irq_handler, IRQF_SAMPLE_RANDOM | mode, name, NULL); ++	if (res == 0) ++		enable_irq_wake(irq); ++} ++ ++static void __init csb300_switches(void) ++{ ++#ifdef CONFIG_CSB300_WAKE_SW0 ++	at91_set_A_periph(AT91_PIN_PB29, 1);		/* IRQ0 */ ++	switch_irq_setup(AT91RM9200_ID_IRQ0, "csb300_sw0", IRQF_TRIGGER_FALLING);  +#endif -+	at32_add_device_twi(0); -+#ifndef CONFIG_BOARD_ATSTK1002_SW2_CUSTOM -+	at32_add_device_mci(0, &mci0_data); ++#ifdef CONFIG_CSB300_WAKE_SW1 ++	at91_set_gpio_input(AT91_PIN_PB28, 1); ++	at91_set_deglitch(AT91_PIN_PB28, 1); ++	switch_irq_setup(AT91_PIN_PB28, "csb300_sw1", IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING);  +#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); ++	/* there's also SW2 at PA21, GPIO or TIOA2 */ ++} ++#else ++static void __init csb300_switches(void) {}  +#endif  + -+	setup_j2_leds(); + static void __init csb337_board_init(void) + { + 	/* Serial */ +@@ -168,8 +219,12 @@ + 	at91_add_device_spi(csb337_spi_devices, ARRAY_SIZE(csb337_spi_devices)); + 	/* MMC */ + 	at91_add_device_mmc(0, &csb337_mmc_data); ++	/* LEDS */ ++	at91_gpio_leds(csb337_leds, ARRAY_SIZE(csb337_leds)); + 	/* NOR flash */ + 	platform_device_register(&csb_flash); ++	/* Switches on CSB300 */ ++	csb300_switches(); + } +  + MACHINE_START(CSB337, "Cogent CSB337") +Index: linux-2.6.22.1/arch/arm/mach-at91/clock.c +=================================================================== +--- linux-2.6.22.1/arch/arm/mach-at91/clock.c	(revision 1) ++++ linux-2.6.22.1/arch/arm/mach-at91/clock.c	(arbetskopia) +@@ -32,6 +32,7 @@ + #include <asm/arch/cpu.h> +  + #include "clock.h" ++#include "generic.h" +  +  + /* +@@ -254,6 +255,23 @@ +  + /*------------------------------------------------------------------------*/ +  ++#ifdef CONFIG_PM ++ ++int clk_must_disable(struct clk *clk) ++{ ++	if (!at91_suspend_entering_slow_clock()) ++		return 0; ++ ++	while (clk->parent) ++		clk = clk->parent; ++	return clk != &clk32k; ++} ++EXPORT_SYMBOL(clk_must_disable);  + -+#ifndef CONFIG_BOARD_ATSTK1002_SW3_CUSTOM -+#ifndef CONFIG_BOARD_ATSTK1002_SW1_CUSTOM -+	at73c213_set_clk(&at73c213_data); -+#endif  +#endif ++ ++/*------------------------------------------------------------------------*/ ++ + #ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS - 	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="" + /* +@@ -362,7 +380,7 @@ - # -+# Power managment options -+# + static int at91_clk_show(struct seq_file *s, void *unused) + { +-	u32		scsr, pcsr, sr; ++	u32		scsr, pcsr, sr, i; + 	struct clk	*clk; +  + 	seq_printf(s, "SCSR = %8x\n", scsr = at91_sys_read(AT91_PMC_SCSR)); +@@ -372,6 +390,9 @@ + 	seq_printf(s, "PLLA = %8x\n", at91_sys_read(AT91_CKGR_PLLAR)); + 	seq_printf(s, "PLLB = %8x\n", at91_sys_read(AT91_CKGR_PLLBR)); + 	seq_printf(s, "MCKR = %8x\n", at91_sys_read(AT91_PMC_MCKR)); ++#warning "Hard-coded PCK" ++  	for (i = 0; i < 4; i++) ++  		seq_printf(s, "PCK%d = %8x\n", i, at91_sys_read(AT91_PMC_PCKR(i))); + 	seq_printf(s, "SR   = %8x\n", sr = at91_sys_read(AT91_PMC_SR)); +  + 	seq_printf(s, "\n"); +Index: linux-2.6.22.1/arch/arm/mach-at91/board-cam60.c +=================================================================== +--- linux-2.6.22.1/arch/arm/mach-at91/board-cam60.c	(revision 0) ++++ linux-2.6.22.1/arch/arm/mach-at91/board-cam60.c	(revision 0) +@@ -0,0 +1,148 @@ ++/* ++ * KwikByte CAM60 ++ * ++ * based on board-sam9260ek.c ++ *   Copyright (C) 2005 SAN People ++ *   Copyright (C) 2006 Atmel ++ * ++ * 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 ++ */ ++ ++#include <linux/types.h> ++#include <linux/init.h> ++#include <linux/mm.h> ++#include <linux/module.h> ++#include <linux/platform_device.h> ++#include <linux/spi/spi.h> ++#include <linux/spi/flash.h> ++ ++#include <asm/hardware.h> ++#include <asm/setup.h> ++#include <asm/mach-types.h> ++#include <asm/irq.h> ++ ++#include <asm/mach/arch.h> ++#include <asm/mach/map.h> ++#include <asm/mach/irq.h> ++ ++#include <asm/arch/board.h> ++#include <asm/arch/gpio.h> ++#include <asm/arch/at91sam926x_mc.h> ++ ++#include "generic.h" ++  + ++/* ++ * Serial port configuration. ++ *    0 .. 5 = USART0 .. USART5 ++ *    6      = DBGU ++ */ ++static struct at91_uart_config __initdata cam60_uart_config = { ++	.console_tty	= 0,				/* ttyS0 */ ++	.nr_tty		= 1, ++	.tty_map	= { 6, -1, -1, -1, -1, -1, -1 }	/* ttyS0, ..., ttyS6 */ ++}; ++ ++static void __init cam60_map_io(void) ++{ ++	/* Initialize processor: 10 MHz crystal */ ++	at91sam9260_initialize(10000000); ++ ++	/* Setup the serial ports and console */ ++	at91_init_serial(&cam60_uart_config); ++} ++ ++static void __init cam60_init_irq(void) ++{ ++	at91sam9260_init_interrupts(NULL); ++} ++ ++ ++/* ++ * SPI devices. ++ */ ++#if defined(CONFIG_MTD_DATAFLASH) ++static struct mtd_partition __initdata cam60_spi_partitions[] = { ++	{ ++		.name	= "BOOT1", ++		.offset	= 0, ++		.size	= 4 * 1056, ++	}, ++	{ ++		.name	= "BOOT2", ++		.offset	= MTDPART_OFS_NXTBLK, ++		.size	= 256 * 1056, ++	}, ++	{ ++		.name	= "kernel", ++		.offset	= MTDPART_OFS_NXTBLK, ++		.size	= 2222 * 1056, ++	}, ++	{ ++		.name	= "file system", ++		.offset	= MTDPART_OFS_NXTBLK, ++		.size	= MTDPART_SIZ_FULL, ++	}, ++}; ++ ++static struct flash_platform_data __initdata cam60_spi_flash_platform_data = { ++	.name		= "spi_flash", ++	.parts		= cam60_spi_partitions, ++	.nr_parts	= ARRAY_SIZE(cam60_spi_partitions) ++}; ++#endif ++ ++static struct spi_board_info cam60_spi_devices[] = { ++#if defined(CONFIG_MTD_DATAFLASH) ++	{	/* DataFlash chip */ ++		.modalias	= "mtd_dataflash", ++		.chip_select	= 0, ++		.max_speed_hz	= 15 * 1000 * 1000, ++		.bus_num	= 0, ++		.platform_data	= &cam60_spi_flash_platform_data ++	}, ++#endif ++}; ++ ++ ++/* ++ * MACB Ethernet device ++ */ ++static struct __initdata at91_eth_data cam60_macb_data = { ++	.phy_irq_pin	= AT91_PIN_PB5, ++	.is_rmii	= 0, ++}; ++ ++ ++static void __init cam60_board_init(void) ++{ ++	/* Serial */ ++	at91_add_device_serial(); ++	/* SPI */ ++	at91_add_device_spi(cam60_spi_devices, ARRAY_SIZE(cam60_spi_devices)); ++	/* Ethernet */ ++	at91_add_device_eth(&cam60_macb_data); ++} ++ ++MACHINE_START(CAM60, "KwikByte CAM60") ++	/* Maintainer: KwikByte */ ++	.phys_io	= AT91_BASE_SYS, ++	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc, ++	.boot_params	= AT91_SDRAM_BASE + 0x100, ++	.timer		= &at91sam926x_timer, ++	.map_io		= cam60_map_io, ++	.init_irq	= cam60_init_irq, ++	.init_machine	= cam60_board_init, ++MACHINE_END +Index: linux-2.6.22.1/arch/arm/configs/cam60_defconfig +=================================================================== +--- linux-2.6.22.1/arch/arm/configs/cam60_defconfig	(revision 0) ++++ linux-2.6.22.1/arch/arm/configs/cam60_defconfig	(revision 0) +@@ -0,0 +1,954 @@  +# -+# CPU Frequency scaling ++# Automatically generated make config: don't edit ++# Linux kernel version: 2.6.20 ++# Tue May  1 21:06:33 2007  +# -+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 ++CONFIG_ARM=y ++# CONFIG_GENERIC_TIME is not set ++CONFIG_MMU=y ++CONFIG_GENERIC_HARDIRQS=y ++CONFIG_TRACE_IRQFLAGS_SUPPORT=y ++CONFIG_HARDIRQS_SW_RESEND=y ++CONFIG_GENERIC_IRQ_PROBE=y ++CONFIG_RWSEM_GENERIC_SPINLOCK=y ++# CONFIG_ARCH_HAS_ILOG2_U32 is not set ++# CONFIG_ARCH_HAS_ILOG2_U64 is not set ++CONFIG_GENERIC_HWEIGHT=y ++CONFIG_GENERIC_CALIBRATE_DELAY=y ++CONFIG_VECTORS_BASE=0xffff0000 ++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"  +  +# - # 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 ++# Code maturity level options ++# ++CONFIG_EXPERIMENTAL=y ++CONFIG_BROKEN_ON_SMP=y ++CONFIG_INIT_ENV_ARG_LIMIT=32  +  +# -+# Bridge: Netfilter Configuration ++# General setup  +# -+# 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 ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++# CONFIG_SWAP is not set ++CONFIG_SYSVIPC=y ++# CONFIG_IPC_NS is not set ++# CONFIG_POSIX_MQUEUE is not set ++# CONFIG_BSD_PROCESS_ACCT is not set ++# CONFIG_TASKSTATS is not set ++# CONFIG_UTS_NS is not set ++# CONFIG_AUDIT is not set ++CONFIG_IKCONFIG=y ++CONFIG_IKCONFIG_PROC=y ++CONFIG_SYSFS_DEPRECATED=y ++# CONFIG_RELAY is not set ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_CC_OPTIMIZE_FOR_SIZE=y ++CONFIG_SYSCTL=y ++# CONFIG_EMBEDDED is not set ++CONFIG_UID16=y ++CONFIG_SYSCTL_SYSCALL=y ++CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set ++# CONFIG_KALLSYMS_EXTRA_PASS is not set ++CONFIG_HOTPLUG=y ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++CONFIG_BASE_FULL=y ++CONFIG_FUTEX=y ++CONFIG_EPOLL=y ++CONFIG_SHMEM=y ++CONFIG_SLAB=y ++CONFIG_VM_EVENT_COUNTERS=y ++CONFIG_RT_MUTEXES=y ++# CONFIG_TINY_SHMEM is not set ++CONFIG_BASE_SMALL=0 ++# CONFIG_SLOB is not set  +  +# -+# MII PHY device drivers ++# Loadable module support  +# -+# 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 ++CONFIG_MODULES=y ++CONFIG_MODULE_UNLOAD=y ++CONFIG_MODULE_FORCE_UNLOAD=y ++# CONFIG_MODVERSIONS is not set ++# CONFIG_MODULE_SRCVERSION_ALL is not set ++# CONFIG_KMOD is not set  +  +# -+# Watchdog Device Drivers ++# Block layer  +# -+# 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 ++CONFIG_BLOCK=y ++# CONFIG_LBD is not set ++# CONFIG_BLK_DEV_IO_TRACE is not set ++# CONFIG_LSF is not set  +  +# -+# I2C Algorithms ++# IO Schedulers  +# -+CONFIG_I2C_ALGOBIT=m -+# CONFIG_I2C_ALGOPCF is not set -+# CONFIG_I2C_ALGOPCA is not set ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_AS=y ++# CONFIG_IOSCHED_DEADLINE is not set ++# CONFIG_IOSCHED_CFQ is not set ++CONFIG_DEFAULT_AS=y ++# CONFIG_DEFAULT_DEADLINE is not set ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="anticipatory"  +  +# -+# I2C Hardware Bus support ++# System Type  +# -+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 ++# CONFIG_ARCH_AAEC2000 is not set ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_VERSATILE is not set ++CONFIG_ARCH_AT91=y ++# CONFIG_ARCH_CLPS7500 is not set ++# CONFIG_ARCH_CLPS711X is not set ++# CONFIG_ARCH_CO285 is not set ++# CONFIG_ARCH_EBSA110 is not set ++# CONFIG_ARCH_EP93XX is not set ++# CONFIG_ARCH_FOOTBRIDGE is not set ++# CONFIG_ARCH_NETX is not set ++# CONFIG_ARCH_H720X is not set ++# CONFIG_ARCH_IMX is not set ++# CONFIG_ARCH_IOP32X is not set ++# CONFIG_ARCH_IOP33X is not set ++# CONFIG_ARCH_IOP13XX is not set ++# CONFIG_ARCH_IXP4XX is not set ++# CONFIG_ARCH_IXP2000 is not set ++# CONFIG_ARCH_IXP23XX is not set ++# CONFIG_ARCH_L7200 is not set ++# CONFIG_ARCH_PNX4008 is not set ++# CONFIG_ARCH_PXA is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C2410 is not set ++# CONFIG_ARCH_SHARK is not set ++# CONFIG_ARCH_LH7A40X is not set ++# CONFIG_ARCH_OMAP is not set  +  +# -+# Miscellaneous I2C Chip support ++# Atmel AT91 System-on-Chip  +# -+# 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 ++# CONFIG_ARCH_AT91RM9200 is not set ++CONFIG_ARCH_AT91SAM9260=y ++# CONFIG_ARCH_AT91SAM9261 is not set ++# CONFIG_ARCH_AT91SAM9263 is not set  +  +# -+# MMC/SD Card Drivers ++# AT91SAM9260 Board Type  +# -+CONFIG_MMC_BLOCK=y ++# CONFIG_MACH_AT91SAM9260EK is not set ++CONFIG_MACH_CAM60=y  +  +# -+# MMC/SD Host Controller Drivers ++# AT91 Board Options  +# -+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 ++# AT91 Feature Selections  +# -+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 ++# CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set  +  +# -+# I2C RTC drivers ++# Processor Type  +# -+# 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 ++CONFIG_CPU_32=y ++CONFIG_CPU_ARM926T=y ++CONFIG_CPU_32v5=y ++CONFIG_CPU_ABRT_EV5TJ=y ++CONFIG_CPU_CACHE_VIVT=y ++CONFIG_CPU_COPY_V4WB=y ++CONFIG_CPU_TLB_V4WBI=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y  +  +# -+# SPI RTC drivers ++# Processor Features  +# -+# CONFIG_RTC_DRV_RS5C348 is not set -+# CONFIG_RTC_DRV_MAX6902 is not set ++# CONFIG_ARM_THUMB is not set ++# CONFIG_CPU_ICACHE_DISABLE is not set ++# CONFIG_CPU_DCACHE_DISABLE is not set ++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set ++# CONFIG_CPU_CACHE_ROUND_ROBIN is not set  +  +# -+# Platform RTC drivers ++# Bus support  +# -+# 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 ++# PCCARD (PCMCIA/CardBus) support  +# ++# CONFIG_PCCARD is not set  +  +# -+# CPU Frequency scaling ++# Kernel Features  +# -+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 ++# CONFIG_PREEMPT is not set ++# CONFIG_NO_IDLE_HZ is not set ++CONFIG_HZ=100 ++# CONFIG_AEABI is not set ++# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set ++CONFIG_SELECT_MEMORY_MODEL=y ++CONFIG_FLATMEM_MANUAL=y ++# CONFIG_DISCONTIGMEM_MANUAL is not set ++# CONFIG_SPARSEMEM_MANUAL is not set ++CONFIG_FLATMEM=y ++CONFIG_FLAT_NODE_MEM_MAP=y ++# CONFIG_SPARSEMEM_STATIC is not set ++CONFIG_SPLIT_PTLOCK_CPUS=4096 ++# CONFIG_RESOURCES_64BIT is not set ++# CONFIG_LEDS is not set ++CONFIG_ALIGNMENT_TRAP=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 ++# Boot options ++# ++CONFIG_ZBOOT_ROM_TEXT=0x22000000 ++CONFIG_ZBOOT_ROM_BSS=0x20004000 ++# CONFIG_ZBOOT_ROM is not set ++CONFIG_CMDLINE="console=ttyS0,115200 noinitrd root=/dev/mtdblock3 rootfstype=jffs2 mem=64M" ++# CONFIG_XIP_KERNEL is not set  +  +# -+# MII PHY device drivers ++# Floating point emulation  +# -+# 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 ++# At least one emulation must be selected  +# -+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 ++CONFIG_FPE_NWFPE=y ++# CONFIG_FPE_NWFPE_XP is not set ++# CONFIG_FPE_FASTFPE is not set ++# CONFIG_VFP is not set  +  +# -+# Input Device Drivers ++# Userspace binary formats  +# -+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 ++CONFIG_BINFMT_ELF=y ++# CONFIG_BINFMT_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++# CONFIG_ARTHUR is not set  +  +# -+# Watchdog Device Drivers ++# Power management options  +# -+# 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 ++# CONFIG_PM is not set ++# CONFIG_APM is not set  +  +# -+# I2C Algorithms ++# Networking  +# -+CONFIG_I2C_ALGOBIT=m -+# CONFIG_I2C_ALGOPCF is not set -+# CONFIG_I2C_ALGOPCA is not set ++CONFIG_NET=y  +  +# -+# I2C Hardware Bus support ++# Networking options  +# -+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 ++# CONFIG_NETDEBUG is not set ++CONFIG_PACKET=y ++# CONFIG_PACKET_MMAP is not set ++CONFIG_UNIX=y ++CONFIG_XFRM=y ++# CONFIG_XFRM_USER is not set ++# CONFIG_XFRM_SUB_POLICY is not set ++# CONFIG_NET_KEY is not set ++CONFIG_INET=y ++# CONFIG_IP_MULTICAST is not set ++# CONFIG_IP_ADVANCED_ROUTER is not set ++CONFIG_IP_FIB_HASH=y ++CONFIG_IP_PNP=y ++# CONFIG_IP_PNP_DHCP is not set ++CONFIG_IP_PNP_BOOTP=y ++# CONFIG_IP_PNP_RARP is not set ++# CONFIG_NET_IPIP is not set ++# CONFIG_NET_IPGRE is not set ++# CONFIG_ARPD is not set ++# CONFIG_SYN_COOKIES is not set ++# CONFIG_INET_AH is not set ++# CONFIG_INET_ESP is not set ++# CONFIG_INET_IPCOMP is not set ++# CONFIG_INET_XFRM_TUNNEL is not set ++# CONFIG_INET_TUNNEL is not set ++CONFIG_INET_XFRM_MODE_TRANSPORT=y ++CONFIG_INET_XFRM_MODE_TUNNEL=y ++CONFIG_INET_XFRM_MODE_BEET=y ++CONFIG_INET_DIAG=y ++CONFIG_INET_TCP_DIAG=y ++# CONFIG_TCP_CONG_ADVANCED is not set ++CONFIG_TCP_CONG_CUBIC=y ++CONFIG_DEFAULT_TCP_CONG="cubic" ++# CONFIG_TCP_MD5SIG is not set ++# CONFIG_IPV6 is not set ++# CONFIG_INET6_XFRM_TUNNEL is not set ++# CONFIG_INET6_TUNNEL is not set ++# CONFIG_NETWORK_SECMARK is not set ++# CONFIG_NETFILTER is not set  +  +# -+# Miscellaneous I2C Chip support ++# DCCP Configuration (EXPERIMENTAL)  +# -+# 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 ++# CONFIG_IP_DCCP is not set  +  +# -+# SPI Master Controller Drivers ++# SCTP Configuration (EXPERIMENTAL)  +# -+CONFIG_SPI_ATMEL=y -+# CONFIG_SPI_BITBANG is not set ++# CONFIG_IP_SCTP is not set  +  +# -+# SPI Protocol Masters ++# TIPC Configuration (EXPERIMENTAL)  +# -+# 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 ++# CONFIG_TIPC is not set ++# CONFIG_ATM is not set ++# CONFIG_BRIDGE is not set ++# CONFIG_VLAN_8021Q is not set ++# CONFIG_DECNET is not set ++# CONFIG_LLC2 is not set ++# CONFIG_IPX is not set ++# CONFIG_ATALK is not set ++# CONFIG_X25 is not set ++# CONFIG_LAPB is not set ++# CONFIG_ECONET is not set ++# CONFIG_WAN_ROUTER is not set  +  +# -+# Frame buffer hardware drivers ++# QoS and/or fair queueing  +# -+# 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 ++# CONFIG_NET_SCHED is not set  +  +# -+# Advanced Linux Sound Architecture ++# Network testing  +# -+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 ++# CONFIG_NET_PKTGEN is not set ++# CONFIG_HAMRADIO is not set ++# CONFIG_IRDA is not set ++# CONFIG_BT is not set ++# CONFIG_IEEE80211 is not set  +  +# -+# Generic devices ++# Device Drivers  +# -+# 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 ++# Generic Driver Options  +# -+CONFIG_SND_AT73C213=m -+CONFIG_SND_AT73C213_TARGET_BITRATE=48000 ++CONFIG_STANDALONE=y ++CONFIG_PREVENT_FIRMWARE_BUILD=y ++# CONFIG_FW_LOADER is not set ++# CONFIG_DEBUG_DRIVER is not set ++# CONFIG_SYS_HYPERVISOR is not set  +  +# -+# System on Chip audio support ++# Connector - unified userspace <-> kernelspace linker  +# -+# CONFIG_SND_SOC is not set ++# CONFIG_CONNECTOR is not set  +  +# -+# Open Sound System ++# Memory Technology Devices (MTD)  +# -+# CONFIG_SOUND_PRIME is not set ++CONFIG_MTD=y ++# CONFIG_MTD_DEBUG is not set ++CONFIG_MTD_CONCAT=y ++CONFIG_MTD_PARTITIONS=y ++# CONFIG_MTD_REDBOOT_PARTS is not set ++CONFIG_MTD_CMDLINE_PARTS=y ++# CONFIG_MTD_AFS_PARTS is not set  +  +# -+# HID Devices ++# User Modules And Translation Layers  +# -+# 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 ++CONFIG_MTD_CHAR=y ++CONFIG_MTD_BLKDEVS=y ++CONFIG_MTD_BLOCK=y ++# CONFIG_FTL is not set ++# CONFIG_NFTL is not set ++# CONFIG_INFTL is not set ++# CONFIG_RFD_FTL is not set ++# CONFIG_SSFDC is not set  +  +# -+# MMC/SD Card Drivers ++# RAM/ROM/Flash chip drivers  +# -+CONFIG_MMC_BLOCK=y ++CONFIG_MTD_CFI=y ++# CONFIG_MTD_JEDECPROBE is not set ++CONFIG_MTD_GEN_PROBE=y ++# CONFIG_MTD_CFI_ADV_OPTIONS is not set ++CONFIG_MTD_MAP_BANK_WIDTH_1=y ++CONFIG_MTD_MAP_BANK_WIDTH_2=y ++CONFIG_MTD_MAP_BANK_WIDTH_4=y ++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set ++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set ++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set ++CONFIG_MTD_CFI_I1=y ++CONFIG_MTD_CFI_I2=y ++# CONFIG_MTD_CFI_I4 is not set ++# CONFIG_MTD_CFI_I8 is not set ++# CONFIG_MTD_CFI_INTELEXT is not set ++# CONFIG_MTD_CFI_AMDSTD is not set ++# CONFIG_MTD_CFI_STAA is not set ++# CONFIG_MTD_RAM is not set ++# CONFIG_MTD_ROM is not set ++# CONFIG_MTD_ABSENT is not set ++# CONFIG_MTD_OBSOLETE_CHIPS is not set  +  +# -+# MMC/SD Host Controller Drivers ++# Mapping drivers for chip access  +# -+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 ++CONFIG_MTD_COMPLEX_MAPPINGS=y ++# CONFIG_MTD_PHYSMAP is not set ++# CONFIG_MTD_ARM_INTEGRATOR is not set ++# CONFIG_MTD_PLATRAM is not set  +  +# -+# RTC interfaces ++# Self-contained MTD device drivers  +# -+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 ++CONFIG_MTD_DATAFLASH=y ++# CONFIG_MTD_M25P80 is not set ++# CONFIG_MTD_SLRAM is not set ++# CONFIG_MTD_PHRAM is not set ++# CONFIG_MTD_MTDRAM is not set ++# CONFIG_MTD_BLOCK2MTD is not set  +  +# -+# I2C RTC drivers ++# Disk-On-Chip Device 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 ++# CONFIG_MTD_DOC2000 is not set ++# CONFIG_MTD_DOC2001 is not set ++# CONFIG_MTD_DOC2001PLUS is not set  +  +# -+# SPI RTC drivers ++# NAND Flash Device Drivers  +# -+# CONFIG_RTC_DRV_RS5C348 is not set -+# CONFIG_RTC_DRV_MAX6902 is not set ++# CONFIG_MTD_NAND is not set  +  +# -+# Platform RTC drivers ++# OneNAND Flash Device 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 ++# CONFIG_MTD_ONENAND is not set  +  +# -+# on-CPU RTC drivers ++# Parallel port support  +# -+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; -+}; ++# CONFIG_PARPORT is not set  + -+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); ++# ++# Plug and Play support ++#  + -+	BUG_ON(channel >= DMAC_NR_CHANNELS -+	       || dmac->channel[channel].state != CH_STATE_ALLOCATED); ++# ++# Block devices ++# ++# CONFIG_BLK_DEV_COW_COMMON is not set ++# CONFIG_BLK_DEV_LOOP is not set ++# CONFIG_BLK_DEV_NBD is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=8192 ++CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 ++CONFIG_BLK_DEV_INITRD=y ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set  + -+	dmac->channel[channel].state = CH_STATE_FREE; -+} ++# ++# SCSI device support ++# ++# CONFIG_RAID_ATTRS is not set ++# CONFIG_SCSI is not set ++# CONFIG_SCSI_NETLINK is not set  + -+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; ++# ++# Serial ATA (prod) and Parallel ATA (experimental) drivers ++# ++# CONFIG_ATA is not set  + -+	block = kmalloc(nr_blocks * sizeof(*block), -+			GFP_KERNEL); -+	if (unlikely(!block)) -+		return NULL; ++# ++# Multi-device support (RAID and LVM) ++# ++# CONFIG_MD is not set  + -+	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; -+	} ++# ++# Fusion MPT device support ++# ++# CONFIG_FUSION is not set  + -+	return block; ++# ++# IEEE 1394 (FireWire) support ++#  + -+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; -+} ++# ++# I2O device support ++#  + -+static void cleanup_channel(struct dw_dma_controller *dmac, -+			    struct dw_dma_channel *chan) -+{ -+	unsigned int i; ++# ++# Network device support ++# ++CONFIG_NETDEVICES=y ++# CONFIG_DUMMY is not set ++# CONFIG_BONDING is not set ++# CONFIG_EQUALIZER is not set ++# CONFIG_TUN is not set  + -+	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); -+	} ++# ++# PHY device support ++# ++# CONFIG_PHYLIB is not set  + -+	chan->state = CH_STATE_ALLOCATED; -+} ++# ++# Ethernet (10 or 100Mbit) ++# ++CONFIG_NET_ETHERNET=y ++CONFIG_MII=y ++CONFIG_MACB=y ++# CONFIG_SMC91X is not set ++# CONFIG_DM9000 is not set  + -+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; ++# ++# Ethernet (1000 Mbit) ++#  + -+	spin_lock_irqsave(&dmac->lock, flags); ++# ++# Ethernet (10000 Mbit) ++#  + -+	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; -+	} ++# ++# Token Ring devices ++#  + -+	chan = &dmac->channel[req->req.channel]; -+	chan->state = CH_STATE_BUSY; -+	chan->req_sg = req; -+	chan->is_cyclic = 0; ++# ++# Wireless LAN (non-hamradio) ++# ++# CONFIG_NET_RADIO is not set  + -+	/* -+	 * 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); ++# ++# Wan interfaces ++# ++# CONFIG_WAN is not set ++# CONFIG_PPP is not set ++# CONFIG_SLIP is not set ++# CONFIG_SHAPER is not set ++# CONFIG_NETCONSOLE is not set ++# CONFIG_NETPOLL is not set ++# CONFIG_NET_POLL_CONTROLLER is not set  + -+	/* -+	 * 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); ++# ++# ISDN subsystem ++# ++# CONFIG_ISDN is not set  + -+	BUG_ON(nr_blocks == 0); -+	chan->nr_blocks = nr_blocks; ++# ++# Input device support ++# ++CONFIG_INPUT=y ++# CONFIG_INPUT_FF_MEMLESS is not set  + -+	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; ++# ++# Userland interfaces ++# ++CONFIG_INPUT_MOUSEDEV=y ++# CONFIG_INPUT_MOUSEDEV_PSAUX is not set ++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  + -+	case DMA_DIR_PERIPH_TO_MEM: -+		direction = DMA_FROM_DEVICE; -+		cfghi = req->periph_id << (39 - 32); -+		break; -+	default: -+		goto out_unclaim_channel; -+	} ++# ++# Input Device Drivers ++# ++# CONFIG_INPUT_KEYBOARD is not set ++# CONFIG_INPUT_MOUSE is not set ++# CONFIG_INPUT_JOYSTICK is not set ++# CONFIG_INPUT_TOUCHSCREEN is not set ++# CONFIG_INPUT_MISC is not set  + -+        chan->direction = direction; ++# ++# Hardware I/O ports ++# ++# CONFIG_SERIO is not set ++# CONFIG_GAMEPORT is not set  + -+	dmac_chan_writel_hi(dmac, req->req.channel, CFG, cfghi); -+	dmac_chan_writel_lo(dmac, req->req.channel, CFG, cfglo); ++# ++# Character devices ++# ++CONFIG_VT=y ++CONFIG_VT_CONSOLE=y ++CONFIG_HW_CONSOLE=y ++# CONFIG_VT_HW_CONSOLE_BINDING is not set ++# CONFIG_SERIAL_NONSTANDARD is not set  + -+	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 ++# ++# Serial drivers ++# ++# CONFIG_SERIAL_8250 is not set  + -+	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; ++# ++# Non-8250 serial port support ++# ++CONFIG_SERIAL_ATMEL=y ++CONFIG_SERIAL_ATMEL_CONSOLE=y ++# CONFIG_SERIAL_ATMEL_TTYAT is not set ++CONFIG_SERIAL_CORE=y ++CONFIG_SERIAL_CORE_CONSOLE=y ++CONFIG_UNIX98_PTYS=y ++CONFIG_LEGACY_PTYS=y ++CONFIG_LEGACY_PTY_COUNT=256  + -+		ret = -ENOMEM; -+		chan->block = allocate_blocks(dmac, nr_blocks); -+		if (!chan->block) -+			goto out_unclaim_channel; ++# ++# IPMI ++# ++# CONFIG_IPMI_HANDLER is not set  + -+		if (direction == DMA_TO_DEVICE) -+			ctllo |= 1 << 28 | 1 << 27 | 2 << 7; -+		else -+			ctllo |= 1 << 28 | 1 << 27 | 2 << 9; ++# ++# Watchdog Cards ++# ++# CONFIG_WATCHDOG is not set ++# CONFIG_HW_RANDOM is not set ++# CONFIG_NVRAM is not set ++# CONFIG_DTLK is not set ++# CONFIG_R3964 is not set ++# CONFIG_RAW_DRIVER is not set  + -+		/* -+		 * 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; ++# ++# TPM devices ++# ++# CONFIG_TCG_TPM is not set  + -+			offset += block_size; -+			if (offset > req->sg[j].length) { -+				j++; -+				offset = 0; -+			} -+		} ++# ++# I2C support ++# ++# CONFIG_I2C is not set  + -+		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); ++# ++# SPI support ++# ++CONFIG_SPI=y ++# CONFIG_SPI_DEBUG is not set ++CONFIG_SPI_MASTER=y  + -+		/* -+		 * 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); -+	} ++# ++# SPI Master Controller Drivers ++# ++CONFIG_SPI_ATMEL=y ++# CONFIG_SPI_BITBANG is not set  + -+	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); ++# ++# SPI Protocol Masters ++#  + -+	return 0; ++# ++# Dallas's 1-wire bus ++# ++# CONFIG_W1 is not set  + -+out_unclaim_channel: -+	chan->state = CH_STATE_ALLOCATED; -+	return ret; -+} ++# ++# Hardware Monitoring support ++# ++# CONFIG_HWMON is not set ++# CONFIG_HWMON_VID is not set  + -+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; ++# ++# Misc devices ++# ++# CONFIG_TIFM_CORE is not set  + -+	spin_lock_irqsave(&dmac->lock, flags); ++# ++# LED devices ++# ++# CONFIG_NEW_LEDS is not set  + -+        block_size = (req->buffer_size/req->periods) >> req->width; ++# ++# LED drivers ++#  + -+	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; -+	} ++# ++# LED Triggers ++#  + -+	chan = &dmac->channel[req->req.channel]; -+	chan->state = CH_STATE_BUSY; -+	chan->is_cyclic = 1; -+        chan->req_cyclic = req; ++# ++# Multimedia devices ++# ++# CONFIG_VIDEO_DEV is not set  + -+	/* -+	 * 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); ++# ++# Digital Video Broadcasting Devices ++# ++# CONFIG_DVB is not set  + -+	/* -+          Setup -+	 */ -+	BUG_ON(req->buffer_size % req->periods); -+	/* printk(KERN_INFO "block_size = %lu, periods = %u\n", block_size, req->periods); */ ++# ++# Graphics support ++# ++# CONFIG_FIRMWARE_EDID is not set ++# CONFIG_FB is not set  + -+	chan->nr_blocks = req->periods; ++# ++# Console display driver support ++# ++# CONFIG_VGA_CONSOLE is not set ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set  + -+	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; ++# ++# Sound ++# ++# CONFIG_SOUND is not set  + -+	case DMA_DIR_PERIPH_TO_MEM: -+		direction = DMA_FROM_DEVICE; -+		cfghi = req->periph_id << (39 - 32); -+		break; -+	default: -+		goto out_unclaim_channel; -+	} ++# ++# HID Devices ++# ++# CONFIG_HID is not set  + -+        chan->direction = direction; ++# ++# USB support ++# ++CONFIG_USB_ARCH_HAS_HCD=y ++CONFIG_USB_ARCH_HAS_OHCI=y ++# CONFIG_USB_ARCH_HAS_EHCI is not set ++# CONFIG_USB is not set  + -+	dmac_chan_writel_hi(dmac, req->req.channel, CFG, cfghi); -+	dmac_chan_writel_lo(dmac, req->req.channel, CFG, cfglo); ++# ++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' ++#  + -+	ctlhi = block_size; -+	ctllo = ((req->direction << 20) -+		 | (req->width << 4) | (req->width << 1) -+		 | (1 << 0));		 // interrupt enable ++# ++# USB Gadget Support ++# ++# CONFIG_USB_GADGET is not set  + -+        { -+		struct dw_dma_lli *lli = NULL, *lli_prev = NULL; ++# ++# MMC/SD Card support ++# ++# CONFIG_MMC is not set  + -+		ret = -ENOMEM; -+		chan->block = allocate_blocks(dmac, req->periods); -+		if (!chan->block) -+			goto out_unclaim_channel; ++# ++# Real Time Clock ++# ++CONFIG_RTC_LIB=y ++# CONFIG_RTC_CLASS is not set  + -+		if (direction == DMA_TO_DEVICE) -+			ctllo |= 1 << 28 | 1 << 27 | 2 << 7; -+		else -+			ctllo |= 1 << 28 | 1 << 27 | 2 << 9; ++# ++# File systems ++# ++CONFIG_EXT2_FS=y ++# CONFIG_EXT2_FS_XATTR is not set ++# CONFIG_EXT2_FS_XIP is not set ++CONFIG_EXT3_FS=y ++CONFIG_EXT3_FS_XATTR=y ++# CONFIG_EXT3_FS_POSIX_ACL is not set ++# CONFIG_EXT3_FS_SECURITY is not set ++# CONFIG_EXT4DEV_FS is not set ++CONFIG_JBD=y ++# CONFIG_JBD_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_FS_POSIX_ACL is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_GFS2_FS is not set ++# CONFIG_OCFS2_FS is not set ++# CONFIG_MINIX_FS is not set ++# CONFIG_ROMFS_FS is not set ++CONFIG_INOTIFY=y ++CONFIG_INOTIFY_USER=y ++# CONFIG_QUOTA is not set ++CONFIG_DNOTIFY=y ++# CONFIG_AUTOFS_FS is not set ++CONFIG_AUTOFS4_FS=y ++# CONFIG_FUSE_FS is not set  + -+		/* -+		 * 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; ++# ++# CD-ROM/DVD Filesystems ++# ++# CONFIG_ISO9660_FS is not set ++# CONFIG_UDF_FS is not set  + -+		/*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); */ ++# ++# DOS/FAT/NT Filesystems ++# ++CONFIG_FAT_FS=y ++# CONFIG_MSDOS_FS is not set ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++# CONFIG_NTFS_FS is not set  + -+		/* -+		 * 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); -+	} ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_PROC_SYSCTL=y ++CONFIG_SYSFS=y ++CONFIG_TMPFS=y ++# CONFIG_TMPFS_POSIX_ACL is not set ++# CONFIG_HUGETLB_PAGE is not set ++CONFIG_RAMFS=y ++# CONFIG_CONFIGFS_FS is not set  + -+	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); ++# ++# Miscellaneous filesystems ++# ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_FS is not set ++# CONFIG_HFS_FS is not set ++# CONFIG_HFSPLUS_FS is not set ++# CONFIG_BEFS_FS is not set ++# CONFIG_BFS_FS is not set ++# CONFIG_EFS_FS is not set ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_SUMMARY is not set ++# CONFIG_JFFS2_FS_XATTR is not set ++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set ++CONFIG_JFFS2_ZLIB=y ++CONFIG_JFFS2_RTIME=y ++# CONFIG_JFFS2_RUBIN is not set ++CONFIG_CRAMFS=y ++# CONFIG_VXFS_FS is not set ++# CONFIG_HPFS_FS is not set ++# CONFIG_QNX4FS_FS is not set ++# CONFIG_SYSV_FS is not set ++# CONFIG_UFS_FS is not set  + -+	return 0; ++# ++# Network File Systems ++# ++CONFIG_NFS_FS=y ++CONFIG_NFS_V3=y ++# CONFIG_NFS_V3_ACL is not set ++# CONFIG_NFS_V4 is not set ++# CONFIG_NFS_DIRECTIO is not set ++# CONFIG_NFSD is not set ++CONFIG_ROOT_NFS=y ++CONFIG_LOCKD=y ++CONFIG_LOCKD_V4=y ++CONFIG_NFS_COMMON=y ++CONFIG_SUNRPC=y ++# CONFIG_RPCSEC_GSS_KRB5 is not set ++# CONFIG_RPCSEC_GSS_SPKM3 is not set ++# CONFIG_SMB_FS is not set ++# CONFIG_CIFS is not set ++# CONFIG_NCP_FS is not set ++# CONFIG_CODA_FS is not set ++# CONFIG_AFS_FS is not set ++# CONFIG_9P_FS is not set  + -+out_unclaim_channel: -+	chan->state = CH_STATE_ALLOCATED; -+	return ret; -+} ++# ++# Partition Types ++# ++# CONFIG_PARTITION_ADVANCED is not set ++CONFIG_MSDOS_PARTITION=y  + -+static int dmac_start_request(struct dma_controller *_dmac, -+			      unsigned int channel) -+{ -+	struct dw_dma_controller *dmac = to_dw_dmac(_dmac); ++# ++# Native Language Support ++# ++CONFIG_NLS=y ++CONFIG_NLS_DEFAULT="iso8859-1" ++CONFIG_NLS_CODEPAGE_437=y ++# CONFIG_NLS_CODEPAGE_737 is not set ++# CONFIG_NLS_CODEPAGE_775 is not set ++CONFIG_NLS_CODEPAGE_850=y ++# CONFIG_NLS_CODEPAGE_852 is not set ++# CONFIG_NLS_CODEPAGE_855 is not set ++# CONFIG_NLS_CODEPAGE_857 is not set ++# CONFIG_NLS_CODEPAGE_860 is not set ++# CONFIG_NLS_CODEPAGE_861 is not set ++# CONFIG_NLS_CODEPAGE_862 is not set ++# CONFIG_NLS_CODEPAGE_863 is not set ++# CONFIG_NLS_CODEPAGE_864 is not set ++# CONFIG_NLS_CODEPAGE_865 is not set ++# CONFIG_NLS_CODEPAGE_866 is not set ++# CONFIG_NLS_CODEPAGE_869 is not set ++# CONFIG_NLS_CODEPAGE_936 is not set ++# CONFIG_NLS_CODEPAGE_950 is not set ++# CONFIG_NLS_CODEPAGE_932 is not set ++# CONFIG_NLS_CODEPAGE_949 is not set ++# CONFIG_NLS_CODEPAGE_874 is not set ++# CONFIG_NLS_ISO8859_8 is not set ++# CONFIG_NLS_CODEPAGE_1250 is not set ++# CONFIG_NLS_CODEPAGE_1251 is not set ++# CONFIG_NLS_ASCII is not set ++CONFIG_NLS_ISO8859_1=y ++# CONFIG_NLS_ISO8859_2 is not set ++# CONFIG_NLS_ISO8859_3 is not set ++# CONFIG_NLS_ISO8859_4 is not set ++# CONFIG_NLS_ISO8859_5 is not set ++# CONFIG_NLS_ISO8859_6 is not set ++# CONFIG_NLS_ISO8859_7 is not set ++# CONFIG_NLS_ISO8859_9 is not set ++# CONFIG_NLS_ISO8859_13 is not set ++# CONFIG_NLS_ISO8859_14 is not set ++# CONFIG_NLS_ISO8859_15 is not set ++# CONFIG_NLS_KOI8_R is not set ++# CONFIG_NLS_KOI8_U is not set ++# CONFIG_NLS_UTF8 is not set  + -+	BUG_ON(channel >= DMAC_NR_CHANNELS); ++# ++# Distributed Lock Manager ++# ++# CONFIG_DLM is not set  + -+	set_channel_bit(dmac, CH_EN, channel); ++# ++# Profiling support ++# ++# CONFIG_PROFILING is not set  + -+	return 0; -+} ++# ++# Kernel hacking ++# ++# CONFIG_PRINTK_TIME is not set ++CONFIG_ENABLE_MUST_CHECK=y ++# CONFIG_MAGIC_SYSRQ is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++CONFIG_DEBUG_KERNEL=y ++CONFIG_LOG_BUF_SHIFT=14 ++CONFIG_DETECT_SOFTLOCKUP=y ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_DEBUG_SLAB is not set ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_RT_MUTEX_TESTER is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_RWSEMS is not set ++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_DEBUG_VM is not set ++# CONFIG_DEBUG_LIST is not set ++CONFIG_FRAME_POINTER=y ++CONFIG_FORCED_INLINING=y ++# CONFIG_RCU_TORTURE_TEST is not set ++CONFIG_DEBUG_USER=y ++# CONFIG_DEBUG_ERRORS is not set ++CONFIG_DEBUG_LL=y ++# CONFIG_DEBUG_ICEDCC is not set  + -+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; ++# ++# Security options ++# ++# CONFIG_KEYS is not set ++# CONFIG_SECURITY is not set  + -+	BUG_ON(channel >= DMAC_NR_CHANNELS); ++# ++# Cryptographic options ++# ++# CONFIG_CRYPTO is not set  + -+        chan = &dmac->channel[channel]; ++# ++# Library routines ++# ++CONFIG_BITREVERSE=y ++# CONFIG_CRC_CCITT is not set ++# CONFIG_CRC16 is not set ++CONFIG_CRC32=y ++# CONFIG_LIBCRC32C is not set ++CONFIG_ZLIB_INFLATE=y ++CONFIG_ZLIB_DEFLATE=y ++CONFIG_PLIST=y ++CONFIG_IOMAP_COPY=y +Index: linux-2.6.22.1/arch/arm/configs/kb9202_defconfig +=================================================================== +--- linux-2.6.22.1/arch/arm/configs/kb9202_defconfig	(revision 1) ++++ linux-2.6.22.1/arch/arm/configs/kb9202_defconfig	(arbetskopia) +@@ -1,19 +1,31 @@ + # + # Automatically generated make config: don't edit +-# Linux kernel version: 2.6.13-rc2 +-# Sun Aug 14 19:26:59 2005 ++# Linux kernel version: 2.6.21 ++# Mon May  7 11:43:14 2007 + # + CONFIG_ARM=y ++CONFIG_SYS_SUPPORTS_APM_EMULATION=y ++CONFIG_GENERIC_GPIO=y ++# CONFIG_GENERIC_TIME is not set + CONFIG_MMU=y +-CONFIG_UID16=y ++# CONFIG_NO_IOPORT is not set ++CONFIG_GENERIC_HARDIRQS=y ++CONFIG_TRACE_IRQFLAGS_SUPPORT=y ++CONFIG_HARDIRQS_SW_RESEND=y ++CONFIG_GENERIC_IRQ_PROBE=y + CONFIG_RWSEM_GENERIC_SPINLOCK=y ++# CONFIG_ARCH_HAS_ILOG2_U32 is not set ++# CONFIG_ARCH_HAS_ILOG2_U64 is not set ++CONFIG_GENERIC_HWEIGHT=y + CONFIG_GENERIC_CALIBRATE_DELAY=y ++CONFIG_ZONE_DMA=y ++CONFIG_VECTORS_BASE=0xffff0000 ++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +  + # + # Code maturity level options + # +-# CONFIG_EXPERIMENTAL is not set +-CONFIG_CLEAN_COMPILE=y ++CONFIG_EXPERIMENTAL=y + CONFIG_BROKEN_ON_SMP=y + CONFIG_INIT_ENV_ARG_LIMIT=32 +  +@@ -21,54 +33,103 @@ + # General setup + # + CONFIG_LOCALVERSION="" +-# CONFIG_SWAP is not set +-# CONFIG_SYSVIPC is not set +-# CONFIG_BSD_PROCESS_ACCT is not set ++CONFIG_LOCALVERSION_AUTO=y ++CONFIG_SWAP=y ++CONFIG_SYSVIPC=y ++# CONFIG_IPC_NS is not set ++CONFIG_SYSVIPC_SYSCTL=y ++CONFIG_POSIX_MQUEUE=y ++CONFIG_BSD_PROCESS_ACCT=y ++# CONFIG_BSD_PROCESS_ACCT_V3 is not set ++# CONFIG_TASKSTATS is not set ++# CONFIG_UTS_NS is not set ++CONFIG_AUDIT=y ++CONFIG_IKCONFIG=y ++CONFIG_IKCONFIG_PROC=y ++CONFIG_SYSFS_DEPRECATED=y ++# CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + CONFIG_SYSCTL=y +-# CONFIG_AUDIT is not set +-CONFIG_HOTPLUG=y +-# CONFIG_KOBJECT_UEVENT is not set +-# CONFIG_IKCONFIG is not set + # CONFIG_EMBEDDED is not set ++CONFIG_UID16=y ++CONFIG_SYSCTL_SYSCALL=y + CONFIG_KALLSYMS=y + # CONFIG_KALLSYMS_ALL is not set +-# CONFIG_KALLSYMS_EXTRA_PASS is not set ++CONFIG_KALLSYMS_EXTRA_PASS=y ++CONFIG_HOTPLUG=y + CONFIG_PRINTK=y + CONFIG_BUG=y ++CONFIG_ELF_CORE=y + CONFIG_BASE_FULL=y + CONFIG_FUTEX=y + CONFIG_EPOLL=y +-CONFIG_CC_OPTIMIZE_FOR_SIZE=y + CONFIG_SHMEM=y +-CONFIG_CC_ALIGN_FUNCTIONS=0 +-CONFIG_CC_ALIGN_LABELS=0 +-CONFIG_CC_ALIGN_LOOPS=0 +-CONFIG_CC_ALIGN_JUMPS=0 ++CONFIG_SLAB=y ++CONFIG_VM_EVENT_COUNTERS=y ++CONFIG_RT_MUTEXES=y + # CONFIG_TINY_SHMEM is not set + CONFIG_BASE_SMALL=0 ++# CONFIG_SLOB is not set +  + # + # Loadable module support + # + CONFIG_MODULES=y + CONFIG_MODULE_UNLOAD=y +-CONFIG_OBSOLETE_MODPARM=y +-# CONFIG_MODULE_SRCVERSION_ALL is not set ++# CONFIG_MODULE_FORCE_UNLOAD is not set ++CONFIG_MODVERSIONS=y ++CONFIG_MODULE_SRCVERSION_ALL=y + CONFIG_KMOD=y +  + # ++# Block layer ++# ++CONFIG_BLOCK=y ++CONFIG_LBD=y ++# CONFIG_BLK_DEV_IO_TRACE is not set ++# CONFIG_LSF is not set  + -+	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; -+	} ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_AS=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++# CONFIG_DEFAULT_AS is not set ++# CONFIG_DEFAULT_DEADLINE is not set ++CONFIG_DEFAULT_CFQ=y ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="cfq"  + ++# + # System Type + # ++# CONFIG_ARCH_AAEC2000 is not set ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_VERSATILE is not set ++CONFIG_ARCH_AT91=y + # CONFIG_ARCH_CLPS7500 is not set + # CONFIG_ARCH_CLPS711X is not set + # CONFIG_ARCH_CO285 is not set + # CONFIG_ARCH_EBSA110 is not set ++# CONFIG_ARCH_EP93XX is not set + # CONFIG_ARCH_FOOTBRIDGE is not set +-# CONFIG_ARCH_INTEGRATOR is not set +-# CONFIG_ARCH_IOP3XX is not set ++# CONFIG_ARCH_NETX is not set ++# CONFIG_ARCH_H720X is not set ++# CONFIG_ARCH_IMX is not set ++# CONFIG_ARCH_IOP32X is not set ++# CONFIG_ARCH_IOP33X is not set ++# CONFIG_ARCH_IOP13XX is not set + # CONFIG_ARCH_IXP4XX is not set + # CONFIG_ARCH_IXP2000 is not set ++# CONFIG_ARCH_IXP23XX is not set + # CONFIG_ARCH_L7200 is not set ++# CONFIG_ARCH_NS9XXX is not set ++# CONFIG_ARCH_PNX4008 is not set + # CONFIG_ARCH_PXA is not set + # CONFIG_ARCH_RPC is not set + # CONFIG_ARCH_SA1100 is not set +@@ -76,34 +137,52 @@ + # CONFIG_ARCH_SHARK is not set + # CONFIG_ARCH_LH7A40X is not set + # CONFIG_ARCH_OMAP is not set +-# CONFIG_ARCH_VERSATILE is not set +-# CONFIG_ARCH_IMX is not set +-# CONFIG_ARCH_H720X is not set +-# CONFIG_ARCH_AAEC2000 is not set +-CONFIG_ARCH_AT91=y  + -+        if (!current_pos) { -+		if (chan->is_cyclic) { -+			current_pos = chan->req_cyclic->buffer_start; -+		} else { -+			current_pos = chan->req_sg->sg->dma_address; -+		} -+	} ++# ++# Atmel AT91 System-on-Chip ++# + CONFIG_ARCH_AT91RM9200=y ++# CONFIG_ARCH_AT91SAM9260 is not set ++# CONFIG_ARCH_AT91SAM9261 is not set ++# CONFIG_ARCH_AT91SAM9263 is not set +  + # +-# AT91RM9200 Implementations ++# AT91RM9200 Board Type + # ++# CONFIG_MACH_ONEARM is not set + # CONFIG_ARCH_AT91RM9200DK is not set + # CONFIG_MACH_AT91RM9200EK is not set + # CONFIG_MACH_CSB337 is not set + # CONFIG_MACH_CSB637 is not set + # CONFIG_MACH_CARMEVA is not set ++# CONFIG_MACH_ATEB9200 is not set + CONFIG_MACH_KB9200=y ++# CONFIG_MACH_KAFA is not set ++# CONFIG_MACH_CHUB is not set +  + # ++# AT91 Board Options ++#  + -+	return current_pos; -+} ++# ++# AT91 Feature Selections ++# ++# CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set ++# CONFIG_ATMEL_TCLIB is not set  + ++# + # Processor Type + # + CONFIG_CPU_32=y + CONFIG_CPU_ARM920T=y +-CONFIG_CPU_32v4=y ++CONFIG_CPU_32v4T=y + CONFIG_CPU_ABRT_EV4T=y + CONFIG_CPU_CACHE_V4WT=y + CONFIG_CPU_CACHE_VIVT=y + CONFIG_CPU_COPY_V4WB=y + CONFIG_CPU_TLB_V4WBI=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y +  + # + # Processor Features +@@ -112,24 +191,44 @@ + # CONFIG_CPU_ICACHE_DISABLE is not set + # CONFIG_CPU_DCACHE_DISABLE is not set + # CONFIG_CPU_DCACHE_WRITETHROUGH is not set ++# CONFIG_OUTER_CACHE is not set +  + # + # Bus support + # +-CONFIG_ISA_DMA_API=y +  + # + # PCCARD (PCMCIA/CardBus) support + # +-# CONFIG_PCCARD is not set ++CONFIG_PCCARD=m ++# CONFIG_PCMCIA_DEBUG is not set ++CONFIG_PCMCIA=m ++CONFIG_PCMCIA_LOAD_CIS=y ++CONFIG_PCMCIA_IOCTL=y +  + # ++# PC-card bridges ++# ++# CONFIG_AT91_CF is not set  + -+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; ++# + # Kernel Features + # ++# CONFIG_PREEMPT is not set + # CONFIG_NO_IDLE_HZ is not set ++CONFIG_HZ=100 ++# CONFIG_AEABI is not set + # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set ++CONFIG_SELECT_MEMORY_MODEL=y ++CONFIG_FLATMEM_MANUAL=y ++# CONFIG_DISCONTIGMEM_MANUAL is not set ++# CONFIG_SPARSEMEM_MANUAL is not set + CONFIG_FLATMEM=y + CONFIG_FLAT_NODE_MEM_MAP=y ++# CONFIG_SPARSEMEM_STATIC is not set ++CONFIG_SPLIT_PTLOCK_CPUS=4096 ++# CONFIG_RESOURCES_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=1 + # CONFIG_LEDS is not set + CONFIG_ALIGNMENT_TRAP=y +  +@@ -138,8 +237,10 @@ + # + CONFIG_ZBOOT_ROM_TEXT=0x10000000 + CONFIG_ZBOOT_ROM_BSS=0x20040000 +-CONFIG_ZBOOT_ROM=y +-CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/ram rw initrd=0x20210000,654933" ++# CONFIG_ZBOOT_ROM is not set ++CONFIG_CMDLINE="noinitrd root=/dev/mtdblock0 rootfstype=jffs2 mem=64M" ++# CONFIG_XIP_KERNEL is not set ++# CONFIG_KEXEC is not set +  + # + # Floating point emulation +@@ -150,6 +251,7 @@ + # + CONFIG_FPE_NWFPE=y + # CONFIG_FPE_NWFPE_XP is not set ++# CONFIG_FPE_FASTFPE is not set +  + # + # Userspace binary formats +@@ -165,6 +267,96 @@ + # CONFIG_PM is not set +  + # ++# Networking ++# ++CONFIG_NET=y  + -+	BUG_ON(channel >= DMAC_NR_CHANNELS); ++# ++# Networking options ++# ++# CONFIG_NETDEBUG is not set ++CONFIG_PACKET=y ++# CONFIG_PACKET_MMAP is not set ++CONFIG_UNIX=y ++# CONFIG_NET_KEY is not set ++CONFIG_INET=y ++CONFIG_IP_MULTICAST=y ++# CONFIG_IP_ADVANCED_ROUTER is not set ++CONFIG_IP_FIB_HASH=y ++CONFIG_IP_PNP=y ++# CONFIG_IP_PNP_DHCP is not set ++# CONFIG_IP_PNP_BOOTP is not set ++# CONFIG_IP_PNP_RARP is not set ++# CONFIG_NET_IPIP is not set ++# CONFIG_NET_IPGRE is not set ++# CONFIG_IP_MROUTE is not set ++# CONFIG_ARPD is not set ++# CONFIG_SYN_COOKIES is not set ++# CONFIG_INET_AH is not set ++# CONFIG_INET_ESP is not set ++# CONFIG_INET_IPCOMP is not set ++# CONFIG_INET_XFRM_TUNNEL is not set ++# CONFIG_INET_TUNNEL is not set ++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set ++# CONFIG_INET_XFRM_MODE_TUNNEL is not set ++# CONFIG_INET_XFRM_MODE_BEET is not set ++# CONFIG_INET_DIAG is not set ++# CONFIG_TCP_CONG_ADVANCED is not set ++CONFIG_TCP_CONG_CUBIC=y ++CONFIG_DEFAULT_TCP_CONG="cubic" ++# CONFIG_TCP_MD5SIG is not set ++# CONFIG_IPV6 is not set ++# CONFIG_INET6_XFRM_TUNNEL is not set ++# CONFIG_INET6_TUNNEL is not set ++# CONFIG_NETWORK_SECMARK is not set ++# CONFIG_NETFILTER is not set  + -+	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)); ++# ++# DCCP Configuration (EXPERIMENTAL) ++# ++# CONFIG_IP_DCCP is not set  + -+	if (chan->state == CH_STATE_BUSY) { -+		clear_channel_bit(dmac, CH_EN, channel); -+		cleanup_channel(dmac, &dmac->channel[channel]); -+	} ++# ++# SCTP Configuration (EXPERIMENTAL) ++# ++CONFIG_IP_SCTP=m ++# CONFIG_SCTP_DBG_MSG is not set ++# CONFIG_SCTP_DBG_OBJCNT is not set ++# CONFIG_SCTP_HMAC_NONE is not set ++# CONFIG_SCTP_HMAC_SHA1 is not set ++CONFIG_SCTP_HMAC_MD5=y  + -+	return 0; -+} ++# ++# TIPC Configuration (EXPERIMENTAL) ++# ++# CONFIG_TIPC is not set ++# CONFIG_ATM is not set ++# CONFIG_BRIDGE is not set ++# CONFIG_VLAN_8021Q is not set ++# CONFIG_DECNET is not set ++# CONFIG_LLC2 is not set ++# CONFIG_IPX is not set ++# CONFIG_ATALK is not set ++# CONFIG_X25 is not set ++# CONFIG_LAPB is not set ++# CONFIG_ECONET is not set ++# CONFIG_WAN_ROUTER is not set  + ++# ++# QoS and/or fair queueing ++# ++# CONFIG_NET_SCHED is not set  + -+static void dmac_block_complete(struct dw_dma_controller *dmac) -+{ -+	struct dw_dma_channel *chan; -+	unsigned long status, chanid; ++# ++# Network testing ++# ++# CONFIG_NET_PKTGEN is not set ++# CONFIG_HAMRADIO is not set ++# CONFIG_IRDA is not set ++# CONFIG_BT is not set ++# CONFIG_IEEE80211 is not set  + -+	status = dmac_readl_lo(dmac, STATUS_BLOCK); ++# + # Device Drivers + # +  +@@ -173,15 +365,97 @@ + # + CONFIG_STANDALONE=y + CONFIG_PREVENT_FIRMWARE_BUILD=y +-# CONFIG_FW_LOADER is not set +-CONFIG_DEBUG_DRIVER=y ++CONFIG_FW_LOADER=y ++# CONFIG_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_SYS_HYPERVISOR is not set +  + # ++# Connector - unified userspace <-> kernelspace linker ++# ++# CONFIG_CONNECTOR is not set  + -+	while (status) { -+		struct dma_request *req; -+		chanid = __ffs(status); -+		chan = &dmac->channel[chanid]; ++# + # Memory Technology Devices (MTD) + # +-# CONFIG_MTD is not set ++CONFIG_MTD=y ++# CONFIG_MTD_DEBUG is not set ++CONFIG_MTD_CONCAT=y ++CONFIG_MTD_PARTITIONS=y ++# CONFIG_MTD_REDBOOT_PARTS is not set ++CONFIG_MTD_CMDLINE_PARTS=y ++# CONFIG_MTD_AFS_PARTS is not set +  + # ++# User Modules And Translation Layers ++# ++CONFIG_MTD_CHAR=y ++CONFIG_MTD_BLKDEVS=y ++CONFIG_MTD_BLOCK=y ++# CONFIG_FTL is not set ++# CONFIG_NFTL is not set ++# CONFIG_INFTL is not set ++# CONFIG_RFD_FTL is not set ++# CONFIG_SSFDC is not set  + -+                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); -+	} -+} ++# ++# RAM/ROM/Flash chip drivers ++# ++# CONFIG_MTD_CFI is not set ++# CONFIG_MTD_JEDECPROBE is not set ++CONFIG_MTD_MAP_BANK_WIDTH_1=y ++CONFIG_MTD_MAP_BANK_WIDTH_2=y ++CONFIG_MTD_MAP_BANK_WIDTH_4=y ++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set ++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set ++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set ++CONFIG_MTD_CFI_I1=y ++CONFIG_MTD_CFI_I2=y ++# CONFIG_MTD_CFI_I4 is not set ++# CONFIG_MTD_CFI_I8 is not set ++# CONFIG_MTD_RAM is not set ++# CONFIG_MTD_ROM is not set ++# CONFIG_MTD_ABSENT is not set ++# CONFIG_MTD_OBSOLETE_CHIPS is not set  + -+static void dmac_xfer_complete(struct dw_dma_controller *dmac) -+{ -+	struct dw_dma_channel *chan; -+	struct dma_request *req; -+	unsigned long status, chanid; ++# ++# Mapping drivers for chip access ++# ++CONFIG_MTD_COMPLEX_MAPPINGS=y ++# CONFIG_MTD_PLATRAM is not set  + -+	status = dmac_readl_lo(dmac, STATUS_XFER); ++# ++# Self-contained MTD device drivers ++# ++# CONFIG_MTD_SLRAM is not set ++# CONFIG_MTD_PHRAM is not set ++# CONFIG_MTD_MTDRAM is not set ++# CONFIG_MTD_BLOCK2MTD is not set  + -+	while (status) { -+		chanid = __ffs(status); -+		chan = &dmac->channel[chanid]; ++# ++# Disk-On-Chip Device Drivers ++# ++# CONFIG_MTD_DOC2000 is not set ++# CONFIG_MTD_DOC2001 is not set ++# CONFIG_MTD_DOC2001PLUS is not set  + -+		dmac_writel_lo(dmac, CLEAR_XFER, 1 << chanid); ++# ++# NAND Flash Device Drivers ++# ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_VERIFY_WRITE is not set ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND_IDS=y ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++CONFIG_MTD_NAND_AT91=y ++# CONFIG_MTD_NAND_NANDSIM is not set  + -+                req = &chan->req_sg->req; -+                BUG_ON(!req); -+                cleanup_channel(dmac, chan); -+                if (req->xfer_complete) -+			req->xfer_complete(req); ++# ++# OneNAND Flash Device Drivers ++# ++# CONFIG_MTD_ONENAND is not set  + -+		status = dmac_readl_lo(dmac, STATUS_XFER); -+	} -+} ++# + # Parallel port support + # + # CONFIG_PARPORT is not set +@@ -189,6 +463,7 @@ + # + # Plug and Play support + # ++# CONFIG_PNPACPI is not set +  + # + # Block devices +@@ -196,28 +471,27 @@ + # CONFIG_BLK_DEV_COW_COMMON is not set + CONFIG_BLK_DEV_LOOP=y + # CONFIG_BLK_DEV_CRYPTOLOOP is not set +-CONFIG_BLK_DEV_NBD=y ++# CONFIG_BLK_DEV_NBD is not set + # CONFIG_BLK_DEV_UB is not set + CONFIG_BLK_DEV_RAM=y + CONFIG_BLK_DEV_RAM_COUNT=16 +-CONFIG_BLK_DEV_RAM_SIZE=4096 +-CONFIG_BLK_DEV_INITRD=y +-CONFIG_INITRAMFS_SOURCE="" ++CONFIG_BLK_DEV_RAM_SIZE=16384 ++CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 + # CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set +  + # +-# IO Schedulers ++# ATA/ATAPI/MFM/RLL support + # +-CONFIG_IOSCHED_NOOP=y +-CONFIG_IOSCHED_AS=y +-CONFIG_IOSCHED_DEADLINE=y +-CONFIG_IOSCHED_CFQ=y +-# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_IDE is not set +  + # + # SCSI device support + # ++# CONFIG_RAID_ATTRS is not set + CONFIG_SCSI=y ++# CONFIG_SCSI_TGT is not set ++# CONFIG_SCSI_NETLINK is not set + CONFIG_SCSI_PROC_FS=y +  + # +@@ -233,24 +507,41 @@ + # + # Some SCSI devices (e.g. CD jukebox) support multiple LUNs + # +-# CONFIG_SCSI_MULTI_LUN is not set +-# CONFIG_SCSI_CONSTANTS is not set +-# CONFIG_SCSI_LOGGING is not set ++CONFIG_SCSI_MULTI_LUN=y ++CONFIG_SCSI_CONSTANTS=y ++CONFIG_SCSI_LOGGING=y ++# CONFIG_SCSI_SCAN_ASYNC is not set +  + # +-# SCSI Transport Attributes ++# SCSI Transports + # +-# CONFIG_SCSI_SPI_ATTRS is not set ++CONFIG_SCSI_SPI_ATTRS=m + # CONFIG_SCSI_FC_ATTRS is not set + # CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set +  + # + # SCSI low-level drivers + # +-# CONFIG_SCSI_SATA is not set ++# CONFIG_ISCSI_TCP is not set + # CONFIG_SCSI_DEBUG is not set +  + # ++# PCMCIA SCSI adapter support ++# ++# CONFIG_PCMCIA_AHA152X is not set ++# CONFIG_PCMCIA_FDOMAIN is not set ++# CONFIG_PCMCIA_NINJA_SCSI is not set ++# CONFIG_PCMCIA_QLOGIC is not set ++# CONFIG_PCMCIA_SYM53C500 is not set  + -+static void dmac_error(struct dw_dma_controller *dmac) -+{ -+	struct dw_dma_channel *chan; -+	unsigned long status, chanid; ++# ++# Serial ATA (prod) and Parallel ATA (experimental) drivers ++# ++# CONFIG_ATA is not set  + -+	status = dmac_readl_lo(dmac, STATUS_ERROR); ++# + # Multi-device support (RAID and LVM) + # + # CONFIG_MD is not set +@@ -269,61 +560,8 @@ + # +  + # +-# Networking support ++# Network device support + # +-CONFIG_NET=y +- +-# +-# Networking options +-# +-CONFIG_PACKET=y +-# CONFIG_PACKET_MMAP is not set +-CONFIG_UNIX=y +-# CONFIG_NET_KEY is not set +-CONFIG_INET=y +-CONFIG_IP_MULTICAST=y +-# CONFIG_IP_ADVANCED_ROUTER is not set +-CONFIG_IP_FIB_HASH=y +-CONFIG_IP_PNP=y +-CONFIG_IP_PNP_DHCP=y +-# CONFIG_IP_PNP_BOOTP is not set +-# CONFIG_IP_PNP_RARP is not set +-# CONFIG_NET_IPIP is not set +-# CONFIG_NET_IPGRE is not set +-# CONFIG_IP_MROUTE is not set +-# CONFIG_SYN_COOKIES is not set +-# CONFIG_INET_AH is not set +-# CONFIG_INET_ESP is not set +-# CONFIG_INET_IPCOMP is not set +-# CONFIG_INET_TUNNEL is not set +-# CONFIG_IP_TCPDIAG is not set +-# CONFIG_IP_TCPDIAG_IPV6 is not set +-# CONFIG_TCP_CONG_ADVANCED is not set +-CONFIG_TCP_CONG_BIC=y +-# CONFIG_IPV6 is not set +-# CONFIG_NETFILTER is not set +-# CONFIG_BRIDGE is not set +-# CONFIG_VLAN_8021Q is not set +-# CONFIG_DECNET is not set +-# CONFIG_LLC2 is not set +-# CONFIG_IPX is not set +-# CONFIG_ATALK is not set +- +-# +-# QoS and/or fair queueing +-# +-# CONFIG_NET_SCHED is not set +-# CONFIG_NET_CLS_ROUTE is not set +- +-# +-# Network testing +-# +-# CONFIG_NET_PKTGEN is not set +-# CONFIG_NETPOLL is not set +-# CONFIG_NET_POLL_CONTROLLER is not set +-# CONFIG_HAMRADIO is not set +-# CONFIG_IRDA is not set +-# CONFIG_BT is not set + CONFIG_NETDEVICES=y + # CONFIG_DUMMY is not set + # CONFIG_BONDING is not set +@@ -331,6 +569,11 @@ + # CONFIG_TUN is not set +  + # ++# PHY device support ++# ++# CONFIG_PHYLIB is not set  + -+	while (status) { -+		struct dma_request *req; ++# + # Ethernet (10 or 100Mbit) + # + CONFIG_NET_ETHERNET=y +@@ -357,11 +600,20 @@ + # CONFIG_NET_RADIO is not set +  + # ++# PCMCIA network device support ++# ++# CONFIG_NET_PCMCIA is not set  + -+		chanid = __ffs(status); -+		chan = &dmac->channel[chanid]; ++# + # Wan interfaces + # + # CONFIG_WAN is not set + # CONFIG_PPP is not set + # CONFIG_SLIP is not set ++# CONFIG_SHAPER is not set ++# CONFIG_NETCONSOLE is not set ++# CONFIG_NETPOLL is not set ++# CONFIG_NET_POLL_CONTROLLER is not set +  + # + # ISDN subsystem +@@ -372,6 +624,7 @@ + # Input device support + # + CONFIG_INPUT=y ++# CONFIG_INPUT_FF_MEMLESS is not set +  + # + # Userland interfaces +@@ -397,9 +650,7 @@ + # + # Hardware I/O ports + # +-CONFIG_SERIO=y +-# CONFIG_SERIO_SERPORT is not set +-# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO is not set + # CONFIG_GAMEPORT is not set +  + # +@@ -408,6 +659,7 @@ + CONFIG_VT=y + CONFIG_VT_CONSOLE=y + CONFIG_HW_CONSOLE=y ++# CONFIG_VT_HW_CONSOLE_BINDING is not set + # CONFIG_SERIAL_NONSTANDARD is not set +  + # +@@ -420,11 +672,11 @@ + # + CONFIG_SERIAL_ATMEL=y + CONFIG_SERIAL_ATMEL_CONSOLE=y ++# CONFIG_SERIAL_ATMEL_TTYAT is not set + CONFIG_SERIAL_CORE=y + CONFIG_SERIAL_CORE_CONSOLE=y + CONFIG_UNIX98_PTYS=y +-CONFIG_LEGACY_PTYS=y +-CONFIG_LEGACY_PTY_COUNT=256 ++# CONFIG_LEGACY_PTYS is not set +  + # + # IPMI +@@ -435,21 +687,23 @@ + # Watchdog Cards + # + # CONFIG_WATCHDOG is not set ++# CONFIG_HW_RANDOM is not set + # CONFIG_NVRAM is not set +-# CONFIG_RTC is not set +-# CONFIG_AT91RM9200_RTC is not set + # CONFIG_DTLK is not set + # CONFIG_R3964 is not set +  + # +-# Ftape, the floppy tape device driver ++# PCMCIA character devices + # ++# CONFIG_SYNCLINK_CS is not set ++# CONFIG_CARDMAN_4000 is not set ++# CONFIG_CARDMAN_4040 is not set + # CONFIG_RAW_DRIVER is not set +  + # + # TPM devices + # +-# CONFIG_AT91_SPI is not set ++# CONFIG_TCG_TPM is not set +  + # + # I2C support +@@ -457,10 +711,50 @@ + # CONFIG_I2C is not set +  + # ++# SPI support ++# ++# CONFIG_SPI is not set ++# CONFIG_SPI_MASTER is not set  + -+		dmac_writel_lo(dmac, CLEAR_ERROR, 1 << chanid); -+		clear_channel_bit(dmac, CH_EN, chanid); ++# ++# Dallas's 1-wire bus ++# ++# CONFIG_W1 is not set  + -+                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; -+                } ++# ++# Hardware Monitoring support ++# ++CONFIG_HWMON=y ++# CONFIG_HWMON_VID is not set ++# CONFIG_SENSORS_ABITUGURU is not set ++# CONFIG_SENSORS_F71805F is not set ++# CONFIG_SENSORS_PC87427 is not set ++# CONFIG_SENSORS_VT1211 is not set ++CONFIG_HWMON_DEBUG_CHIP=y  + -+		cleanup_channel(dmac, chan); -+		if (req->error) -+			req->error(req); ++# + # Misc devices + # +  + # ++# Multifunction device drivers ++# ++# CONFIG_MFD_SM501 is not set  + -+		status = dmac_readl_lo(dmac, STATUS_XFER); -+	} -+} ++# ++# LED devices ++# ++# CONFIG_NEW_LEDS is not set  + -+static irqreturn_t dmac_interrupt(int irq, void *dev_id) -+{ -+	struct dw_dma_controller *dmac = dev_id; -+	unsigned long status; -+	int ret = IRQ_NONE; ++# ++# LED drivers ++#  + -+	spin_lock(&dmac->lock); ++# ++# LED Triggers ++#  + -+	status = dmac_readl_lo(dmac, STATUS_INT); ++# + # Multimedia devices + # + # CONFIG_VIDEO_DEV is not set +@@ -469,100 +763,156 @@ + # Digital Video Broadcasting Devices + # + # CONFIG_DVB is not set ++# CONFIG_USB_DABUSB is not set +  + # + # Graphics support + # +-# CONFIG_FB is not set ++CONFIG_BACKLIGHT_LCD_SUPPORT=y ++CONFIG_BACKLIGHT_CLASS_DEVICE=y ++# CONFIG_LCD_CLASS_DEVICE is not set ++CONFIG_BACKLIGHT_KB920x=y ++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_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++CONFIG_FB_MODE_HELPERS=y ++CONFIG_FB_TILEBLITTING=y +  + # ++# Frame buffer hardware drivers ++# ++CONFIG_FB_S1D15605=y ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_VIRTUAL is not set  + -+	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); ++# + # Console display driver support + # + # CONFIG_VGA_CONSOLE is not set + CONFIG_DUMMY_CONSOLE=y ++CONFIG_FRAMEBUFFER_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set ++CONFIG_FONTS=y ++# CONFIG_FONT_8x8 is not set ++# CONFIG_FONT_8x16 is not set ++# CONFIG_FONT_6x11 is not set ++# CONFIG_FONT_7x14 is not set ++# CONFIG_FONT_PEARL_8x8 is not set ++# CONFIG_FONT_ACORN_8x8 is not set ++CONFIG_FONT_MINI_4x6=y ++# CONFIG_FONT_SUN8x16 is not set ++# CONFIG_FONT_SUN12x22 is not set ++# CONFIG_FONT_10x18 is not set +  + # ++# Logo configuration ++# ++# CONFIG_LOGO is not set  + -+		status = dmac_readl_lo(dmac, STATUS_INT); -+	} ++# + # Sound + # + # CONFIG_SOUND is not set +  + # ++# HID Devices ++# ++CONFIG_HID=y ++# CONFIG_HID_DEBUG is not set  + -+	spin_unlock(&dmac->lock); -+	return ret; -+} ++# + # USB support + # + CONFIG_USB_ARCH_HAS_HCD=y + CONFIG_USB_ARCH_HAS_OHCI=y ++# CONFIG_USB_ARCH_HAS_EHCI is not set + CONFIG_USB=y +-CONFIG_USB_DEBUG=y ++# CONFIG_USB_DEBUG is not set +  + # + # Miscellaneous USB options + # + CONFIG_USB_DEVICEFS=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG is not set +  + # + # USB Host Controller Drivers + # + # CONFIG_USB_ISP116X_HCD is not set + CONFIG_USB_OHCI_HCD=y +-# CONFIG_USB_OHCI_BIG_ENDIAN is not set ++# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set ++# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set + CONFIG_USB_OHCI_LITTLE_ENDIAN=y + # CONFIG_USB_SL811_HCD is not set +  + # + # USB Device Class drivers + # +-# CONFIG_USB_BLUETOOTH_TTY is not set + # CONFIG_USB_ACM is not set + # CONFIG_USB_PRINTER is not set +  + # +-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information ++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' + #  + -+static int __devinit dmac_probe(struct platform_device *pdev) -+{ -+	struct dw_dma_controller *dmac; -+	struct resource *regs; -+	int ret; ++# ++# may also be needed; see USB_STORAGE Help for more information ++# + CONFIG_USB_STORAGE=y +-CONFIG_USB_STORAGE_DEBUG=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set + # CONFIG_USB_STORAGE_FREECOM is not set + # CONFIG_USB_STORAGE_DPCM is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++CONFIG_USB_LIBUSUAL=y +  + # + # USB Input Devices + # +-# CONFIG_USB_HID is not set +- +-# +-# USB HID Boot Protocol drivers +-# +-# CONFIG_USB_KBD is not set +-# CONFIG_USB_MOUSE is not set ++CONFIG_USB_HID=y ++# CONFIG_USB_HIDINPUT_POWERBOOK is not set ++# CONFIG_HID_FF is not set ++# CONFIG_USB_HIDDEV is not set + # CONFIG_USB_AIPTEK is not set + # CONFIG_USB_WACOM is not set + # CONFIG_USB_ACECAD is not set + # CONFIG_USB_KBTAB is not set + # CONFIG_USB_POWERMATE is not set +-# CONFIG_USB_MTOUCH is not set +-# CONFIG_USB_ITMTOUCH is not set +-# CONFIG_USB_EGALAX is not set ++# CONFIG_USB_TOUCHSCREEN is not set ++# CONFIG_USB_YEALINK is not set + # CONFIG_USB_XPAD is not set + # CONFIG_USB_ATI_REMOTE is not set ++# CONFIG_USB_ATI_REMOTE2 is not set ++# CONFIG_USB_KEYSPAN_REMOTE is not set ++# CONFIG_USB_APPLETOUCH is not set ++# CONFIG_USB_GTCO is not set +  + # + # USB Imaging devices + # ++# CONFIG_USB_MDC800 is not set + # CONFIG_USB_MICROTEK is not set +  + # +-# USB Multimedia devices +-# +-# CONFIG_USB_DABUSB is not set +- +-# +-# Video4Linux support is needed for USB Multimedia device support +-# +- +-# + # USB Network Adapters + # ++# CONFIG_USB_CATC is not set + # CONFIG_USB_KAWETH is not set + # CONFIG_USB_PEGASUS is not set ++# CONFIG_USB_RTL8150 is not set ++# CONFIG_USB_USBNET_MII is not set + # CONFIG_USB_USBNET is not set + # CONFIG_USB_MON is not set +  +@@ -580,12 +930,23 @@ + # + # CONFIG_USB_EMI62 is not set + # CONFIG_USB_EMI26 is not set ++# CONFIG_USB_ADUTUX is not set ++# CONFIG_USB_AUERSWALD is not set ++# CONFIG_USB_RIO500 is not set ++# CONFIG_USB_LEGOTOWER is not set + # CONFIG_USB_LCD is not set ++# CONFIG_USB_BERRY_CHARGE is not set + # CONFIG_USB_LED is not set ++# CONFIG_USB_CYPRESS_CY7C63 is not set + # CONFIG_USB_CYTHERM is not set +-# CONFIG_USB_PHIDGETKIT is not set +-# CONFIG_USB_PHIDGETSERVO is not set ++# CONFIG_USB_PHIDGET is not set + # CONFIG_USB_IDMOUSE is not set ++# CONFIG_USB_FTDI_ELAN is not set ++# CONFIG_USB_APPLEDISPLAY is not set ++# CONFIG_USB_LD is not set ++# CONFIG_USB_TRANCEVIBRATOR is not set ++# CONFIG_USB_IOWARRIOR is not set ++# CONFIG_USB_TEST is not set +  + # + # USB DSL modem support +@@ -599,36 +960,51 @@ + # + # MMC/SD Card support + # +-# CONFIG_MMC is not set ++CONFIG_MMC=y ++# CONFIG_MMC_DEBUG is not set ++CONFIG_MMC_BLOCK=y ++CONFIG_MMC_AT91=y +  + # ++# Real Time Clock ++# ++CONFIG_RTC_LIB=y ++# CONFIG_RTC_CLASS is not set  + -+	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+	if (!regs) -+		return -ENXIO; ++# + # File systems + # + CONFIG_EXT2_FS=y + CONFIG_EXT2_FS_XATTR=y +-# CONFIG_EXT2_FS_POSIX_ACL is not set +-# CONFIG_EXT2_FS_SECURITY is not set ++CONFIG_EXT2_FS_POSIX_ACL=y ++CONFIG_EXT2_FS_SECURITY=y + # CONFIG_EXT2_FS_XIP is not set + CONFIG_EXT3_FS=y + CONFIG_EXT3_FS_XATTR=y +-# CONFIG_EXT3_FS_POSIX_ACL is not set +-# CONFIG_EXT3_FS_SECURITY is not set ++CONFIG_EXT3_FS_POSIX_ACL=y ++CONFIG_EXT3_FS_SECURITY=y ++# CONFIG_EXT4DEV_FS is not set + CONFIG_JBD=y + # CONFIG_JBD_DEBUG is not set + CONFIG_FS_MBCACHE=y + # CONFIG_REISERFS_FS is not set + # CONFIG_JFS_FS is not set +- +-# +-# XFS support +-# ++CONFIG_FS_POSIX_ACL=y + # CONFIG_XFS_FS is not set ++# CONFIG_GFS2_FS is not set ++# CONFIG_OCFS2_FS is not set + # CONFIG_MINIX_FS is not set + # CONFIG_ROMFS_FS is not set +-# CONFIG_QUOTA is not set ++CONFIG_INOTIFY=y ++CONFIG_INOTIFY_USER=y ++CONFIG_QUOTA=y ++# CONFIG_QFMT_V1 is not set ++CONFIG_QFMT_V2=y ++CONFIG_QUOTACTL=y + CONFIG_DNOTIFY=y +-CONFIG_AUTOFS_FS=y ++# CONFIG_AUTOFS_FS is not set + CONFIG_AUTOFS4_FS=y ++# CONFIG_FUSE_FS is not set +  + # + # CD-ROM/DVD Filesystems +@@ -643,25 +1019,40 @@ + CONFIG_MSDOS_FS=y + CONFIG_VFAT_FS=y + CONFIG_FAT_DEFAULT_CODEPAGE=437 +-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++CONFIG_FAT_DEFAULT_IOCHARSET="ascii" + # CONFIG_NTFS_FS is not set +  + # + # Pseudo filesystems + # + CONFIG_PROC_FS=y ++CONFIG_PROC_SYSCTL=y + CONFIG_SYSFS=y +-CONFIG_DEVPTS_FS_XATTR=y +-# CONFIG_DEVPTS_FS_SECURITY is not set + CONFIG_TMPFS=y +-# CONFIG_TMPFS_XATTR is not set ++# CONFIG_TMPFS_POSIX_ACL is not set + # CONFIG_HUGETLB_PAGE is not set + CONFIG_RAMFS=y ++CONFIG_CONFIGFS_FS=y +  + # + # Miscellaneous filesystems + # ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_FS is not set ++# CONFIG_HFS_FS is not set + # CONFIG_HFSPLUS_FS is not set ++# CONFIG_BEFS_FS is not set ++# CONFIG_BFS_FS is not set ++# CONFIG_EFS_FS is not set ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_SUMMARY is not set ++# CONFIG_JFFS2_FS_XATTR is not set ++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set ++CONFIG_JFFS2_ZLIB=y ++CONFIG_JFFS2_RTIME=y ++# CONFIG_JFFS2_RUBIN is not set + # CONFIG_CRAMFS is not set + # CONFIG_VXFS_FS is not set + # CONFIG_HPFS_FS is not set +@@ -675,16 +1066,23 @@ + CONFIG_NFS_FS=y + CONFIG_NFS_V3=y + # CONFIG_NFS_V3_ACL is not set ++CONFIG_NFS_V4=y ++# CONFIG_NFS_DIRECTIO is not set + # CONFIG_NFSD is not set + CONFIG_ROOT_NFS=y + CONFIG_LOCKD=y + CONFIG_LOCKD_V4=y + CONFIG_NFS_COMMON=y + CONFIG_SUNRPC=y ++CONFIG_SUNRPC_GSS=y ++CONFIG_RPCSEC_GSS_KRB5=y ++# CONFIG_RPCSEC_GSS_SPKM3 is not set + # CONFIG_SMB_FS is not set + # CONFIG_CIFS is not set + # CONFIG_NCP_FS is not set + # CONFIG_CODA_FS is not set ++# CONFIG_AFS_FS is not set ++# CONFIG_9P_FS is not set +  + # + # Partition Types +@@ -734,26 +1132,51 @@ + # CONFIG_NLS_ISO8859_15 is not set + # CONFIG_NLS_KOI8_R is not set + # CONFIG_NLS_KOI8_U is not set +-# CONFIG_NLS_UTF8 is not set ++CONFIG_NLS_UTF8=y +  + # ++# Distributed Lock Manager ++# ++# CONFIG_DLM is not set  + -+	dmac = kmalloc(sizeof(*dmac), GFP_KERNEL); -+	if (!dmac) -+		return -ENOMEM; -+	memset(dmac, 0, sizeof(*dmac)); ++# ++# Profiling support ++# ++# CONFIG_PROFILING is not set  + -+	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); ++# + # Kernel hacking + # + # CONFIG_PRINTK_TIME is not set ++CONFIG_ENABLE_MUST_CHECK=y ++CONFIG_MAGIC_SYSRQ=y ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set + CONFIG_DEBUG_KERNEL=y +-# CONFIG_MAGIC_SYSRQ is not set +-CONFIG_LOG_BUF_SHIFT=14 ++# CONFIG_DEBUG_SHIRQ is not set ++CONFIG_LOG_BUF_SHIFT=17 ++CONFIG_DETECT_SOFTLOCKUP=y + # CONFIG_SCHEDSTATS is not set ++# CONFIG_TIMER_STATS is not set + # CONFIG_DEBUG_SLAB is not set +-# CONFIG_DEBUG_SPINLOCK is not set +-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_RT_MUTEX_TESTER is not set ++CONFIG_DEBUG_SPINLOCK=y ++# CONFIG_DEBUG_MUTEXES is not set ++CONFIG_DEBUG_SPINLOCK_SLEEP=y ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set + # CONFIG_DEBUG_KOBJECT is not set + CONFIG_DEBUG_BUGVERBOSE=y + # CONFIG_DEBUG_INFO is not set +-# CONFIG_DEBUG_FS is not set ++# CONFIG_DEBUG_VM is not set ++# CONFIG_DEBUG_LIST is not set + CONFIG_FRAME_POINTER=y +-CONFIG_DEBUG_USER=y +-CONFIG_DEBUG_ERRORS=y ++CONFIG_FORCED_INLINING=y ++# CONFIG_RCU_TORTURE_TEST is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_ERRORS is not set + CONFIG_DEBUG_LL=y + # CONFIG_DEBUG_ICEDCC is not set +  +@@ -766,7 +1189,43 @@ + # + # Cryptographic options + # +-# CONFIG_CRYPTO is not set ++CONFIG_CRYPTO=y ++CONFIG_CRYPTO_ALGAPI=y ++CONFIG_CRYPTO_BLKCIPHER=y ++CONFIG_CRYPTO_HASH=m ++CONFIG_CRYPTO_MANAGER=y ++CONFIG_CRYPTO_HMAC=m ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_NULL is not set ++# CONFIG_CRYPTO_MD4 is not set ++CONFIG_CRYPTO_MD5=y ++# CONFIG_CRYPTO_SHA1 is not set ++# CONFIG_CRYPTO_SHA256 is not set ++# CONFIG_CRYPTO_SHA512 is not set ++# CONFIG_CRYPTO_WP512 is not set ++# CONFIG_CRYPTO_TGR192 is not set ++# CONFIG_CRYPTO_GF128MUL is not set ++# CONFIG_CRYPTO_ECB is not set ++CONFIG_CRYPTO_CBC=y ++CONFIG_CRYPTO_PCBC=m ++# CONFIG_CRYPTO_LRW is not set ++CONFIG_CRYPTO_DES=y ++# CONFIG_CRYPTO_FCRYPT is not set ++# CONFIG_CRYPTO_BLOWFISH is not set ++# CONFIG_CRYPTO_TWOFISH is not set ++# CONFIG_CRYPTO_SERPENT is not set ++# CONFIG_CRYPTO_AES is not set ++# CONFIG_CRYPTO_CAST5 is not set ++# CONFIG_CRYPTO_CAST6 is not set ++# CONFIG_CRYPTO_TEA is not set ++# CONFIG_CRYPTO_ARC4 is not set ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_ANUBIS is not set ++# CONFIG_CRYPTO_DEFLATE is not set ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# CONFIG_CRYPTO_CRC32C is not set ++# CONFIG_CRYPTO_CAMELLIA is not set ++# CONFIG_CRYPTO_TEST is not set +  + # + # Hardware crypto devices +@@ -775,6 +1234,14 @@ + # + # Library routines + # ++CONFIG_BITREVERSE=y + # CONFIG_CRC_CCITT is not set ++# CONFIG_CRC16 is not set + CONFIG_CRC32=y + # CONFIG_LIBCRC32C is not set ++CONFIG_AUDIT_GENERIC=y ++CONFIG_ZLIB_INFLATE=y ++CONFIG_ZLIB_DEFLATE=y ++CONFIG_PLIST=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT=y +Index: linux-2.6.22.1/arch/arm/configs/at91sam9260ek_defconfig +=================================================================== +--- linux-2.6.22.1/arch/arm/configs/at91sam9260ek_defconfig	(revision 1) ++++ linux-2.6.22.1/arch/arm/configs/at91sam9260ek_defconfig	(arbetskopia) +@@ -1,18 +1,24 @@ + # + # Automatically generated make config: don't edit +-# Linux kernel version: 2.6.19-rc6 +-# Fri Nov 17 18:42:21 2006 ++# Linux kernel version: 2.6.21 ++# Mon May  7 11:42:02 2007 + # + CONFIG_ARM=y ++CONFIG_SYS_SUPPORTS_APM_EMULATION=y ++CONFIG_GENERIC_GPIO=y + # CONFIG_GENERIC_TIME is not set + CONFIG_MMU=y ++# CONFIG_NO_IOPORT is not set + CONFIG_GENERIC_HARDIRQS=y + CONFIG_TRACE_IRQFLAGS_SUPPORT=y + CONFIG_HARDIRQS_SW_RESEND=y + CONFIG_GENERIC_IRQ_PROBE=y + CONFIG_RWSEM_GENERIC_SPINLOCK=y ++# CONFIG_ARCH_HAS_ILOG2_U32 is not set ++# CONFIG_ARCH_HAS_ILOG2_U64 is not set + CONFIG_GENERIC_HWEIGHT=y + CONFIG_GENERIC_CALIBRATE_DELAY=y ++CONFIG_ZONE_DMA=y + CONFIG_VECTORS_BASE=0xffff0000 + CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +  +@@ -31,13 +37,16 @@ + # CONFIG_SWAP is not set + CONFIG_SYSVIPC=y + # CONFIG_IPC_NS is not set ++CONFIG_SYSVIPC_SYSCTL=y + # CONFIG_POSIX_MQUEUE is not set + # CONFIG_BSD_PROCESS_ACCT is not set + # CONFIG_TASKSTATS is not set + # CONFIG_UTS_NS is not set + # CONFIG_AUDIT is not set + # CONFIG_IKCONFIG is not set ++CONFIG_SYSFS_DEPRECATED=y + # CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y + CONFIG_INITRAMFS_SOURCE="" + CONFIG_CC_OPTIMIZE_FOR_SIZE=y + CONFIG_SYSCTL=y +@@ -76,7 +85,9 @@ + # Block layer + # + CONFIG_BLOCK=y ++# CONFIG_LBD is not set + # CONFIG_BLK_DEV_IO_TRACE is not set ++# CONFIG_LSF is not set +  + # + # IO Schedulers +@@ -110,10 +121,12 @@ + # CONFIG_ARCH_IMX is not set + # CONFIG_ARCH_IOP32X is not set + # CONFIG_ARCH_IOP33X is not set ++# CONFIG_ARCH_IOP13XX is not set + # CONFIG_ARCH_IXP4XX is not set + # CONFIG_ARCH_IXP2000 is not set + # CONFIG_ARCH_IXP23XX is not set + # CONFIG_ARCH_L7200 is not set ++# CONFIG_ARCH_NS9XXX is not set + # CONFIG_ARCH_PNX4008 is not set + # CONFIG_ARCH_PXA is not set + # CONFIG_ARCH_RPC is not set +@@ -129,21 +142,29 @@ + # CONFIG_ARCH_AT91RM9200 is not set + CONFIG_ARCH_AT91SAM9260=y + # CONFIG_ARCH_AT91SAM9261 is not set ++# CONFIG_ARCH_AT91SAM9263 is not set +  + # +-# AT91SAM9260 Board Type ++# AT91SAM9260 Variants + # ++# CONFIG_ARCH_AT91SAM9260_SAM9XE is not set  + -+	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; ++# ++# AT91SAM9260 / AT91SAM9XE Board Type ++# + CONFIG_MACH_AT91SAM9260EK=y +  + # + # AT91 Board Options + # ++# CONFIG_MTD_AT91_DATAFLASH_CARD is not set + # CONFIG_MTD_NAND_AT91_BUSWIDTH_16 is not set +  + # + # AT91 Feature Selections + # + # CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set ++# CONFIG_ATMEL_TCLIB is not set +  + # + # Processor Type +@@ -166,6 +187,7 @@ + # CONFIG_CPU_DCACHE_DISABLE is not set + # CONFIG_CPU_DCACHE_WRITETHROUGH is not set + # CONFIG_CPU_CACHE_ROUND_ROBIN is not set ++# CONFIG_OUTER_CACHE is not set +  + # + # Bus support +@@ -193,6 +215,7 @@ + # CONFIG_SPARSEMEM_STATIC is not set + CONFIG_SPLIT_PTLOCK_CPUS=4096 + # CONFIG_RESOURCES_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=1 + # CONFIG_LEDS is not set + CONFIG_ALIGNMENT_TRAP=y +  +@@ -203,6 +226,7 @@ + CONFIG_ZBOOT_ROM_BSS=0x0 + CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw" + # CONFIG_XIP_KERNEL is not set ++# CONFIG_KEXEC is not set +  + # + # Floating point emulation +@@ -228,7 +252,6 @@ + # Power management options + # + # CONFIG_PM is not set +-# CONFIG_APM is not set +  + # + # Networking +@@ -242,9 +265,6 @@ + CONFIG_PACKET=y + # CONFIG_PACKET_MMAP is not set + CONFIG_UNIX=y +-CONFIG_XFRM=y +-# CONFIG_XFRM_USER is not set +-# CONFIG_XFRM_SUB_POLICY is not set + # CONFIG_NET_KEY is not set + CONFIG_INET=y + # CONFIG_IP_MULTICAST is not set +@@ -263,14 +283,15 @@ + # CONFIG_INET_IPCOMP is not set + # CONFIG_INET_XFRM_TUNNEL is not set + # CONFIG_INET_TUNNEL is not set +-CONFIG_INET_XFRM_MODE_TRANSPORT=y +-CONFIG_INET_XFRM_MODE_TUNNEL=y +-CONFIG_INET_XFRM_MODE_BEET=y ++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set ++# CONFIG_INET_XFRM_MODE_TUNNEL is not set ++# CONFIG_INET_XFRM_MODE_BEET is not set + CONFIG_INET_DIAG=y + CONFIG_INET_TCP_DIAG=y + # CONFIG_TCP_CONG_ADVANCED is not set + CONFIG_TCP_CONG_CUBIC=y + CONFIG_DEFAULT_TCP_CONG="cubic" ++# CONFIG_TCP_MD5SIG is not set + # CONFIG_IPV6 is not set + # CONFIG_INET6_XFRM_TUNNEL is not set + # CONFIG_INET6_TUNNEL is not set +@@ -328,6 +349,7 @@ + CONFIG_PREVENT_FIRMWARE_BUILD=y + # CONFIG_FW_LOADER is not set + # CONFIG_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set + # CONFIG_SYS_HYPERVISOR is not set +  + # +@@ -348,6 +370,7 @@ + # + # Plug and Play support + # ++# CONFIG_PNPACPI is not set +  + # + # Block devices +@@ -360,7 +383,6 @@ + CONFIG_BLK_DEV_RAM_COUNT=16 + CONFIG_BLK_DEV_RAM_SIZE=8192 + CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 +-CONFIG_BLK_DEV_INITRD=y + # CONFIG_CDROM_PKTCDVD is not set + # CONFIG_ATA_OVER_ETH is not set +  +@@ -369,6 +391,7 @@ + # + # CONFIG_RAID_ATTRS is not set + CONFIG_SCSI=y ++# CONFIG_SCSI_TGT is not set + # CONFIG_SCSI_NETLINK is not set + CONFIG_SCSI_PROC_FS=y +  +@@ -388,6 +411,7 @@ + CONFIG_SCSI_MULTI_LUN=y + # CONFIG_SCSI_CONSTANTS is not set + # CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set +  + # + # SCSI Transports +@@ -405,6 +429,11 @@ + # CONFIG_SCSI_DEBUG is not set +  + # ++# Serial ATA (prod) and Parallel ATA (experimental) drivers ++# ++# CONFIG_ATA is not set  + -+	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; ++# + # Multi-device support (RAID and LVM) + # + # CONFIG_MD is not set +@@ -425,7 +454,51 @@ + # + # Network device support + # +-# CONFIG_NETDEVICES is not set ++CONFIG_NETDEVICES=y ++# CONFIG_DUMMY is not set ++# CONFIG_BONDING is not set ++# CONFIG_EQUALIZER is not set ++# CONFIG_TUN is not set  + -+	dmac->regs = ioremap(regs->start, regs->end - regs->start + 1); -+	if (!dmac->regs) -+		goto out_free_pool; ++# ++# PHY device support ++# ++# CONFIG_PHYLIB is not set  + -+	ret = request_irq(platform_get_irq(pdev, 0), dmac_interrupt, -+			  IRQF_SAMPLE_RANDOM, pdev->name, dmac); -+	if (ret) -+		goto out_unmap_regs; ++# ++# Ethernet (10 or 100Mbit) ++# ++CONFIG_NET_ETHERNET=y ++CONFIG_MII=y ++CONFIG_MACB=y ++# CONFIG_SMC91X is not set ++# CONFIG_DM9000 is not set  + -+	/* Enable the DMA controller */ -+	dmac_writel_lo(dmac, CFG, 1); ++# ++# Ethernet (1000 Mbit) ++#  + -+	register_dma_controller(&dmac->dma); ++# ++# Ethernet (10000 Mbit) ++#  + -+	printk(KERN_INFO -+	       "dmac%d: DesignWare DMA controller at 0x%p irq %d\n", -+	       dmac->dma.id, dmac->regs, platform_get_irq(pdev, 0)); ++# ++# Token Ring devices ++#  + -+	return 0; ++# ++# Wireless LAN (non-hamradio) ++# ++# CONFIG_NET_RADIO is not set  + -+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; -+} ++# ++# Wan interfaces ++# ++# CONFIG_WAN is not set ++# CONFIG_PPP is not set ++# CONFIG_SLIP is not set ++# CONFIG_SHAPER is not set ++# CONFIG_NETCONSOLE is not set + # CONFIG_NETPOLL is not set + # CONFIG_NET_POLL_CONTROLLER is not set +  +@@ -517,10 +590,6 @@ + # CONFIG_NVRAM is not set + # CONFIG_DTLK is not set + # CONFIG_R3964 is not set +- +-# +-# Ftape, the floppy tape device driver +-# + # CONFIG_RAW_DRIVER is not set +  + # +@@ -553,9 +622,13 @@ + # + # Misc devices + # +-# CONFIG_TIFM_CORE is not set +  + # ++# Multifunction device drivers ++# ++# CONFIG_MFD_SM501 is not set  + -+static struct platform_driver dmac_driver = { -+	.probe		= dmac_probe, -+	.driver		= { -+		.name		= "dmaca", -+	}, -+}; ++# + # LED devices + # + # CONFIG_NEW_LEDS is not set +@@ -582,7 +655,7 @@ + # + # Graphics support + # +-# CONFIG_FIRMWARE_EDID is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + # CONFIG_FB is not set +  + # +@@ -590,7 +663,6 @@ + # + # CONFIG_VGA_CONSOLE is not set + CONFIG_DUMMY_CONSOLE=y +-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +  + # + # Sound +@@ -598,6 +670,12 @@ + # CONFIG_SOUND is not set +  + # ++# HID Devices ++# ++CONFIG_HID=y ++# CONFIG_HID_DEBUG is not set  + -+static int __init dmac_init(void) -+{ -+	return platform_driver_register(&dmac_driver); -+} -+subsys_initcall(dmac_init); ++# + # USB support + # + CONFIG_USB_ARCH_HAS_HCD=y +@@ -610,7 +688,6 @@ + # Miscellaneous USB options + # + CONFIG_USB_DEVICEFS=y +-# CONFIG_USB_BANDWIDTH is not set + # CONFIG_USB_DYNAMIC_MINORS is not set + # CONFIG_USB_OTG is not set +  +@@ -619,7 +696,8 @@ + # + # CONFIG_USB_ISP116X_HCD is not set + CONFIG_USB_OHCI_HCD=y +-# CONFIG_USB_OHCI_BIG_ENDIAN is not set ++# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set ++# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set + CONFIG_USB_OHCI_LITTLE_ENDIAN=y + # CONFIG_USB_SL811_HCD is not set +  +@@ -671,6 +749,7 @@ + # CONFIG_USB_ATI_REMOTE2 is not set + # CONFIG_USB_KEYSPAN_REMOTE is not set + # CONFIG_USB_APPLETOUCH is not set ++# CONFIG_USB_GTCO is not set +  + # + # USB Imaging devices +@@ -708,6 +787,7 @@ + # CONFIG_USB_RIO500 is not set + # CONFIG_USB_LEGOTOWER is not set + # CONFIG_USB_LCD is not set ++# CONFIG_USB_BERRY_CHARGE is not set + # CONFIG_USB_LED is not set + # CONFIG_USB_CYPRESS_CY7C63 is not set + # CONFIG_USB_CYTHERM is not set +@@ -717,6 +797,7 @@ + # CONFIG_USB_APPLEDISPLAY is not set + # CONFIG_USB_LD is not set + # CONFIG_USB_TRANCEVIBRATOR is not set ++# CONFIG_USB_IOWARRIOR is not set + # CONFIG_USB_TEST is not set +  + # +@@ -889,6 +970,11 @@ + # CONFIG_NLS_UTF8 is not set +  + # ++# Distributed Lock Manager ++# ++# CONFIG_DLM is not set  + -+static void __exit dmac_exit(void) -+{ -+	platform_driver_unregister(&dmac_driver); -+} -+module_exit(dmac_exit); ++# + # Profiling support + # + # CONFIG_PROFILING is not set +@@ -900,28 +986,30 @@ + CONFIG_ENABLE_MUST_CHECK=y + # CONFIG_MAGIC_SYSRQ is not set + # CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set + CONFIG_DEBUG_KERNEL=y ++# CONFIG_DEBUG_SHIRQ is not set + CONFIG_LOG_BUF_SHIFT=14 + CONFIG_DETECT_SOFTLOCKUP=y + # CONFIG_SCHEDSTATS is not set ++# CONFIG_TIMER_STATS is not set + # CONFIG_DEBUG_SLAB is not set + # CONFIG_DEBUG_RT_MUTEXES is not set + # CONFIG_RT_MUTEX_TESTER is not set + # CONFIG_DEBUG_SPINLOCK is not set + # CONFIG_DEBUG_MUTEXES is not set +-# CONFIG_DEBUG_RWSEMS is not set + # CONFIG_DEBUG_SPINLOCK_SLEEP is not set + # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set + # CONFIG_DEBUG_KOBJECT is not set + CONFIG_DEBUG_BUGVERBOSE=y + # CONFIG_DEBUG_INFO is not set +-# CONFIG_DEBUG_FS is not set + # CONFIG_DEBUG_VM is not set + # CONFIG_DEBUG_LIST is not set + CONFIG_FRAME_POINTER=y + CONFIG_FORCED_INLINING=y +-# CONFIG_HEADERS_CHECK is not set + # CONFIG_RCU_TORTURE_TEST is not set ++# CONFIG_FAULT_INJECTION is not set + CONFIG_DEBUG_USER=y + # CONFIG_DEBUG_ERRORS is not set + CONFIG_DEBUG_LL=y +@@ -941,9 +1029,12 @@ + # + # Library routines + # ++CONFIG_BITREVERSE=y + # CONFIG_CRC_CCITT is not set + # CONFIG_CRC16 is not set + CONFIG_CRC32=y + # CONFIG_LIBCRC32C is not set + CONFIG_ZLIB_INFLATE=y + CONFIG_PLIST=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT=y +Index: linux-2.6.22.1/arch/arm/configs/at91sam9261ek_defconfig +=================================================================== +--- linux-2.6.22.1/arch/arm/configs/at91sam9261ek_defconfig	(revision 1) ++++ linux-2.6.22.1/arch/arm/configs/at91sam9261ek_defconfig	(arbetskopia) +@@ -1,18 +1,24 @@ + # + # Automatically generated make config: don't edit +-# Linux kernel version: 2.6.19-rc6 +-# Fri Nov 17 18:00:38 2006 ++# Linux kernel version: 2.6.21 ++# Mon May  7 11:42:30 2007 + # + CONFIG_ARM=y ++CONFIG_SYS_SUPPORTS_APM_EMULATION=y ++CONFIG_GENERIC_GPIO=y + # CONFIG_GENERIC_TIME is not set + CONFIG_MMU=y ++# CONFIG_NO_IOPORT is not set + CONFIG_GENERIC_HARDIRQS=y + CONFIG_TRACE_IRQFLAGS_SUPPORT=y + CONFIG_HARDIRQS_SW_RESEND=y + CONFIG_GENERIC_IRQ_PROBE=y + CONFIG_RWSEM_GENERIC_SPINLOCK=y ++# CONFIG_ARCH_HAS_ILOG2_U32 is not set ++# CONFIG_ARCH_HAS_ILOG2_U64 is not set + CONFIG_GENERIC_HWEIGHT=y + CONFIG_GENERIC_CALIBRATE_DELAY=y ++CONFIG_ZONE_DMA=y + CONFIG_VECTORS_BASE=0xffff0000 + CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +  +@@ -31,13 +37,16 @@ + # CONFIG_SWAP is not set + CONFIG_SYSVIPC=y + # CONFIG_IPC_NS is not set ++CONFIG_SYSVIPC_SYSCTL=y + # CONFIG_POSIX_MQUEUE is not set + # CONFIG_BSD_PROCESS_ACCT is not set + # CONFIG_TASKSTATS is not set + # CONFIG_UTS_NS is not set + # CONFIG_AUDIT is not set + # CONFIG_IKCONFIG is not set ++CONFIG_SYSFS_DEPRECATED=y + # CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y + CONFIG_INITRAMFS_SOURCE="" + CONFIG_CC_OPTIMIZE_FOR_SIZE=y + CONFIG_SYSCTL=y +@@ -76,7 +85,9 @@ + # Block layer + # + CONFIG_BLOCK=y ++# CONFIG_LBD is not set + # CONFIG_BLK_DEV_IO_TRACE is not set ++# CONFIG_LSF is not set +  + # + # IO Schedulers +@@ -110,10 +121,12 @@ + # CONFIG_ARCH_IMX is not set + # CONFIG_ARCH_IOP32X is not set + # CONFIG_ARCH_IOP33X is not set ++# CONFIG_ARCH_IOP13XX is not set + # CONFIG_ARCH_IXP4XX is not set + # CONFIG_ARCH_IXP2000 is not set + # CONFIG_ARCH_IXP23XX is not set + # CONFIG_ARCH_L7200 is not set ++# CONFIG_ARCH_NS9XXX is not set + # CONFIG_ARCH_PNX4008 is not set + # CONFIG_ARCH_PXA is not set + # CONFIG_ARCH_RPC is not set +@@ -129,6 +142,7 @@ + # CONFIG_ARCH_AT91RM9200 is not set + # CONFIG_ARCH_AT91SAM9260 is not set + CONFIG_ARCH_AT91SAM9261=y ++# CONFIG_ARCH_AT91SAM9263 is not set +  + # + # AT91SAM9261 Board Type +@@ -138,12 +152,14 @@ + # + # AT91 Board Options + # ++# CONFIG_MTD_AT91_DATAFLASH_CARD is not set + # CONFIG_MTD_NAND_AT91_BUSWIDTH_16 is not set +  + # + # AT91 Feature Selections + # + # CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set ++# CONFIG_ATMEL_TCLIB is not set +  + # + # Processor Type +@@ -166,6 +182,7 @@ + # CONFIG_CPU_DCACHE_DISABLE is not set + # CONFIG_CPU_DCACHE_WRITETHROUGH is not set + # CONFIG_CPU_CACHE_ROUND_ROBIN is not set ++# CONFIG_OUTER_CACHE is not set +  + # + # Bus support +@@ -193,6 +210,7 @@ + # CONFIG_SPARSEMEM_STATIC is not set + CONFIG_SPLIT_PTLOCK_CPUS=4096 + # CONFIG_RESOURCES_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=1 + # CONFIG_LEDS is not set + CONFIG_ALIGNMENT_TRAP=y +  +@@ -203,6 +221,7 @@ + CONFIG_ZBOOT_ROM_BSS=0x0 + CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw" + # CONFIG_XIP_KERNEL is not set ++# CONFIG_KEXEC is not set +  + # + # Floating point emulation +@@ -228,7 +247,6 @@ + # Power management options + # + # CONFIG_PM is not set +-# CONFIG_APM is not set +  + # + # Networking +@@ -245,6 +263,7 @@ + CONFIG_XFRM=y + # CONFIG_XFRM_USER is not set + # CONFIG_XFRM_SUB_POLICY is not set ++# CONFIG_XFRM_MIGRATE is not set + # CONFIG_NET_KEY is not set + CONFIG_INET=y + # CONFIG_IP_MULTICAST is not set +@@ -271,6 +290,7 @@ + # CONFIG_TCP_CONG_ADVANCED is not set + CONFIG_TCP_CONG_CUBIC=y + CONFIG_DEFAULT_TCP_CONG="cubic" ++# CONFIG_TCP_MD5SIG is not set + # CONFIG_IPV6 is not set + # CONFIG_INET6_XFRM_TUNNEL is not set + # CONFIG_INET6_TUNNEL is not set +@@ -328,6 +348,7 @@ + CONFIG_PREVENT_FIRMWARE_BUILD=y + # CONFIG_FW_LOADER is not set + # CONFIG_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set + # CONFIG_SYS_HYPERVISOR is not set +  + # +@@ -350,6 +371,7 @@ + # User Modules And Translation Layers + # + # CONFIG_MTD_CHAR is not set ++CONFIG_MTD_BLKDEVS=y + CONFIG_MTD_BLOCK=y + # CONFIG_FTL is not set + # CONFIG_NFTL is not set +@@ -386,6 +408,8 @@ + # + # Self-contained MTD device drivers + # ++# CONFIG_MTD_DATAFLASH is not set ++# CONFIG_MTD_M25P80 is not set + # CONFIG_MTD_SLRAM is not set + # CONFIG_MTD_PHRAM is not set + # CONFIG_MTD_MTDRAM is not set +@@ -422,6 +446,7 @@ + # + # Plug and Play support + # ++# CONFIG_PNPACPI is not set +  + # + # Block devices +@@ -434,7 +459,6 @@ + CONFIG_BLK_DEV_RAM_COUNT=16 + CONFIG_BLK_DEV_RAM_SIZE=8192 + CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 +-CONFIG_BLK_DEV_INITRD=y + # CONFIG_CDROM_PKTCDVD is not set + # CONFIG_ATA_OVER_ETH is not set +  +@@ -443,6 +467,7 @@ + # + # CONFIG_RAID_ATTRS is not set + CONFIG_SCSI=y ++# CONFIG_SCSI_TGT is not set + # CONFIG_SCSI_NETLINK is not set + CONFIG_SCSI_PROC_FS=y +  +@@ -462,6 +487,7 @@ + CONFIG_SCSI_MULTI_LUN=y + # CONFIG_SCSI_CONSTANTS is not set + # CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set +  + # + # SCSI Transports +@@ -479,6 +505,11 @@ + # CONFIG_SCSI_DEBUG is not set +  + # ++# Serial ATA (prod) and Parallel ATA (experimental) drivers ++# ++# CONFIG_ATA is not set  + -+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__ ++# + # Multi-device support (RAID and LVM) + # + # CONFIG_MD is not set +@@ -575,7 +606,16 @@ + # CONFIG_INPUT_KEYBOARD is not set + # CONFIG_INPUT_MOUSE is not set + # CONFIG_INPUT_JOYSTICK is not set +-# CONFIG_INPUT_TOUCHSCREEN is not set ++CONFIG_INPUT_TOUCHSCREEN=y ++CONFIG_TOUCHSCREEN_ADS7846=y ++# CONFIG_TOUCHSCREEN_GUNZE is not set ++# CONFIG_TOUCHSCREEN_ELO is not set ++# CONFIG_TOUCHSCREEN_MTOUCH is not set ++# CONFIG_TOUCHSCREEN_MK712 is not set ++# CONFIG_TOUCHSCREEN_PENMOUNT is not set ++# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set ++# CONFIG_TOUCHSCREEN_TOUCHWIN is not set ++# CONFIG_TOUCHSCREEN_UCB1400 is not set + # CONFIG_INPUT_MISC is not set +  + # +@@ -634,10 +674,6 @@ + # CONFIG_NVRAM is not set + # CONFIG_DTLK is not set + # CONFIG_R3964 is not set +- +-# +-# Ftape, the floppy tape device driver +-# + # CONFIG_RAW_DRIVER is not set +  + # +@@ -662,6 +698,7 @@ + # I2C Hardware Bus support + # + CONFIG_I2C_AT91=y ++CONFIG_I2C_AT91_CLOCKRATE=100000 + # CONFIG_I2C_OCORES is not set + # CONFIG_I2C_PARPORT_LIGHT is not set + # CONFIG_I2C_STUB is not set +@@ -686,10 +723,22 @@ + # + # 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  + -+#define DW_DMAC_CFG		0x398 -+#define DW_DMAC_CH_EN		0x3a0 ++# ++# SPI Protocol Masters ++# ++# CONFIG_SPI_AT25 is not set  + -+#define DW_DMAC_STATUS_XFER	0x2e8 -+#define DW_DMAC_STATUS_BLOCK	0x2f0 -+#define DW_DMAC_STATUS_ERROR	0x308 ++# + # Dallas's 1-wire bus + # + # CONFIG_W1 is not set +@@ -703,9 +752,13 @@ + # + # Misc devices + # +-# CONFIG_TIFM_CORE is not set +  + # ++# Multifunction device drivers ++# ++# CONFIG_MFD_SM501 is not set  + -+#define DW_DMAC_MASK_XFER	0x310 -+#define DW_DMAC_MASK_BLOCK	0x318 -+#define DW_DMAC_MASK_ERROR	0x330 ++# + # LED devices + # + # CONFIG_NEW_LEDS is not set +@@ -732,7 +785,7 @@ + # + # Graphics support + # +-# CONFIG_FIRMWARE_EDID is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + # CONFIG_FB is not set +  + # +@@ -740,7 +793,6 @@ + # + # CONFIG_VGA_CONSOLE is not set + CONFIG_DUMMY_CONSOLE=y +-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +  + # + # Sound +@@ -748,6 +800,12 @@ + # CONFIG_SOUND is not set +  + # ++# HID Devices ++# ++CONFIG_HID=y ++# CONFIG_HID_DEBUG is not set  + -+#define DW_DMAC_CLEAR_XFER	0x338 -+#define DW_DMAC_CLEAR_BLOCK	0x340 -+#define DW_DMAC_CLEAR_ERROR	0x358 ++# + # USB support + # + CONFIG_USB_ARCH_HAS_HCD=y +@@ -760,7 +818,6 @@ + # Miscellaneous USB options + # + CONFIG_USB_DEVICEFS=y +-# CONFIG_USB_BANDWIDTH is not set + # CONFIG_USB_DYNAMIC_MINORS is not set + # CONFIG_USB_OTG is not set +  +@@ -769,7 +826,8 @@ + # + # CONFIG_USB_ISP116X_HCD is not set + CONFIG_USB_OHCI_HCD=y +-# CONFIG_USB_OHCI_BIG_ENDIAN is not set ++# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set ++# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set + CONFIG_USB_OHCI_LITTLE_ENDIAN=y + # CONFIG_USB_SL811_HCD is not set +  +@@ -821,6 +879,7 @@ + # CONFIG_USB_ATI_REMOTE2 is not set + # CONFIG_USB_KEYSPAN_REMOTE is not set + # CONFIG_USB_APPLETOUCH is not set ++# CONFIG_USB_GTCO is not set +  + # + # USB Imaging devices +@@ -858,6 +917,7 @@ + # CONFIG_USB_RIO500 is not set + # CONFIG_USB_LEGOTOWER is not set + # CONFIG_USB_LCD is not set ++# CONFIG_USB_BERRY_CHARGE is not set + # CONFIG_USB_LED is not set + # CONFIG_USB_CYPRESS_CY7C63 is not set + # CONFIG_USB_CYTHERM is not set +@@ -867,6 +927,7 @@ + # CONFIG_USB_APPLEDISPLAY is not set + # CONFIG_USB_LD is not set + # CONFIG_USB_TRANCEVIBRATOR is not set ++# CONFIG_USB_IOWARRIOR is not set + # CONFIG_USB_TEST is not set +  + # +@@ -903,7 +964,6 @@ + # CONFIG_MMC_DEBUG is not set + CONFIG_MMC_BLOCK=y + CONFIG_MMC_AT91=m +-# CONFIG_MMC_TIFM_SD is not set +  + # + # Real Time Clock +@@ -973,7 +1033,6 @@ + # CONFIG_BEFS_FS is not set + # CONFIG_BFS_FS is not set + # CONFIG_EFS_FS is not set +-# CONFIG_JFFS_FS is not set + # CONFIG_JFFS2_FS is not set + CONFIG_CRAMFS=y + # CONFIG_VXFS_FS is not set +@@ -1045,6 +1104,11 @@ + # CONFIG_NLS_UTF8 is not set +  + # ++# Distributed Lock Manager ++# ++# CONFIG_DLM is not set  + -+#define DW_DMAC_STATUS_INT	0x360 ++# + # Profiling support + # + # CONFIG_PROFILING is not set +@@ -1056,28 +1120,30 @@ + CONFIG_ENABLE_MUST_CHECK=y + # CONFIG_MAGIC_SYSRQ is not set + # CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set + CONFIG_DEBUG_KERNEL=y ++# CONFIG_DEBUG_SHIRQ is not set + CONFIG_LOG_BUF_SHIFT=14 + CONFIG_DETECT_SOFTLOCKUP=y + # CONFIG_SCHEDSTATS is not set ++# CONFIG_TIMER_STATS is not set + # CONFIG_DEBUG_SLAB is not set + # CONFIG_DEBUG_RT_MUTEXES is not set + # CONFIG_RT_MUTEX_TESTER is not set + # CONFIG_DEBUG_SPINLOCK is not set + # CONFIG_DEBUG_MUTEXES is not set +-# CONFIG_DEBUG_RWSEMS is not set + # CONFIG_DEBUG_SPINLOCK_SLEEP is not set + # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set + # CONFIG_DEBUG_KOBJECT is not set + CONFIG_DEBUG_BUGVERBOSE=y + # CONFIG_DEBUG_INFO is not set +-# CONFIG_DEBUG_FS is not set + # CONFIG_DEBUG_VM is not set + # CONFIG_DEBUG_LIST is not set + CONFIG_FRAME_POINTER=y + CONFIG_FORCED_INLINING=y +-# CONFIG_HEADERS_CHECK is not set + # CONFIG_RCU_TORTURE_TEST is not set ++# CONFIG_FAULT_INJECTION is not set + CONFIG_DEBUG_USER=y + # CONFIG_DEBUG_ERRORS is not set + CONFIG_DEBUG_LL=y +@@ -1097,9 +1163,12 @@ + # + # Library routines + # ++CONFIG_BITREVERSE=y + # CONFIG_CRC_CCITT is not set + # CONFIG_CRC16 is not set + CONFIG_CRC32=y + # CONFIG_LIBCRC32C is not set + CONFIG_ZLIB_INFLATE=y + CONFIG_PLIST=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT=y +Index: linux-2.6.22.1/arch/arm/configs/at91sam9263ek_defconfig +=================================================================== +--- linux-2.6.22.1/arch/arm/configs/at91sam9263ek_defconfig	(revision 1) ++++ linux-2.6.22.1/arch/arm/configs/at91sam9263ek_defconfig	(arbetskopia) +@@ -1,11 +1,14 @@ + # + # Automatically generated make config: don't edit +-# Linux kernel version: 2.6.20-rc1 +-# Mon Jan  8 16:06:54 2007 ++# Linux kernel version: 2.6.21 ++# Mon May  7 11:42:49 2007 + # + CONFIG_ARM=y ++CONFIG_SYS_SUPPORTS_APM_EMULATION=y ++CONFIG_GENERIC_GPIO=y + # CONFIG_GENERIC_TIME is not set + CONFIG_MMU=y ++# CONFIG_NO_IOPORT is not set + CONFIG_GENERIC_HARDIRQS=y + CONFIG_TRACE_IRQFLAGS_SUPPORT=y + CONFIG_HARDIRQS_SW_RESEND=y +@@ -15,6 +18,7 @@ + # CONFIG_ARCH_HAS_ILOG2_U64 is not set + CONFIG_GENERIC_HWEIGHT=y + CONFIG_GENERIC_CALIBRATE_DELAY=y ++CONFIG_ZONE_DMA=y + CONFIG_VECTORS_BASE=0xffff0000 + CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +  +@@ -33,6 +37,7 @@ + # CONFIG_SWAP is not set + CONFIG_SYSVIPC=y + # CONFIG_IPC_NS is not set ++CONFIG_SYSVIPC_SYSCTL=y + # CONFIG_POSIX_MQUEUE is not set + # CONFIG_BSD_PROCESS_ACCT is not set + # CONFIG_TASKSTATS is not set +@@ -41,6 +46,7 @@ + # CONFIG_IKCONFIG is not set + CONFIG_SYSFS_DEPRECATED=y + # CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y + CONFIG_INITRAMFS_SOURCE="" + CONFIG_CC_OPTIMIZE_FOR_SIZE=y + CONFIG_SYSCTL=y +@@ -120,6 +126,7 @@ + # CONFIG_ARCH_IXP2000 is not set + # CONFIG_ARCH_IXP23XX is not set + # CONFIG_ARCH_L7200 is not set ++# CONFIG_ARCH_NS9XXX is not set + # CONFIG_ARCH_PNX4008 is not set + # CONFIG_ARCH_PXA is not set + # CONFIG_ARCH_RPC is not set +@@ -152,6 +159,7 @@ + # AT91 Feature Selections + # + # CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set ++# CONFIG_ATMEL_TCLIB is not set +  + # + # Processor Type +@@ -174,6 +182,7 @@ + # CONFIG_CPU_DCACHE_DISABLE is not set + # CONFIG_CPU_DCACHE_WRITETHROUGH is not set + # CONFIG_CPU_CACHE_ROUND_ROBIN is not set ++# CONFIG_OUTER_CACHE is not set +  + # + # Bus support +@@ -201,6 +210,7 @@ + # CONFIG_SPARSEMEM_STATIC is not set + CONFIG_SPLIT_PTLOCK_CPUS=4096 + # CONFIG_RESOURCES_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=1 + # CONFIG_LEDS is not set + CONFIG_ALIGNMENT_TRAP=y +  +@@ -211,6 +221,7 @@ + CONFIG_ZBOOT_ROM_BSS=0x0 + CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw" + # CONFIG_XIP_KERNEL is not set ++# CONFIG_KEXEC is not set +  + # + # Floating point emulation +@@ -236,7 +247,6 @@ + # Power management options + # + # CONFIG_PM is not set +-# CONFIG_APM is not set +  + # + # Networking +@@ -333,6 +343,7 @@ + CONFIG_PREVENT_FIRMWARE_BUILD=y + # CONFIG_FW_LOADER is not set + # CONFIG_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set + # CONFIG_SYS_HYPERVISOR is not set +  + # +@@ -430,6 +441,7 @@ + # + # Plug and Play support + # ++# CONFIG_PNPACPI is not set +  + # + # Block devices +@@ -443,7 +455,6 @@ + CONFIG_BLK_DEV_RAM_COUNT=16 + CONFIG_BLK_DEV_RAM_SIZE=8192 + CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 +-CONFIG_BLK_DEV_INITRD=y + # CONFIG_CDROM_PKTCDVD is not set + # CONFIG_ATA_OVER_ETH is not set +  +@@ -531,6 +542,7 @@ + # + CONFIG_NET_ETHERNET=y + CONFIG_MII=y ++CONFIG_MACB=y + # CONFIG_SMC91X is not set + # CONFIG_DM9000 is not set +  +@@ -685,6 +697,7 @@ + # I2C Hardware Bus support + # + CONFIG_I2C_AT91=y ++CONFIG_I2C_AT91_CLOCKRATE=100000 + # CONFIG_I2C_OCORES is not set + # CONFIG_I2C_PARPORT_LIGHT is not set + # CONFIG_I2C_STUB is not set +@@ -722,6 +735,7 @@ + # + # SPI Protocol Masters + # ++# CONFIG_SPI_AT25 is not set +  + # + # Dallas's 1-wire bus +@@ -737,9 +751,13 @@ + # + # Misc devices + # +-# CONFIG_TIFM_CORE is not set +  + # ++# Multifunction device drivers ++# ++# CONFIG_MFD_SM501 is not set  + -+#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 ++# + # LED devices + # + # CONFIG_NEW_LEDS is not set +@@ -766,15 +784,23 @@ + # + # Graphics support + # ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++CONFIG_FB=y + # CONFIG_FIRMWARE_EDID is not set +-CONFIG_FB=y ++# CONFIG_FB_DDC is not set + # CONFIG_FB_CFB_FILLRECT is not set + # CONFIG_FB_CFB_COPYAREA is not set + # CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_SVGALIB is not set + # CONFIG_FB_MACMODES is not set + # CONFIG_FB_BACKLIGHT is not set + # CONFIG_FB_MODE_HELPERS is not set + # CONFIG_FB_TILEBLITTING is not set  + -+#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 ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_S1D15605 is not set + # CONFIG_FB_S1D13XXX is not set + # CONFIG_FB_VIRTUAL is not set +  +@@ -789,7 +815,6 @@ + # Logo configuration + # + # CONFIG_LOGO is not set +-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +  + # + # Sound +@@ -800,6 +825,7 @@ + # HID Devices + # + CONFIG_HID=y ++# CONFIG_HID_DEBUG is not set +  + # + # USB support +@@ -814,9 +840,7 @@ + # Miscellaneous USB options + # + CONFIG_USB_DEVICEFS=y +-# CONFIG_USB_BANDWIDTH is not set + # CONFIG_USB_DYNAMIC_MINORS is not set +-# CONFIG_USB_MULTITHREAD_PROBE is not set + # CONFIG_USB_OTG is not set +  + # +@@ -824,7 +848,8 @@ + # + # CONFIG_USB_ISP116X_HCD is not set + CONFIG_USB_OHCI_HCD=y +-# CONFIG_USB_OHCI_BIG_ENDIAN is not set ++# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set ++# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set + CONFIG_USB_OHCI_LITTLE_ENDIAN=y + # CONFIG_USB_SL811_HCD is not set +  +@@ -877,6 +902,7 @@ + # CONFIG_USB_ATI_REMOTE2 is not set + # CONFIG_USB_KEYSPAN_REMOTE is not set + # CONFIG_USB_APPLETOUCH is not set ++# CONFIG_USB_GTCO is not set -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 + # + # USB Imaging devices +@@ -914,6 +940,7 @@ + # CONFIG_USB_RIO500 is not set + # CONFIG_USB_LEGOTOWER is not set + # CONFIG_USB_LCD is not set ++# CONFIG_USB_BERRY_CHARGE is not set + # CONFIG_USB_LED is not set + # CONFIG_USB_CYPRESS_CY7C63 is not set + # CONFIG_USB_CYTHERM is not set +@@ -923,6 +950,7 @@ + # CONFIG_USB_APPLEDISPLAY is not set + # CONFIG_USB_LD is not set + # CONFIG_USB_TRANCEVIBRATOR is not set ++# CONFIG_USB_IOWARRIOR is not set + # CONFIG_USB_TEST is not set +  + # +@@ -959,7 +987,6 @@ + # CONFIG_MMC_DEBUG is not set + CONFIG_MMC_BLOCK=y + CONFIG_MMC_AT91=m +-# CONFIG_MMC_TIFM_SD is not set +  + # + # Real Time Clock +@@ -1136,15 +1163,16 @@ + # CONFIG_DEBUG_FS is not set + # CONFIG_HEADERS_CHECK is not set + CONFIG_DEBUG_KERNEL=y ++# CONFIG_DEBUG_SHIRQ is not set + CONFIG_LOG_BUF_SHIFT=14 + CONFIG_DETECT_SOFTLOCKUP=y + # CONFIG_SCHEDSTATS is not set ++# CONFIG_TIMER_STATS is not set + # CONFIG_DEBUG_SLAB is not set + # CONFIG_DEBUG_RT_MUTEXES is not set + # CONFIG_RT_MUTEX_TESTER is not set + # CONFIG_DEBUG_SPINLOCK is not set + # CONFIG_DEBUG_MUTEXES is not set +-# CONFIG_DEBUG_RWSEMS is not set + # CONFIG_DEBUG_SPINLOCK_SLEEP is not set + # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set + # CONFIG_DEBUG_KOBJECT is not set +@@ -1155,6 +1183,7 @@ + CONFIG_FRAME_POINTER=y + CONFIG_FORCED_INLINING=y + # CONFIG_RCU_TORTURE_TEST is not set ++# CONFIG_FAULT_INJECTION is not set + CONFIG_DEBUG_USER=y + # CONFIG_DEBUG_ERRORS is not set + CONFIG_DEBUG_LL=y +@@ -1180,5 +1209,7 @@ + CONFIG_CRC32=y + # CONFIG_LIBCRC32C is not set + CONFIG_ZLIB_INFLATE=y ++CONFIG_ZLIB_DEFLATE=y + CONFIG_PLIST=y +-CONFIG_IOMAP_COPY=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT=y +Index: linux-2.6.22.1/arch/avr32/kernel/setup.c +=================================================================== +--- linux-2.6.22.1/arch/avr32/kernel/setup.c	(revision 1) ++++ linux-2.6.22.1/arch/avr32/kernel/setup.c	(arbetskopia) +@@ -313,7 +313,7 @@ +  + 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 @@ + 		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 +Index: linux-2.6.22.1/arch/avr32/kernel/dma-controller.c +=================================================================== +--- linux-2.6.22.1/arch/avr32/kernel/dma-controller.c	(revision 0) ++++ linux-2.6.22.1/arch/avr32/kernel/dma-controller.c	(revision 0)  @@ -0,0 +1,34 @@  +/*  + * Preliminary DMA controller framework for AVR32 @@ -2309,33 +8633,23 @@ index 0000000..fb654b3  +	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; - 	} +Index: linux-2.6.22.1/arch/avr32/kernel/Makefile +=================================================================== +--- linux-2.6.22.1/arch/avr32/kernel/Makefile	(revision 1) ++++ linux-2.6.22.1/arch/avr32/kernel/Makefile	(arbetskopia) +@@ -9,6 +9,7 @@ + obj-y				+= setup.o traps.o semaphore.o ptrace.o + obj-y				+= signal.o sys_avr32.o process.o time.o + obj-y				+= init_task.o switch_to.o cpu.o ++obj-y				+= dma-controller.o + obj-$(CONFIG_MODULES)		+= module.o avr32_ksyms.o + obj-$(CONFIG_KPROBES)		+= kprobes.o --	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 +Index: linux-2.6.22.1/arch/avr32/mach-at32ap/Kconfig +=================================================================== +--- linux-2.6.22.1/arch/avr32/mach-at32ap/Kconfig	(revision 1) ++++ linux-2.6.22.1/arch/avr32/mach-at32ap/Kconfig	(arbetskopia) +@@ -26,6 +26,13 @@   endchoice @@ -2349,67 +8663,11 @@ index eb30783..43c5b9f 100644   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 @@ +Index: linux-2.6.22.1/arch/avr32/mach-at32ap/at32ap7000.c +=================================================================== +--- linux-2.6.22.1/arch/avr32/mach-at32ap/at32ap7000.c	(revision 1) ++++ linux-2.6.22.1/arch/avr32/mach-at32ap/at32ap7000.c	(arbetskopia) +@@ -17,15 +17,21 @@   #include <asm/arch/at32ap7000.h>   #include <asm/arch/board.h>   #include <asm/arch/portmux.h> @@ -2422,17 +8680,18 @@ index 4dda42d..1130c8a 100644   #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 = {				\ + 		.start		= base,			\ +@@ -88,6 +94,8 @@   	.index		= _index,				\   } @@ -2441,7 +8700,7 @@ index 4dda42d..1130c8a 100644   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) +@@ -104,11 +112,11 @@   {   	unsigned long div, mul, rate; @@ -2456,7 +8715,7 @@ index 4dda42d..1130c8a 100644   	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) +@@ -121,7 +129,7 @@   {   	u32 control; @@ -2465,7 +8724,7 @@ index 4dda42d..1130c8a 100644   	return pll_get_rate(clk, control);   } -@@ -130,7 +138,7 @@ static unsigned long pll1_get_rate(struct clk *clk) +@@ -130,7 +138,7 @@   {   	u32 control; @@ -2474,7 +8733,7 @@ index 4dda42d..1130c8a 100644   	return pll_get_rate(clk, control);   } -@@ -187,108 +195,139 @@ static unsigned long bus_clk_get_rate(struct clk *clk, unsigned int shift) +@@ -187,108 +195,139 @@   static void cpu_clk_mode(struct clk *clk, int enabled)   { @@ -2646,7 +8905,7 @@ index 4dda42d..1130c8a 100644   	return bus_clk_get_rate(clk, shift);   } -@@ -296,6 +335,7 @@ static unsigned long pbb_clk_get_rate(struct clk *clk) +@@ -296,6 +335,7 @@   static struct clk cpu_clk = {   	.name		= "cpu",   	.get_rate	= cpu_clk_get_rate, @@ -2654,7 +8913,7 @@ index 4dda42d..1130c8a 100644   	.users		= 1,   };   static struct clk hsb_clk = { -@@ -327,12 +367,12 @@ static void genclk_mode(struct clk *clk, int enabled) +@@ -327,12 +367,12 @@   {   	u32 control; @@ -2671,7 +8930,7 @@ index 4dda42d..1130c8a 100644   }   static unsigned long genclk_get_rate(struct clk *clk) -@@ -340,9 +380,9 @@ static unsigned long genclk_get_rate(struct clk *clk) +@@ -340,9 +380,9 @@   	u32 control;   	unsigned long div = 1; @@ -2684,7 +8943,7 @@ index 4dda42d..1130c8a 100644   	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) +@@ -353,23 +393,22 @@   	unsigned long parent_rate, actual_rate, div;   	parent_rate = clk->parent->get_rate(clk->parent); @@ -2714,7 +8973,7 @@ index 4dda42d..1130c8a 100644   	return actual_rate;   } -@@ -378,24 +417,24 @@ int genclk_set_parent(struct clk *clk, struct clk *parent) +@@ -378,24 +417,24 @@   {   	u32 control; @@ -2747,7 +9006,7 @@ index 4dda42d..1130c8a 100644   	clk->parent = parent;   	return 0; -@@ -408,11 +447,11 @@ static void __init genclk_init_parent(struct clk *clk) +@@ -408,11 +447,11 @@   	BUG_ON(clk->index > 7); @@ -2763,7 +9022,7 @@ index 4dda42d..1130c8a 100644   	clk->parent = parent;   } -@@ -420,21 +459,53 @@ static void __init genclk_init_parent(struct clk *clk) +@@ -420,21 +459,53 @@   /* --------------------------------------------------------------------    *  System peripherals    * -------------------------------------------------------------------- */ @@ -2772,12 +9031,6 @@ index 4dda42d..1130c8a 100644  -	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, @@ -2786,7 +9039,11 @@ index 4dda42d..1130c8a 100644  +	},  +	IRQ(20),   }; --static struct clk at32_sm_pclk = { +-struct platform_device at32_sm_device = { +-	.name		= "sm", +-	.id		= 0, +-	.resource	= sm_resource, +-	.num_resources	= ARRAY_SIZE(sm_resource),  +  +static struct resource at32ap700x_rtc0_resource[] = {  +	{ @@ -2795,7 +9052,8 @@ index 4dda42d..1130c8a 100644  +		.flags	= IORESOURCE_MEM,  +	},  +	IRQ(21), -+}; + }; +-static struct clk at32_sm_pclk = {  +  +static struct resource at32_wdt0_resource[] = {  +	{ @@ -2830,7 +9088,7 @@ index 4dda42d..1130c8a 100644   	.parent		= &pbb_clk,   	.mode		= pbb_clk_mode,   	.get_rate	= pbb_clk_get_rate, -@@ -491,6 +562,17 @@ static struct clk pico_clk = { +@@ -491,6 +562,17 @@   	.users		= 1,   }; @@ -2848,7 +9106,7 @@ index 4dda42d..1130c8a 100644   /* --------------------------------------------------------------------    * HMATRIX    * -------------------------------------------------------------------- */ -@@ -583,12 +665,14 @@ DEV_CLK(mck, pio4, pba, 14); +@@ -583,12 +665,14 @@   void __init at32_add_system_devices(void)   { @@ -2866,7 +9124,7 @@ index 4dda42d..1130c8a 100644   	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) +@@ -894,6 +978,83 @@   }   /* -------------------------------------------------------------------- @@ -2950,7 +9208,7 @@ index 4dda42d..1130c8a 100644    *  LCDC    * -------------------------------------------------------------------- */   static struct atmel_lcdfb_info atmel_lcdfb0_data; -@@ -1013,6 +1174,228 @@ err_dup_modedb: +@@ -1013,6 +1174,228 @@   }   /* -------------------------------------------------------------------- @@ -3179,7 +9437,7 @@ index 4dda42d..1130c8a 100644    *  GCLK    * -------------------------------------------------------------------- */   static struct clk gclk0 = { -@@ -1066,7 +1449,7 @@ struct clk *at32_clock_list[] = { +@@ -1066,7 +1449,7 @@   	&hsb_clk,   	&pba_clk,   	&pbb_clk, @@ -3188,7 +9446,7 @@ index 4dda42d..1130c8a 100644   	&at32_intc0_pclk,   	&hmatrix_clk,   	&ebi_clk, -@@ -1075,6 +1458,7 @@ struct clk *at32_clock_list[] = { +@@ -1075,6 +1458,7 @@   	&smc0_mck,   	&pdc_hclk,   	&pdc_pclk, @@ -3196,7 +9454,7 @@ index 4dda42d..1130c8a 100644   	&pico_clk,   	&pio0_mck,   	&pio1_mck, -@@ -1092,8 +1476,18 @@ struct clk *at32_clock_list[] = { +@@ -1092,8 +1476,18 @@   	&macb1_pclk,   	&atmel_spi0_spi_clk,   	&atmel_spi1_spi_clk, @@ -3215,7 +9473,7 @@ index 4dda42d..1130c8a 100644   	&gclk0,   	&gclk1,   	&gclk2, -@@ -1113,18 +1507,20 @@ void __init at32_portmux_init(void) +@@ -1113,18 +1507,20 @@   void __init at32_clock_init(void)   { @@ -3241,7 +9499,7 @@ index 4dda42d..1130c8a 100644   		pll1.parent = &osc1;   	genclk_init_parent(&gclk0); -@@ -1133,6 +1529,7 @@ void __init at32_clock_init(void) +@@ -1133,6 +1529,7 @@   	genclk_init_parent(&gclk3);   	genclk_init_parent(&gclk4);   	genclk_init_parent(&atmel_lcdfb0_pixclk); @@ -3249,7 +9507,7 @@ index 4dda42d..1130c8a 100644   	/*   	 * Turn on all clocks that have at least one user already, and -@@ -1157,8 +1554,8 @@ void __init at32_clock_init(void) +@@ -1157,8 +1554,8 @@   			pbb_mask |= 1 << clk->index;   	} @@ -3262,11 +9520,10 @@ index 4dda42d..1130c8a 100644  +	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 +Index: linux-2.6.22.1/arch/avr32/mach-at32ap/cpufreq.c +=================================================================== +--- linux-2.6.22.1/arch/avr32/mach-at32ap/cpufreq.c	(revision 0) ++++ linux-2.6.22.1/arch/avr32/mach-at32ap/cpufreq.c	(revision 0)  @@ -0,0 +1,112 @@  +/*  + * Copyright (C) 2004-2007 Atmel Corporation @@ -3380,304 +9637,10 @@ index 0000000..235524b  +}  +  +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 +Index: linux-2.6.22.1/arch/avr32/mach-at32ap/gpio-dev.c +=================================================================== +--- linux-2.6.22.1/arch/avr32/mach-at32ap/gpio-dev.c	(revision 0) ++++ linux-2.6.22.1/arch/avr32/mach-at32ap/gpio-dev.c	(revision 0)  @@ -0,0 +1,570 @@  +/*  + * GPIO /dev and configfs interface @@ -4249,98 +10212,302 @@ index 0000000..3d4810d  +	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(); - } +Index: linux-2.6.22.1/arch/avr32/mach-at32ap/extint.c +=================================================================== +--- linux-2.6.22.1/arch/avr32/mach-at32ap/extint.c	(revision 1) ++++ linux-2.6.22.1/arch/avr32/mach-at32ap/extint.c	(arbetskopia) +@@ -17,42 +17,83 @@ -+#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; -+} + #include <asm/io.h> +  +-#include <asm/arch/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 +  +-#include "sm.h" ++/* Bitfields in TEST */ ++#define EIC_TESTEN_OFFSET			31 ++#define EIC_TESTEN_SIZE				1 +  +-static void eim_ack_irq(unsigned int irq) ++/* Bitfields in NMIC */ ++#define EIC_EN_OFFSET				0 ++#define EIC_EN_SIZE				1  + -+int at32_select_gpio_pins(unsigned int port, u32 pins, u32 oe_mask) -+{ -+	struct pio_device *pio; -+	u32 old, new; ++/* 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))  + -+	pio = &pio_dev[port]; -+	BUG_ON(port > ARRAY_SIZE(pio_dev) || !pio->regs || (oe_mask & ~pins)); ++/* 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)  + -+	/* Try to allocate the pins */ -+	do { -+		old = pio->pinmux_mask; -+		if (old & pins) -+			return -EBUSY; ++struct eic { ++	void __iomem *regs; ++	struct irq_chip *chip; ++	unsigned int first_irq; ++};  + -+		new = old | pins; -+	} while (cmpxchg(&pio->pinmux_mask, old, new) != old); ++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 @@ + 		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 @@ + 	} +  + 	if (ret == 0) { +-		sm_writel(sm, EIM_MODE, mode); +-		sm_writel(sm, EIM_EDGE, edge); +-		sm_writel(sm, EIM_LEVEL, level); ++		eic_writel(eic, MODE, mode); ++		eic_writel(eic, EDGE, edge); ++		eic_writel(eic, LEVEL, level); +  + 		if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) + 			flow_type |= IRQ_LEVEL; +@@ -99,35 +139,33 @@ + 		desc->status |= flow_type; + 	} +  +-	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 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; ++	}  + -+	/* That went well, now configure the port */ -+	pio_writel(pio, OER, oe_mask); -+	pio_writel(pio, PER, pins); ++	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_eic_irq); ++	set_irq_data(int_irq, eic); +  +-	set_irq_chained_handler(int_irq, demux_eim_irq); +-	set_irq_data(int_irq, sm); ++	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); +  +-	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);  +	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 0; ++err_ioremap: ++	kfree(eic); ++err_kzalloc: ++	return ret; + } +-arch_initcall(eim_init);  + -+	return pio_readl(pio, PDSR) & pins; -+} ++static struct platform_driver eic_driver = { ++	.driver = { ++		.name = "at32_eic", ++	}, ++};  + -+void at32_gpio_set_value_multiple(unsigned int port, u32 value, u32 mask) ++static int __init eic_init(void)  +{ -+	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); ++	return platform_driver_probe(&eic_driver, eic_probe);  +} -+ -+#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 ++arch_initcall(eic_init); +Index: linux-2.6.22.1/arch/avr32/mach-at32ap/pm.h +=================================================================== +--- linux-2.6.22.1/arch/avr32/mach-at32ap/pm.h	(revision 0) ++++ linux-2.6.22.1/arch/avr32/mach-at32ap/pm.h	(revision 0)  @@ -0,0 +1,112 @@  +/*  + * Register definitions for the Power Manager (PM) @@ -4454,11 +10621,10 @@ index 0000000..a1f8ace  +	__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 +Index: linux-2.6.22.1/arch/avr32/mach-at32ap/sm.h +=================================================================== +--- linux-2.6.22.1/arch/avr32/mach-at32ap/sm.h	(revision 1) ++++ linux-2.6.22.1/arch/avr32/mach-at32ap/sm.h	(arbetskopia)  @@ -1,242 +0,0 @@  -/*  - * Register definitions for SM @@ -4702,11 +10868,1118 @@ index cad02b5..0000000  -	__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, +Index: linux-2.6.22.1/arch/avr32/mach-at32ap/pio.c +=================================================================== +--- linux-2.6.22.1/arch/avr32/mach-at32ap/pio.c	(revision 1) ++++ linux-2.6.22.1/arch/avr32/mach-at32ap/pio.c	(arbetskopia) +@@ -158,6 +158,82 @@ + 	dump_stack(); + } +  ++#ifdef CONFIG_GPIO_DEV ++ ++/* Gang allocators and accessors; used by the GPIO /dev driver */ ++int at32_gpio_port_is_valid(unsigned int port) ++{ ++	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 */ +Index: linux-2.6.22.1/arch/avr32/mach-at32ap/at32ap.c +=================================================================== +--- linux-2.6.22.1/arch/avr32/mach-at32ap/at32ap.c	(revision 1) ++++ linux-2.6.22.1/arch/avr32/mach-at32ap/at32ap.c	(arbetskopia) +@@ -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(); + } +Index: linux-2.6.22.1/arch/avr32/mach-at32ap/Makefile +=================================================================== +--- linux-2.6.22.1/arch/avr32/mach-at32ap/Makefile	(revision 1) ++++ linux-2.6.22.1/arch/avr32/mach-at32ap/Makefile	(arbetskopia) +@@ -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 +Index: linux-2.6.22.1/arch/avr32/Kconfig +=================================================================== +--- linux-2.6.22.1/arch/avr32/Kconfig	(revision 1) ++++ linux-2.6.22.1/arch/avr32/Kconfig	(arbetskopia) +@@ -113,6 +113,13 @@ + 	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 @@ + 	  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 @@ +  + 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 +Index: linux-2.6.22.1/arch/avr32/configs/atngw100_defconfig +=================================================================== +--- linux-2.6.22.1/arch/avr32/configs/atngw100_defconfig	(revision 1) ++++ linux-2.6.22.1/arch/avr32/configs/atngw100_defconfig	(arbetskopia) +@@ -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_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_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_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_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_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_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_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_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 @@ + # + # Misc devices + # +-# CONFIG_BLINK is not set + # CONFIG_IDE is not set +  + # +@@ -545,13 +571,26 @@ + # 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 @@ + # 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,9 +683,44 @@ + # 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=y +@@ -655,7 +737,7 @@ + # 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 @@ + # + # 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,9 +853,53 @@ + # + # 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 + # + # CONFIG_DMA_ENGINE is not set +@@ -767,7 +931,8 @@ + # 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_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 +Index: linux-2.6.22.1/arch/avr32/configs/atstk1002_defconfig +=================================================================== +--- linux-2.6.22.1/arch/avr32/configs/atstk1002_defconfig	(revision 1) ++++ linux-2.6.22.1/arch/avr32/configs/atstk1002_defconfig	(arbetskopia) +@@ -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_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_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_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_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_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_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 @@ + # + # 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 @@ + # + # Misc devices + # +-# CONFIG_BLINK is not set ++CONFIG_ATMEL_SSC=m + # CONFIG_IDE is not set +  + # +@@ -397,13 +427,26 @@ + # 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,9 +486,44 @@ + # + # 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 + # + # CONFIG_SERIO is not set +@@ -477,7 +555,15 @@ + # 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,15 +574,63 @@ + # 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 + # + # CONFIG_W1 is not set +@@ -517,21 +651,93 @@ + # + # 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 + # + # CONFIG_USB_ARCH_HAS_HCD is not set +@@ -545,21 +751,59 @@ + # + # 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,9 +816,52 @@ + # + # 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 + # + # CONFIG_DMA_ENGINE is not set +@@ -590,11 +877,14 @@ + # + # 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_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_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_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 +Index: linux-2.6.22.1/arch/avr32/mm/dma-coherent.c +=================================================================== +--- linux-2.6.22.1/arch/avr32/mm/dma-coherent.c	(revision 1) ++++ linux-2.6.22.1/arch/avr32/mm/dma-coherent.c	(arbetskopia) +@@ -41,6 +41,13 @@   	struct page *page, *free, *end;   	int order; @@ -4720,59 +11993,546 @@ index 099212d..26f29c6 100644   	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 +Index: linux-2.6.22.1/arch/avr32/boards/atngw100/Kconfig +=================================================================== +--- linux-2.6.22.1/arch/avr32/boards/atngw100/Kconfig	(revision 0) ++++ linux-2.6.22.1/arch/avr32/boards/atngw100/Kconfig	(revision 0) +@@ -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. +Index: linux-2.6.22.1/arch/avr32/boards/atngw100/setup.c +=================================================================== +--- linux-2.6.22.1/arch/avr32/boards/atngw100/setup.c	(revision 1) ++++ linux-2.6.22.1/arch/avr32/boards/atngw100/setup.c	(arbetskopia) +@@ -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> - 	  Say N if you are unsure. + /* Initialized by bootloader-specific startup code. */ + struct tag *bootloader_tags __initdata; +@@ -39,6 +42,11 @@ + 	}, + }; -+# AVR32 Architecture ++static struct mci_platform_data __initdata mci0_data = { ++	.detect_pin	= GPIO_PIN_PC(25), ++	.wp_pin		= GPIO_PIN_PE(0), ++};  + -+config AT32AP700X_WDT -+	tristate "AT32AP700x watchdog" -+	depends on WATCHDOG && CPU_AT32AP7000 + /* +  * 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 @@ + 	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,7 +161,23 @@ + 	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; + } + postcore_initcall(atngw100_init); +Index: linux-2.6.22.1/arch/avr32/boards/atstk1000/Kconfig +=================================================================== +--- linux-2.6.22.1/arch/avr32/boards/atstk1000/Kconfig	(revision 0) ++++ linux-2.6.22.1/arch/avr32/boards/atstk1000/Kconfig	(revision 0) +@@ -0,0 +1,95 @@ ++# STK1000 customization ++ ++if BOARD_ATSTK1002 ++ ++config BOARD_ATSTK1002_CUSTOM ++	bool "Non-default STK-1002 jumper settings"  +	help -+	  Watchdog timer embedded into AT32AP700x devices. This will reboot -+	  your system when the timeout is reached. ++	  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.  + -+config AT32AP700X_WDT_TIMEOUT -+	int "Timeout value for AT32AP700x watchdog" -+	depends on AT32AP700X_WDT -+	default "2" -+	range 1 2 ++if BOARD_ATSTK1002_CUSTOM ++ ++config BOARD_ATSTK1002_SW1_CUSTOM ++	bool "SW1: use SSC1 (not SPI0)"  +	help -+	  Sets the timeout value for the watchdog in AT32AP700x devices. -+	  Limited by hardware to be 1 or 2 seconds. ++	  This also prevents using the external DAC as an audio interface, ++	  and means you can't initialize the on-board QVGA display.  + -+	  Set to 2 seconds by default. ++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.  + - # X86 (i386 + ia64 + x86_64) Architecture ++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_GPIO_MOUSE ++	bool "Configure gpio_mouse on GPIO J1 header" ++	depends on !BOARD_ATSTK1002_SW4_CUSTOM ++	help ++	  Enable gpio_mouse board configuration on GPIO 0 to 7. Connecting a ++	  10-pin flat cable from J1 (GPIO) to J25 (SWITCH) will let a user give ++	  mouse inputs using the the switches SW0 to SW7. ++ ++	  SW0: right ++	  SW1: down ++	  SW2: up ++	  SW3: left ++	  SW5: right button ++	  SW6: middle button ++	  SW7: left button ++ ++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 +Index: linux-2.6.22.1/arch/avr32/boards/atstk1000/atstk1002.c +=================================================================== +--- linux-2.6.22.1/arch/avr32/boards/atstk1000/atstk1002.c	(revision 1) ++++ linux-2.6.22.1/arch/avr32/boards/atstk1000/atstk1002.c	(arbetskopia) +@@ -11,10 +11,13 @@ + #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 <linux/gpio_mouse.h> - 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 + #include <video/atmel_lcdc.h> -+# AVR32 Architecture -+obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o +@@ -27,17 +30,48 @@ +  + #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  + - # 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 @@ ++#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", + 		.max_speed_hz	= 16000000, +@@ -45,7 +79,62 @@ + 		.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, ++}; ++ ++#ifdef CONFIG_BOARD_ATSTK1002_GPIO_MOUSE ++static struct gpio_mouse_platform_data gpio_mouse0_data = { ++	.polarity	= GPIO_MOUSE_POLARITY_ACT_LOW, ++	{ ++		{ ++			.up		= GPIO_PIN_PB(2), ++			.down		= GPIO_PIN_PB(1), ++			.left		= GPIO_PIN_PB(3), ++			.right		= GPIO_PIN_PB(0), ++			.bleft		= GPIO_PIN_PB(7), ++			.bmiddle	= GPIO_PIN_PB(6), ++			.bright		= GPIO_PIN_PB(5), ++		}, ++	}, ++	.scan_ms	= 10, ++}; ++ ++static struct platform_device gpio_mouse0_device = { ++	.name		= "gpio_mouse", ++	.id		= 0, ++	.dev		= { ++		.platform_data = &gpio_mouse0_data, ++	}, ++}; ++ ++static void __init add_device_gpio_mouse0(void) ++{ ++	struct platform_device *pdev = &gpio_mouse0_device; ++	struct gpio_mouse_platform_data *data = pdev->dev.platform_data; ++ ++	at32_select_gpio(data->up, 0); ++	at32_select_gpio(data->down, 0); ++	at32_select_gpio(data->left, 0); ++	at32_select_gpio(data->right, 0); ++ ++	at32_select_gpio(data->bleft, 0); ++	at32_select_gpio(data->bmiddle, 0); ++	at32_select_gpio(data->bright, 0); ++ ++	platform_device_register(pdev); ++} ++#endif ++ + /* +  * The next two functions should go away as the boot loader is +  * supposed to initialize the macb address registers with a valid +@@ -101,12 +190,103 @@ + 	clk_put(pclk); + } +  ++#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) ++{ ++	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	SW2_DEFAULT ++#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 */ +-#else +-	at32_map_usart(0, 1);	/* USART 0/B: /dev/ttyS1, IRDA */ + #endif + 	/* USART 2/unused: expansion connector */ + 	at32_map_usart(3, 2);	/* USART 3/C: /dev/ttyS2, DB9 */ +@@ -140,19 +320,51 @@ +  + 	at32_add_system_devices(); +  +-#ifdef	SW2_DEFAULT ++#ifdef	CONFIG_BOARD_ATSTK1002_SW2_CUSTOM ++	at32_add_device_usart(1); ++#else + 	at32_add_device_usart(0); +-#else +-	at32_add_device_usart(1); + #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 ++ ++#ifdef CONFIG_BOARD_ATSTK1002_GPIO_MOUSE ++	add_device_gpio_mouse0(); ++#endif ++ + 	return 0; + } + postcore_initcall(atstk1002_init); +Index: linux-2.6.22.1/arch/avr32/Makefile +=================================================================== +--- linux-2.6.22.1/arch/avr32/Makefile	(revision 1) ++++ linux-2.6.22.1/arch/avr32/Makefile	(arbetskopia) +@@ -31,6 +31,7 @@ + core-$(CONFIG_LOADER_U_BOOT)		+= arch/avr32/boot/u-boot/ + core-y					+= arch/avr32/kernel/ + core-y					+= arch/avr32/mm/ ++drivers-y				+= arch/avr32/drivers/ + libs-y					+= arch/avr32/lib/ +  + archincdir-$(CONFIG_PLATFORM_AT32AP)	:= arch-at32ap +Index: linux-2.6.22.1/arch/avr32/drivers/dw-dmac.h +=================================================================== +--- linux-2.6.22.1/arch/avr32/drivers/dw-dmac.h	(revision 0) ++++ linux-2.6.22.1/arch/avr32/drivers/dw-dmac.h	(revision 0) +@@ -0,0 +1,42 @@  +/* -+ * Watchdog driver for Atmel AT32AP700X devices ++ * Driver for the Synopsys DesignWare DMA Controller  + *  + * Copyright (C) 2005-2006 Atmel Corporation  + * @@ -4780,882 +12540,2367 @@ index 0000000..9b598d9  + * 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__ */ +Index: linux-2.6.22.1/arch/avr32/drivers/Makefile +=================================================================== +--- linux-2.6.22.1/arch/avr32/drivers/Makefile	(revision 0) ++++ linux-2.6.22.1/arch/avr32/drivers/Makefile	(revision 0) +@@ -0,0 +1 @@ ++obj-$(CONFIG_DW_DMAC)			+= dw-dmac.o +Index: linux-2.6.22.1/arch/avr32/drivers/dw-dmac.c +=================================================================== +--- linux-2.6.22.1/arch/avr32/drivers/dw-dmac.c	(revision 0) ++++ linux-2.6.22.1/arch/avr32/drivers/dw-dmac.c	(revision 0) +@@ -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/kernel.h> ++#include <linux/interrupt.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 ++#include <asm/dma-controller.h> ++#include <asm/io.h>  + -+/* 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 ++#include "dw-dmac.h"  + -+#define WDT_CLR			0x04 ++#define DMAC_NR_CHANNELS 3 ++#define DMAC_MAX_BLOCKSIZE 4095  + -+#define WDT_BIT(name)		(1 << WDT_##name) -+#define WDT_BF(name,value)	((value) << WDT_##name) ++enum { ++	CH_STATE_FREE = 0, ++	CH_STATE_ALLOCATED, ++	CH_STATE_BUSY, ++};  + -+#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 dw_dma_lli { ++	dma_addr_t	sar; ++	dma_addr_t	dar; ++	dma_addr_t	llp; ++	u32		ctllo; ++	u32		ctlhi; ++	u32		sstat; ++	u32		dstat; ++};  + -+struct wdt_at32ap700x { -+	void __iomem		*regs; -+	int			timeout; -+	int			users; -+	struct miscdevice	miscdev; ++struct dw_dma_block { ++	struct dw_dma_lli *lli_vaddr; ++	dma_addr_t lli_dma_addr;  +};  + -+static struct wdt_at32ap700x *wdt; ++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; ++};  + -+/* -+ * 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)); -+} ++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)  + -+/* -+ * Enable and reset the watchdog. -+ */ -+static void inline at32_wdt_start(void) ++#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)  +{ -+	/* 0xf is 2^16 divider = 2 sec, 0xe is 2^15 divider = 1 sec */ -+	unsigned long psel = (wdt->timeout > 1) ? 0xf : 0xe; ++	struct dw_dma_controller *dmac = to_dw_dmac(_dmac); ++	struct dw_dma_channel *chan; ++	unsigned long flags; ++	int i;  + -+	wdt_writel(wdt, CTRL, WDT_BIT(CTRL_EN) -+			| WDT_BF(CTRL_PSEL, psel) -+			| WDT_BF(CTRL_KEY, 0x55)); -+	wdt_writel(wdt, CTRL, WDT_BIT(CTRL_EN) -+			| WDT_BF(CTRL_PSEL, psel) -+			| WDT_BF(CTRL_KEY, 0xaa)); ++	spin_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;  +}  + -+/* -+ * Pat the watchdog timer. -+ */ -+static void inline at32_wdt_pat(void) ++static void dmac_release_channel(struct dma_controller *_dmac, int channel)  +{ -+	wdt_writel(wdt, CLR, 0x42); ++	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;  +}  + -+/* -+ * Watchdog device is opened, and watchdog starts running. -+ */ -+static int at32_wdt_open(struct inode *inode, struct file *file) ++static struct dw_dma_block *allocate_blocks(struct dw_dma_controller *dmac, ++					    unsigned int nr_blocks)  +{ -+	if (test_and_set_bit(1, &wdt->users)) -+		return -EBUSY; ++	struct dw_dma_block *block; ++	void *p; ++	unsigned int i;  + -+	at32_wdt_start(); -+	return nonseekable_open(inode, file); ++	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;  +}  + -+/* -+ * 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) ++static void cleanup_channel(struct dw_dma_controller *dmac, ++			    struct dw_dma_channel *chan)  +{ -+#ifndef CONFIG_WATCHDOG_NOWAYOUT -+	at32_wdt_stop(); -+#endif -+	clear_bit(1, &wdt->users); -+	return 0; ++	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;  +}  + -+/* -+ * Change the watchdog time interval. -+ */ -+static int at32_wdt_settimeout(int time) ++static int dmac_prepare_request_sg(struct dma_controller *_dmac, ++				   struct dma_request_sg *req)  +{ -+	/* -+	 * 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)) ++	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;  +  +	/* -+	 * Set new watchdog time. It will be used when at32_wdt_start() is -+	 * called. ++	 * We have marked the channel as busy, so no need to keep the ++	 * lock as long as we only touch the channel-specific ++	 * registers  +	 */ -+	wdt->timeout = time; -+	return 0; -+} ++	spin_unlock_irqrestore(&dmac->lock, flags);  + -+static struct watchdog_info at32_wdt_info = { -+	.identity	= "at32ap700x watchdog", -+	.options	= WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, -+}; ++	/* ++	 * 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);  + -+/* -+ * 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; ++	BUG_ON(nr_blocks == 0); ++	chan->nr_blocks = nr_blocks;  + -+	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); ++	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 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; ++ ++	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 ssize_t at32_wdt_write(struct file *file, const char *data, size_t len, -+				loff_t *ppos) ++static int dmac_prepare_request_cyclic(struct dma_controller *_dmac, ++                                       struct dma_request_cyclic *req)  +{ -+	at32_wdt_pat(); -+	return len; -+} ++	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;  + -+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, -+}; ++	spin_lock_irqsave(&dmac->lock, flags);  + -+static int __init at32_wdt_probe(struct platform_device *pdev) -+{ -+	struct resource	*regs; -+	int ret; ++        block_size = (req->buffer_size/req->periods) >> req->width;  + -+	if (wdt) { -+		dev_dbg(&pdev->dev, "only 1 wdt instance supported.\n"); -+		return -EBUSY; ++	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;  +	}  + -+	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+	if (!regs) { -+		dev_dbg(&pdev->dev, "missing mmio resource\n"); -+		return -ENXIO; -+	} ++	chan = &dmac->channel[req->req.channel]; ++	chan->state = CH_STATE_BUSY; ++	chan->is_cyclic = 1; ++        chan->req_cyclic = req;  + -+	wdt = kzalloc(sizeof(struct wdt_at32ap700x), GFP_KERNEL); -+	if (!wdt) { -+		dev_dbg(&pdev->dev, "no memory for wdt structure\n"); -+		return -ENOMEM; ++	/* ++	 * 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;  +	}  + -+	wdt->regs = ioremap(regs->start, regs->end - regs->start + 1); -+	if (!wdt->regs) { ++        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; -+		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; ++		chan->block = allocate_blocks(dmac, req->periods); ++		if (!chan->block) ++			goto out_unclaim_channel;  + -+	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); -+	} ++		if (direction == DMA_TO_DEVICE) ++			ctllo |= 1 << 28 | 1 << 27 | 2 << 7; ++		else ++			ctllo |= 1 << 28 | 1 << 27 | 2 << 9;  + -+	ret = misc_register(&wdt->miscdev); -+	if (ret) { -+		dev_dbg(&pdev->dev, "failed to register wdt miscdev\n"); -+		goto err_iounmap; ++		/* ++		 * 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);  +	}  + -+	platform_set_drvdata(pdev, wdt); -+	wdt->miscdev.parent = &pdev->dev; -+	dev_info(&pdev->dev, "AT32AP700X WDT at 0x%p\n", wdt->regs); ++	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;  + -+err_iounmap: -+	iounmap(wdt->regs); -+err_free: -+	kfree(wdt); -+	wdt = NULL; ++out_unclaim_channel: ++	chan->state = CH_STATE_ALLOCATED;  +	return ret;  +}  + -+static int __exit at32_wdt_remove(struct platform_device *pdev) ++static int dmac_start_request(struct dma_controller *_dmac, ++			      unsigned int channel)  +{ -+	if (wdt && platform_get_drvdata(pdev) == wdt) { -+		misc_deregister(&wdt->miscdev); -+		iounmap(wdt->regs); -+		kfree(wdt); -+		wdt = NULL; -+		platform_set_drvdata(pdev, NULL); -+	} ++	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 void at32_wdt_shutdown(struct platform_device *pdev) ++static dma_addr_t dmac_get_current_pos(struct dma_controller *_dmac, ++                                       unsigned int channel)  +{ -+	at32_wdt_stop(); ++	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;  +}  + -+#ifdef CONFIG_PM -+static int at32_wdt_suspend(struct platform_device *pdev, pm_message_t message) ++ ++static int dmac_stop_request(struct dma_controller *_dmac, ++                             unsigned int channel)  +{ -+	at32_wdt_stop(); ++	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 int at32_wdt_resume(struct platform_device *pdev) ++ ++static void dmac_block_complete(struct dw_dma_controller *dmac)  +{ -+	if (wdt->users) -+		at32_wdt_start(); ++	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;  +} -+#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, ++static struct platform_driver dmac_driver = { ++	.probe		= dmac_probe,  +	.driver		= { -+		.name	= "at32_wdt", -+		.owner	= THIS_MODULE, ++		.name		= "dmaca",  +	}, -+	.shutdown	= at32_wdt_shutdown,  +};  + -+static int __init at32_wdt_init(void) ++static int __init dmac_init(void)  +{ -+	return platform_driver_probe(&at32_wdt_driver, at32_wdt_probe); ++	return platform_driver_register(&dmac_driver);  +} -+module_init(at32_wdt_init); ++subsys_initcall(dmac_init);  + -+static void __exit at32_wdt_exit(void) ++static void __exit dmac_exit(void)  +{ -+	platform_driver_unregister(&at32_wdt_driver); ++	platform_driver_unregister(&dmac_driver);  +} -+module_exit(at32_wdt_exit); ++module_exit(dmac_exit);  + -+MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>"); -+MODULE_DESCRIPTION("Watchdog driver for Atmel AT32AP700X"); ++MODULE_DESCRIPTION("Synopsys DesignWare DMA Controller driver"); ++MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>");  +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 @@ +Index: linux-2.6.22.1/drivers/serial/atmel_serial.c +=================================================================== +--- linux-2.6.22.1/drivers/serial/atmel_serial.c	(revision 1) ++++ linux-2.6.22.1/drivers/serial/atmel_serial.c	(arbetskopia) +@@ -7,6 +7,8 @@ +  *  Based on drivers/char/serial_sa1100.c, by Deep Blue Solutions Ltd. +  *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. +  * ++ *  DMA support added by Chip Coldwell. ++ * +  * 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 +@@ -33,6 +35,7 @@ + #include <linux/sysrq.h> + #include <linux/tty_flip.h> + #include <linux/platform_device.h> ++#include <linux/dma-mapping.h> + #include <linux/atmel_pdc.h> - menu "I2C Hardware Bus support" + #include <asm/io.h> +@@ -47,6 +50,11 @@ -+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 + #include "atmel_serial.h" +  ++#define SUPPORT_PDC ++#define PDC_BUFFER_SIZE		(L1_CACHE_BYTES << 3) ++#warning "Revisit" ++#define PDC_RX_TIMEOUT		(3 * 10)		/* 3 bytes */  + -+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. + #if defined(CONFIG_SERIAL_ATMEL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) + #define SUPPORT_SYSRQ + #endif +@@ -107,6 +115,13 @@ + static int (*atmel_open_hook)(struct uart_port *); + static void (*atmel_close_hook)(struct uart_port *); +  ++struct atmel_dma_buffer { ++	unsigned char	*buf; ++	dma_addr_t	dma_addr; ++	size_t		dma_size; ++	unsigned int	ofs; ++};  + - 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 + /* +  * We wrap our port structure around the generic uart_port. +  */ +@@ -114,10 +129,21 @@ + 	struct uart_port	uart;		/* uart */ + 	struct clk		*clk;		/* uart clock */ + 	unsigned short		suspended;	/* is port suspended? */ ++	int			break_active;	/* break being received */ ++ ++	short			use_dma_rx;	/* enable PDC receiver */ ++	short			pdc_rx_idx;	/* current PDC RX buffer */ ++	struct atmel_dma_buffer	pdc_rx[2];	/* PDC receier */ ++ ++	short			use_dma_tx;	/* enable PDC transmitter */ ++	struct atmel_dma_buffer	pdc_tx;		/* PDC transmitter */ + }; - 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 @@ + static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART]; +  ++#define PDC_RX_BUF(port)	&(port)->pdc_rx[(port)->pdc_rx_idx] ++#define PDC_RX_SWITCH(port)	(port)->pdc_rx_idx = !(port)->pdc_rx_idx ++ + #ifdef SUPPORT_SYSRQ + static struct console atmel_console; + #endif +@@ -205,7 +231,12 @@ + { + 	struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port; +  +-	UART_PUT_IDR(port, ATMEL_US_TXRDY); ++	if (atmel_port->use_dma_tx) { ++		UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);		/* disable PDC transmit */ ++		UART_PUT_IDR(port, ATMEL_US_ENDTX | ATMEL_US_TXBUFE); ++	} ++	else ++		UART_PUT_IDR(port, ATMEL_US_TXRDY); + } +  + /* +@@ -215,7 +246,17 @@ + { + 	struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port; +  +-	UART_PUT_IER(port, ATMEL_US_TXRDY); ++	if (atmel_port->use_dma_tx) { ++		if (UART_GET_PTSR(port) & ATMEL_PDC_TXTEN) ++			/* The transmitter is already running.  Yes, we ++			   really need this.*/ ++			return; ++ ++		UART_PUT_IER(port, ATMEL_US_ENDTX | ATMEL_US_TXBUFE); ++		UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);		/* re-enable PDC transmit */ ++	} ++	else ++		UART_PUT_IER(port, ATMEL_US_TXRDY); + } +  + /* +@@ -225,7 +266,12 @@ + { + 	struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port; +  +-	UART_PUT_IDR(port, ATMEL_US_RXRDY); ++	if (atmel_port->use_dma_rx) { ++		UART_PUT_PTCR(port, ATMEL_PDC_RXTDIS);		/* disable PDC receive */ ++		UART_PUT_IDR(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT); ++	} ++	else ++		UART_PUT_IDR(port, ATMEL_US_RXRDY); + } +  + /* +@@ -248,10 +294,139 @@ + } +  + /* ++ * Receive data via the PDC.  A buffer has been fulled. ++ */ ++static void atmel_pdc_endrx(struct uart_port *port) ++{ ++	struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port; ++	struct tty_struct *tty = port->info->tty; ++	struct atmel_dma_buffer *pdc = PDC_RX_BUF(atmel_port); ++	unsigned int count; ++ ++	count = pdc->dma_size - pdc->ofs; ++	if (likely(count > 0)) { ++		dma_sync_single_for_cpu(port->dev, pdc->dma_addr, pdc->dma_size, DMA_FROM_DEVICE); ++		tty_insert_flip_string(tty, pdc->buf + pdc->ofs, count); ++		tty_flip_buffer_push(tty); ++ ++		port->icount.rx += count; ++	} ++ ++	/* Set this buffer as the next receive buffer */ ++	pdc->ofs = 0; ++	UART_PUT_RNPR(port, pdc->dma_addr); ++	UART_PUT_RNCR(port, pdc->dma_size); ++ ++	/* Switch to next buffer */ ++	PDC_RX_SWITCH(atmel_port);		/* next PDC buffer */ ++} ++  +/* -+ * Register definitions for the Atmel Two-Wire Interface ++ * Receive data via the PDC.  At least one byte was received, but the ++ * buffer was not full when the inter-character timeout expired.  + */ ++static void atmel_pdc_timeout(struct uart_port *port) ++{ ++	struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port; ++	struct tty_struct *tty = port->info->tty; ++	struct atmel_dma_buffer *pdc = PDC_RX_BUF(atmel_port); ++	/* unsigned */ int ofs, count;  + -+#ifndef __ASM_AVR32_TWI_H__ -+#define __ASM_AVR32_TWI_H__ ++	ofs = UART_GET_RPR(port) - pdc->dma_addr;	/* current DMA adress */ ++	count = ofs - pdc->ofs;  + -+/* 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 ++	if (likely(count > 0)) { ++		dma_sync_single_for_cpu(port->dev, pdc->dma_addr, pdc->dma_size, DMA_FROM_DEVICE); ++		tty_insert_flip_string(tty, pdc->buf + pdc->ofs, count); ++		tty_flip_buffer_push(tty);  + -+/* 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 ++		pdc->ofs = ofs; ++		port->icount.rx += count; ++	}  + -+/* 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 ++	/* reset the UART timeout */ ++	UART_PUT_CR(port, ATMEL_US_STTTO); ++}  + -+/* Bitfields in SMR */ -+#define TWI_SADR_OFFSET				16 -+#define TWI_SADR_SIZE				7 ++/* ++ * Deal with parity, framing and overrun errors. ++ */ ++static void atmel_pdc_rxerr(struct uart_port *port, unsigned int status) ++{ ++	/* clear error */ ++	UART_PUT_CR(port, ATMEL_US_RSTSTA);  + -+/* Bitfields in IADR */ -+#define TWI_IADR_OFFSET				0 -+#define TWI_IADR_SIZE				24 ++	if (status & ATMEL_US_RXBRK) { ++		status &= ~(ATMEL_US_PARE | ATMEL_US_FRAME);	/* ignore side-effect */ ++		port->icount.brk++; ++	} ++	if (status & ATMEL_US_PARE) ++		port->icount.parity++; ++	if (status & ATMEL_US_FRAME) ++		port->icount.frame++; ++	if (status & ATMEL_US_OVRE) ++		port->icount.overrun++; ++}  + -+/* 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 ++/* ++ * A transmission via the PDC is complete. ++ */ ++static void atmel_pdc_endtx(struct uart_port *port) ++{ ++	struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port; ++	struct circ_buf *xmit = &port->info->xmit; ++	struct atmel_dma_buffer *pdc = &atmel_port->pdc_tx;  + -+/* 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 ++	xmit->tail += pdc->ofs; ++	if (xmit->tail >= SERIAL_XMIT_SIZE) ++		xmit->tail -= SERIAL_XMIT_SIZE;  + -+/* Bitfields in RHR */ -+#define TWI_RXDATA_OFFSET			0 -+#define TWI_RXDATA_SIZE				8 ++	port->icount.tx += pdc->ofs; ++	pdc->ofs = 0;  + -+/* Bitfields in THR */ -+#define TWI_TXDATA_OFFSET			0 -+#define TWI_TXDATA_SIZE				8 ++	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) ++		uart_write_wakeup(port); ++}  + -+/* 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 ++/* ++ * The PDC transmitter is idle, so either start the next transfer or ++ * disable the transmitter. ++ */ ++static void atmel_pdc_txbufe(struct uart_port *port) ++{ ++	struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port; ++	struct circ_buf *xmit = &port->info->xmit; ++	struct atmel_dma_buffer *pdc = &atmel_port->pdc_tx; ++	int count;  + -+/* Bit manipulation macros */ -+#define TWI_BIT(name)					\ -+	(1 << TWI_##name##_OFFSET) -+#define TWI_BF(name,value)				\ -+	(((value) & ((1 << TWI_##name##_SIZE) - 1))	\ -+	 << TWI_##name##_OFFSET) -+#define TWI_BFEXT(name,value)				\ -+	(((value) >> TWI_##name##_OFFSET)		\ -+	 & ((1 << TWI_##name##_SIZE) - 1)) -+#define TWI_BFINS(name,value,old)			\ -+	(((old) & ~(((1 << TWI_##name##_SIZE) - 1)	\ -+		    << TWI_##name##_OFFSET))		\ -+	 | TWI_BF(name,value)) ++	if (!uart_circ_empty(xmit)) { ++		/* more to transmit - setup next transfer */ ++		UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);			/* disable PDC transmit */ ++		dma_sync_single_for_device(port->dev, pdc->dma_addr, pdc->dma_size, DMA_TO_DEVICE);  + -+/* Register access macros */ -+#define twi_readl(port,reg)				\ -+	__raw_readl((port)->regs + TWI_##reg) -+#define twi_writel(port,reg,value)			\ -+	__raw_writel((value), (port)->regs + TWI_##reg) ++		if (xmit->tail < xmit->head) ++			count = xmit->head - xmit->tail; ++		else ++			count = SERIAL_XMIT_SIZE - xmit->tail; ++		pdc->ofs = count; ++ ++		UART_PUT_TPR(port, pdc->dma_addr + xmit->tail); ++		UART_PUT_TCR(port, count); ++		UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);			/* re-enable PDC transmit */ ++	} ++	else { ++		/* nothing left to transmit - disable the transmitter */ ++		UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);			/* disable PDC transmit */ ++		UART_PUT_IDR(port, ATMEL_US_ENDTX | ATMEL_US_TXBUFE); ++	} ++}  + -+#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> +  * Characters received (called from interrupt handler) +  */ + 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 +442,29 @@ + 		 * note that the error handling code is + 		 * out of the main execution path + 		 */ +-		if (unlikely(status & (ATMEL_US_PARE | ATMEL_US_FRAME | ATMEL_US_OVRE | ATMEL_US_RXBRK))) { ++		if (unlikely(status & (ATMEL_US_PARE | ATMEL_US_FRAME ++				       | ATMEL_US_OVRE | ATMEL_US_RXBRK) ++			     || atmel_port->break_active)) { + 			UART_PUT_CR(port, ATMEL_US_RSTSTA);	/* clear error */ +-			if (status & ATMEL_US_RXBRK) { ++			if (status & ATMEL_US_RXBRK ++			    && !atmel_port->break_active) { + 				status &= ~(ATMEL_US_PARE | ATMEL_US_FRAME);	/* ignore side-effect */ + 				port->icount.brk++; ++				atmel_port->break_active = 1; ++				UART_PUT_IER(port, ATMEL_US_RXBRK); + 				if (uart_handle_break(port)) + 					goto ignore_char; ++			} else { ++				/* ++				 * This is either the end-of-break ++				 * condition or we've received at ++				 * least one character without RXBRK ++				 * being set. In both cases, the next ++				 * RXBRK will indicate start-of-break. ++				 */ ++				UART_PUT_IDR(port, ATMEL_US_RXBRK); ++				status &= ~ATMEL_US_RXBRK; ++				atmel_port->break_active = 0; + 			} + 			if (status & ATMEL_US_PARE) + 				port->icount.parity++; +@@ -349,9 +540,27 @@ + 	status = UART_GET_CSR(port); + 	pending = status & UART_GET_IMR(port); + 	while (pending) { ++		/* PDC receive */ ++		if (pending & ATMEL_US_ENDRX) ++			atmel_pdc_endrx(port); ++		if (pending & ATMEL_US_TIMEOUT) ++			atmel_pdc_timeout(port); ++		if (atmel_port->use_dma_rx && pending & (ATMEL_US_RXBRK | ATMEL_US_OVRE | ATMEL_US_FRAME | ATMEL_US_PARE)) ++			atmel_pdc_rxerr(port, pending); ++ + 		/* 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++; +@@ -363,6 +572,12 @@ + 		if (pending & (ATMEL_US_RIIC | ATMEL_US_DSRIC | ATMEL_US_DCDIC | ATMEL_US_CTSIC)) + 			wake_up_interruptible(&port->info->delta_msr_wait); +  ++		/* PDC transmit */ ++		if (pending & ATMEL_US_ENDTX) ++			atmel_pdc_endtx(port); ++		if (pending & ATMEL_US_TXBUFE) ++			atmel_pdc_txbufe(port); ++ + 		/* Interrupt transmit */ + 		if (pending & ATMEL_US_TXRDY) + 			atmel_tx_chars(port); +@@ -401,6 +616,47 @@ + 	} +  + 	/* ++	 * Initialize DMA (if necessary) ++	 */ ++	if (atmel_port->use_dma_rx) { ++		int i; ++ ++		for (i = 0; i < 2; i++) { ++			struct atmel_dma_buffer *pdc = &atmel_port->pdc_rx[i]; ++ ++			pdc->buf = kmalloc(PDC_BUFFER_SIZE, GFP_KERNEL); ++			if (pdc->buf == NULL) { ++				if (i != 0) { ++					dma_unmap_single(port->dev, atmel_port->pdc_rx[0].dma_addr, PDC_BUFFER_SIZE, DMA_FROM_DEVICE); ++					kfree(atmel_port->pdc_rx[0].buf); ++				} ++				free_irq(port->irq, port); ++				return -ENOMEM; ++			} ++			pdc->dma_addr = dma_map_single(port->dev, pdc->buf, PDC_BUFFER_SIZE, DMA_FROM_DEVICE); ++			pdc->dma_size = PDC_BUFFER_SIZE; ++			pdc->ofs = 0; ++		} ++ ++		atmel_port->pdc_rx_idx = 0; ++ ++		UART_PUT_RPR(port, atmel_port->pdc_rx[0].dma_addr); ++		UART_PUT_RCR(port, PDC_BUFFER_SIZE); ++ ++		UART_PUT_RNPR(port, atmel_port->pdc_rx[1].dma_addr); ++		UART_PUT_RNCR(port, PDC_BUFFER_SIZE); ++	} ++	if (atmel_port->use_dma_tx) { ++		struct atmel_dma_buffer *pdc = &atmel_port->pdc_tx; ++		struct circ_buf *xmit = &port->info->xmit; ++ ++		pdc->buf = xmit->buf; ++		pdc->dma_addr = dma_map_single(port->dev, pdc->buf, SERIAL_XMIT_SIZE, DMA_TO_DEVICE); ++		pdc->dma_size = SERIAL_XMIT_SIZE; ++		pdc->ofs = 0; ++	} ++ ++	/* + 	 * If there is a specific "open" function (to register + 	 * control line interrupts) + 	 */ +@@ -418,8 +674,16 @@ + 	UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX); + 	UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);		/* enable xmit & rcvr */ +  +-	UART_PUT_IER(port, ATMEL_US_RXRDY);		/* enable receive only */ ++	if (atmel_port->use_dma_rx) { ++		UART_PUT_RTOR(port, PDC_RX_TIMEOUT);		/* set UART timeout */ ++		UART_PUT_CR(port, ATMEL_US_STTTO); +  ++		UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT); ++		UART_PUT_PTCR(port, ATMEL_PDC_RXTEN);		/* enable PDC controller */ ++	} ++	else ++		UART_PUT_IER(port, ATMEL_US_RXRDY);		/* enable receive only */ ++ + 	return 0; + } +  +@@ -431,6 +695,31 @@ + 	struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port; +  + 	/* ++	 * Ensure everything is stopped. ++	 */ ++	atmel_stop_rx(port); ++	atmel_stop_tx(port); ++ ++	/* ++	 * Shut-down the DMA. ++	 */ ++	if (atmel_port->use_dma_rx) { ++		int i; ++ ++		for (i = 0; i < 2; i++) { ++			struct atmel_dma_buffer *pdc = &atmel_port->pdc_rx[i]; ++ ++			dma_unmap_single(port->dev, pdc->dma_addr, pdc->dma_size, DMA_FROM_DEVICE); ++			kfree(pdc->buf); ++		} ++	} ++	if (atmel_port->use_dma_tx) { ++		struct atmel_dma_buffer *pdc = &atmel_port->pdc_tx; ++ ++		dma_unmap_single(port->dev, pdc->dma_addr, pdc->dma_size, DMA_TO_DEVICE); ++	} ++ ++	/* + 	 * Disable all interrupts, port and break condition. + 	 */ + 	UART_PUT_CR(port, ATMEL_US_RSTSTA); +@@ -481,6 +770,7 @@ +  */ + static void atmel_set_termios(struct uart_port *port, struct ktermios * termios, struct ktermios * old) + { ++	struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port; + 	unsigned long flags; + 	unsigned int mode, imr, quot, baud; +  +@@ -490,7 +780,7 @@ + 	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); + 	quot = uart_get_divisor(port, baud); +  +-	if (quot > 65535) {		/* BRGR is 16-bit, so switch to slower clock */ ++	if (quot > 65535) {	/* BRGR is 16-bit, so switch to slower clock */ + 		quot /= 8; + 		mode |= ATMEL_US_USCLKS_MCK_DIV8; + 	} +@@ -539,6 +829,9 @@ + 	if (termios->c_iflag & (BRKINT | PARMRK)) + 		port->read_status_mask |= ATMEL_US_RXBRK; +  ++	if (atmel_port->use_dma_rx)	/* need to enable error interrupts */ ++		UART_PUT_IER(port, port->read_status_mask); ++ + 	/* + 	 * Characters to ignore + 	 */ +@@ -717,6 +1010,13 @@ + 		clk_enable(atmel_port->clk); + 		port->uartclk = clk_get_rate(atmel_port->clk); + 	} ++ ++#ifdef SUPPORT_PDC ++	atmel_port->use_dma_rx = data->use_dma_rx; ++	atmel_port->use_dma_tx = data->use_dma_tx; ++	if (atmel_port->use_dma_tx) ++		port->fifosize = PDC_BUFFER_SIZE; ++#endif + } +  + /* +@@ -893,7 +1193,8 @@ + 	struct uart_port *port = platform_get_drvdata(pdev); + 	struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port; +  +-	if (device_may_wakeup(&pdev->dev) && !at91_suspend_entering_slow_clock()) ++	if (device_may_wakeup(&pdev->dev) ++			&& !clk_must_disable(atmel_port->clk)) + 		enable_irq_wake(port->irq); + 	else { + 		uart_suspend_port(&atmel_uart, port); +Index: linux-2.6.22.1/drivers/mtd/devices/Kconfig +=================================================================== +--- linux-2.6.22.1/drivers/mtd/devices/Kconfig	(revision 1) ++++ linux-2.6.22.1/drivers/mtd/devices/Kconfig	(arbetskopia) +@@ -269,5 +269,11 @@ + 	  LinuxBIOS or if you need to recover a DiskOnChip Millennium on which + 	  you have managed to wipe the first block. +  ++config MTD_AT91_DATAFLASH ++	tristate "AT91RM9200 DataFlash AT45DBxxx (legacy driver)" ++	depends on MTD && ARCH_AT91RM9200 && AT91_SPI ++	help ++	  This enables access to the DataFlash (AT45DBxxx) on the AT91RM9200. ++	  If you have such a board, say 'Y'. ++ + endmenu +- +Index: linux-2.6.22.1/drivers/mtd/devices/at91_dataflash.c +=================================================================== +--- linux-2.6.22.1/drivers/mtd/devices/at91_dataflash.c	(revision 0) ++++ linux-2.6.22.1/drivers/mtd/devices/at91_dataflash.c	(revision 0) +@@ -0,0 +1,667 @@ ++/* ++ * Atmel DataFlash driver for Atmel AT91RM9200 (Thunder)  + * -+ * Partialy rewriten by Karel Hojdar <cmkaho at seznam.cz> -+ * bugs removed, interrupt routine markedly rewritten ++ *  Copyright (C) SAN People (Pty) Ltd  + * -+ * 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 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" ++#include <linux/slab.h> ++#include <linux/pci.h> ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/partitions.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"); ++#include <asm/arch/spi.h>  + ++#undef DEBUG_DATAFLASH  + -+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 DATAFLASH_MAX_DEVICES	4	/* max number of dataflash devices */ ++#undef	DATAFLASH_ALWAYS_ADD_DEVICE	/* always add whole device when using partitions? */ ++ ++#define OP_READ_CONTINUOUS	0xE8 ++#define OP_READ_PAGE		0xD2 ++#define OP_READ_BUFFER1		0xD4 ++#define OP_READ_BUFFER2		0xD6 ++#define OP_READ_STATUS		0xD7 ++ ++#define OP_ERASE_PAGE		0x81 ++#define OP_ERASE_BLOCK		0x50 ++ ++#define OP_TRANSFER_BUF1	0x53 ++#define OP_TRANSFER_BUF2	0x55 ++#define OP_COMPARE_BUF1		0x60 ++#define OP_COMPARE_BUF2		0x61 ++ ++#define OP_PROGRAM_VIA_BUF1	0x82 ++#define OP_PROGRAM_VIA_BUF2	0x85 ++ ++struct dataflash_local ++{ ++	int spi;			/* SPI chip-select number */  + ++	unsigned int page_size;		/* number of bytes per page */ ++	unsigned short page_offset;	/* page offset in flash address */ ++}; ++ ++ ++/* Detected DataFlash devices */ ++static struct mtd_info* mtd_devices[DATAFLASH_MAX_DEVICES]; ++static int nr_devices = 0; ++ ++/* ......................................................................... */ ++ ++#ifdef CONFIG_MTD_PARTITIONS ++ ++static struct mtd_partition static_partitions_2M[] = ++{ ++	{ ++		.name		= "bootloader", ++		.offset		= 0, ++		.size		= 1 * 32 * 8 * 528,	/* 1st sector = 32 blocks * 8 pages * 528 bytes */ ++		.mask_flags	= MTD_WRITEABLE,	/* read-only */ ++	}, ++	{ ++		.name		= "kernel", ++		.offset		= MTDPART_OFS_NXTBLK, ++		.size		= 6 * 32 * 8 * 528,	/* 6 sectors */ ++	}, ++	{ ++		.name		= "filesystem", ++		.offset		= MTDPART_OFS_NXTBLK, ++		.size		= MTDPART_SIZ_FULL,	/* rest = 9 sectors */ ++	} ++}; ++ ++static struct mtd_partition static_partitions_4M[] = ++{ ++	{ ++		.name		= "bootloader", ++		.offset		= 0, ++		.size		= 1 * 64 * 8 * 528,	/* 1st sector = 64 blocks * 8 pages * 528 bytes */ ++		.mask_flags	= MTD_WRITEABLE,	/* read-only */ ++	}, ++	{ ++		.name		= "kernel", ++		.offset		= MTDPART_OFS_NXTBLK, ++		.size		= 4 * 64 * 8 * 528,	/* 4 sectors */ ++	}, ++	{ ++		.name		= "filesystem", ++		.offset		= MTDPART_OFS_NXTBLK, ++		.size		= MTDPART_SIZ_FULL,	/* rest = 11 sectors */ ++	} ++}; ++ ++#if defined(CONFIG_MACH_KAFA) ++static struct mtd_partition static_partitions_8M[] = ++{ ++	{ ++		name:		"romboot", ++		offset:		0, ++		size:		16 * 1056,	/* 160 Kb */ ++		mask_flags:	MTD_WRITEABLE,		/* read-only */ ++	}, ++	{ ++		name:		"uboot", ++		offset:		MTDPART_OFS_APPEND, /* Sperry, NXTBLK is broken */ ++		size:		128 * 1056,		/* 1 MB */ ++	}, ++	{ ++		name:		"kernel", ++		offset:		MTDPART_OFS_APPEND, /* Sperry, NXTBLK is broken */ ++		size:		1024 * 1056,		/* 1 MB */ ++	}, ++	{ ++		name:		"filesystem", ++		offset:		MTDPART_OFS_APPEND, /* Sperry, NXTBLK is broken */ ++		size:		MTDPART_SIZ_FULL, ++	} ++}; ++ ++#elif defined(CONFIG_MACH_MULTMDP) ++ ++static struct mtd_partition static_partitions_8M[] = ++{ ++	{ ++		.name		= "bootloader", ++		.offset		= 0, ++		.size		= 12 * 1056,		/* 1st sector = 32 blocks * 8 pages * 1056 bytes */ ++		.mask_flags	= MTD_WRITEABLE,	/* read-only */ ++	}, ++	{ ++		.name		= "configuration", ++		.offset		= MTDPART_OFS_NXTBLK, ++		.size		= 20 * 1056, ++	}, ++	{ ++		.name		= "kernel", ++		.offset		= MTDPART_OFS_NXTBLK, ++		.size		= 1520 * 1056, ++	}, ++	{ ++		.name		= "filesystem", ++		.offset		= MTDPART_OFS_NXTBLK, ++		.size		= MTDPART_SIZ_FULL, ++	}  +}; -+#define to_atmel_twi(adap) container_of(adap, struct atmel_twi, adapter) ++ ++#else ++ ++static struct mtd_partition static_partitions_8M[] = ++{ ++	{ ++		.name		= "bootloader", ++		.offset		= 0, ++		.size		= 1 * 32 * 8 * 1056,	/* 1st sector = 32 blocks * 8 pages * 1056 bytes */ ++		.mask_flags	= MTD_WRITEABLE,	/* read-only */ ++	}, ++	{ ++		.name		= "kernel", ++		.offset		= MTDPART_OFS_NXTBLK, ++		.size		= 5 * 32 * 8 * 1056,	/* 5 sectors */ ++	}, ++	{ ++		.name		= "filesystem", ++		.offset		= MTDPART_OFS_NXTBLK, ++		.size		= MTDPART_SIZ_FULL,	/* rest = 26 sectors */ ++	} ++}; ++#endif ++ ++static const char *part_probes[] = { "cmdlinepart", NULL, }; ++ ++#endif ++ ++/* ......................................................................... */ ++ ++/* Allocate a single SPI transfer descriptor.  We're assuming that if multiple ++   SPI transfers occur at the same time, spi_access_bus() will serialize them. ++   If this is not valid, then either (i) each dataflash 'priv' structure ++   needs it's own transfer descriptor, (ii) we lock this one, or (iii) use ++   another mechanism.   */ ++static struct spi_transfer_list* spi_transfer_desc;  +  +/* -+ * Initialize the TWI hardware registers. ++ * Perform a SPI transfer to access the DataFlash device.  + */ -+static int __devinit twi_hwinit(struct atmel_twi *twi) ++static int do_spi_transfer(int nr, char* tx, int tx_len, char* rx, int rx_len, ++		char* txnext, int txnext_len, char* rxnext, int rxnext_len)  +{ -+	unsigned long cdiv, ckdiv=0; ++	struct spi_transfer_list* list = spi_transfer_desc;  + -+	twi_writel(twi, IDR, ~0UL); -+	twi_writel(twi, CR, TWI_BIT(SWRST));	/*Reset peripheral*/ -+	twi_readl(twi, SR); ++	list->tx[0] = tx;	list->txlen[0] = tx_len; ++	list->rx[0] = rx;	list->rxlen[0] = rx_len;  + -+	cdiv = (clk_get_rate(twi->pclk) / (2 * baudrate)) - 4; ++	list->tx[1] = txnext;	list->txlen[1] = txnext_len; ++	list->rx[1] = rxnext;	list->rxlen[1] = rxnext_len;  + -+	while (cdiv > 255) { -+		ckdiv++; -+		cdiv = cdiv >> 1; -+	} ++	list->nr_transfers = nr;  + -+	if (ckdiv > 7) -+		return -EINVAL; -+	else -+		twi_writel(twi, CWGR, (TWI_BF(CKDIV, ckdiv) -+			       | TWI_BF(CHDIV, cdiv) -+			       | TWI_BF(CLDIV, cdiv))); -+	return 0; ++	return spi_transfer(list);  +}  + ++/* ......................................................................... */ ++  +/* -+ * Waits for the i2c status register to set the specified bitmask -+ * Returns 0 if timed out (~100ms). ++ * Poll the DataFlash device until it is READY.  + */ -+static short twi_complete(struct atmel_twi *twi, u32 mask) ++static void at91_dataflash_waitready(void)  +{ -+	int timeout = msecs_to_jiffies(100); ++	char* command = kmalloc(2, GFP_KERNEL);  + -+	twi->intmask = mask; -+	init_completion(&twi->comp); ++	if (!command) ++		return;  + -+	twi_writel(twi, IER, mask); ++	do { ++		command[0] = OP_READ_STATUS; ++		command[1] = 0;  + -+	if (!wait_for_completion_timeout(&twi->comp, timeout)) { -+		/* RESET TWI interface */ -+		twi_writel(twi, CR, TWI_BIT(SWRST)); ++		do_spi_transfer(1, command, 2, command, 2, NULL, 0, NULL, 0); ++	} while ((command[1] & 0x80) == 0);  + -+		/* Reinitialize TWI */ -+		twi_hwinit(twi); ++	kfree(command); ++}  + -+		return -ETIMEDOUT; ++/* ++ * Return the status of the DataFlash device. ++ */ ++static unsigned short at91_dataflash_status(void) ++{ ++	unsigned short status; ++	char* command = kmalloc(2, GFP_KERNEL); ++ ++	if (!command) ++		return 0; ++ ++	command[0] = OP_READ_STATUS; ++	command[1] = 0; ++ ++	do_spi_transfer(1, command, 2, command, 2, NULL, 0, NULL, 0); ++	status = command[1]; ++ ++	kfree(command); ++	return status; ++} ++ ++/* ......................................................................... */ ++ ++/* ++ * Erase blocks of flash. ++ */ ++static int at91_dataflash_erase(struct mtd_info *mtd, struct erase_info *instr) ++{ ++	struct dataflash_local *priv = (struct dataflash_local *) mtd->priv; ++	unsigned int pageaddr; ++	char* command; ++ ++#ifdef DEBUG_DATAFLASH ++	printk("dataflash_erase: addr=%i len=%i\n", instr->addr, instr->len); ++#endif ++ ++	/* Sanity checks */ ++	if (instr->addr + instr->len > mtd->size) ++		return -EINVAL; ++	if ((instr->len % mtd->erasesize != 0) || (instr->len % priv->page_size != 0)) ++		return -EINVAL; ++	if ((instr->addr % priv->page_size) != 0) ++		return -EINVAL; ++ ++	command = kmalloc(4, GFP_KERNEL); ++	if (!command) ++		return -ENOMEM; ++ ++	while (instr->len > 0) { ++		/* Calculate flash page address */ ++		pageaddr = (instr->addr / priv->page_size) << priv->page_offset; ++ ++		command[0] = OP_ERASE_PAGE; ++		command[1] = (pageaddr & 0x00FF0000) >> 16; ++		command[2] = (pageaddr & 0x0000FF00) >> 8; ++		command[3] = 0; ++#ifdef DEBUG_DATAFLASH ++		printk("ERASE: (%x) %x %x %x [%i]\n", command[0], command[1], command[2], command[3], pageaddr); ++#endif ++ ++		/* Send command to SPI device */ ++		spi_access_bus(priv->spi); ++		do_spi_transfer(1, command, 4, command, 4, NULL, 0, NULL, 0); ++ ++		at91_dataflash_waitready();		/* poll status until ready */ ++		spi_release_bus(priv->spi); ++ ++		instr->addr += priv->page_size;		/* next page */ ++		instr->len -= priv->page_size;  +	} ++ ++	kfree(command); ++ ++	/* Inform MTD subsystem that erase is complete */ ++	instr->state = MTD_ERASE_DONE; ++	if (instr->callback) ++		instr->callback(instr); ++  +	return 0;  +}  +  +/* -+ * Generic i2c master transfer entrypoint. ++ * Read from the DataFlash device. ++ *   from   : Start offset in flash device ++ *   len    : Amount to read ++ *   retlen : About of data actually read ++ *   buf    : Buffer containing the data  + */ -+static int twi_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) ++static int at91_dataflash_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)  +{ -+	struct atmel_twi *twi = to_atmel_twi(adap); -+	struct i2c_msg *pmsg; -+	int i; ++	struct dataflash_local *priv = (struct dataflash_local *) mtd->priv; ++	unsigned int addr; ++	char* command;  + -+	/* get first message */ -+	pmsg = msgs; ++#ifdef DEBUG_DATAFLASH ++	printk("dataflash_read: %lli .. %lli\n", from, from+len); ++#endif  + -+	dev_dbg(&adap->dev, "twi_xfer: processing %d messages:\n", num); ++	*retlen = 0;  + -+	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)); ++	/* Sanity checks */ ++	if (!len) ++		return 0; ++	if (from + len > mtd->size) ++		return -EINVAL;  + -+		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); ++	/* Calculate flash page/byte address */ ++	addr = (((unsigned)from / priv->page_size) << priv->page_offset) + ((unsigned)from % priv->page_size);  + -+		/* enable */ -+		twi_writel(twi, CR, TWI_BIT(MSEN)); ++	command = kmalloc(8, GFP_KERNEL); ++	if (!command) ++		return -ENOMEM;  + -+		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)); ++	command[0] = OP_READ_CONTINUOUS; ++	command[1] = (addr & 0x00FF0000) >> 16; ++	command[2] = (addr & 0x0000FF00) >> 8; ++	command[3] = (addr & 0x000000FF); ++#ifdef DEBUG_DATAFLASH ++	printk("READ: (%x) %x %x %x\n", command[0], command[1], command[2], command[3]); ++#endif  + -+			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; -+			} ++	/* Send command to SPI device */ ++	spi_access_bus(priv->spi); ++	do_spi_transfer(2, command, 8, command, 8, buf, len, buf, len); ++	spi_release_bus(priv->spi);  + -+			if (twi->nack) -+			    return -ENODEV; ++	*retlen = len; ++	kfree(command); ++	return 0; ++} ++ ++/* ++ * Write to the DataFlash device. ++ *   to     : Start offset in flash device ++ *   len    : Amount to write ++ *   retlen : Amount of data actually written ++ *   buf    : Buffer containing the data ++ */ ++static int at91_dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) ++{ ++	struct dataflash_local *priv = (struct dataflash_local *) mtd->priv; ++	unsigned int pageaddr, addr, offset, writelen; ++	size_t remaining; ++	u_char *writebuf; ++	unsigned short status; ++	int res = 0; ++	char* command; ++	char* tmpbuf = NULL; ++ ++#ifdef DEBUG_DATAFLASH ++	printk("dataflash_write: %lli .. %lli\n", to, to+len); ++#endif ++ ++	*retlen = 0; ++ ++	/* Sanity checks */ ++	if (!len) ++		return 0; ++	if (to + len > mtd->size) ++		return -EINVAL; ++ ++	command = kmalloc(4, GFP_KERNEL); ++	if (!command) ++		return -ENOMEM; ++ ++	pageaddr = ((unsigned)to / priv->page_size); ++	offset = ((unsigned)to % priv->page_size); ++	if (offset + len > priv->page_size) ++		writelen = priv->page_size - offset; ++	else ++		writelen = len; ++	writebuf = (u_char *)buf; ++	remaining = len; ++ ++	/* Allocate temporary buffer */ ++	tmpbuf = kmalloc(priv->page_size, GFP_KERNEL); ++	if (!tmpbuf) { ++		kfree(command); ++		return -ENOMEM; ++	} ++ ++	/* Gain access to the SPI bus */ ++	spi_access_bus(priv->spi); ++ ++	while (remaining > 0) { ++#ifdef DEBUG_DATAFLASH ++		printk("write @ %i:%i len=%i\n", pageaddr, offset, writelen); ++#endif ++ ++		/* (1) Transfer to Buffer1 */ ++		if (writelen != priv->page_size) { ++			addr = pageaddr << priv->page_offset; ++			command[0] = OP_TRANSFER_BUF1; ++			command[1] = (addr & 0x00FF0000) >> 16; ++			command[2] = (addr & 0x0000FF00) >> 8; ++			command[3] = 0; ++#ifdef DEBUG_DATAFLASH ++			printk("TRANSFER: (%x) %x %x %x\n", command[0], command[1], command[2], command[3]); ++#endif ++			do_spi_transfer(1, command, 4, command, 4, NULL, 0, NULL, 0); ++			at91_dataflash_waitready();  +		}  + -+		/* Disable TWI interface */ -+		twi_writel(twi, CR, TWI_BIT(MSDIS)); ++		/* (2) Program via Buffer1 */ ++		addr = (pageaddr << priv->page_offset) + offset; ++		command[0] = OP_PROGRAM_VIA_BUF1; ++		command[1] = (addr & 0x00FF0000) >> 16; ++		command[2] = (addr & 0x0000FF00) >> 8; ++		command[3] = (addr & 0x000000FF); ++#ifdef DEBUG_DATAFLASH ++		printk("PROGRAM: (%x) %x %x %x\n", command[0], command[1], command[2], command[3]); ++#endif ++		do_spi_transfer(2, command, 4, command, 4, writebuf, writelen, tmpbuf, writelen); ++		at91_dataflash_waitready(); ++ ++		/* (3) Compare to Buffer1 */ ++		addr = pageaddr << priv->page_offset; ++		command[0] = OP_COMPARE_BUF1; ++		command[1] = (addr & 0x00FF0000) >> 16; ++		command[2] = (addr & 0x0000FF00) >> 8; ++		command[3] = 0; ++#ifdef DEBUG_DATAFLASH ++		printk("COMPARE: (%x) %x %x %x\n", command[0], command[1], command[2], command[3]); ++#endif ++		do_spi_transfer(1, command, 4, command, 4, NULL, 0, NULL, 0); ++		at91_dataflash_waitready(); ++ ++		/* Get result of the compare operation */ ++		status = at91_dataflash_status(); ++		if ((status & 0x40) == 1) { ++			printk("at91_dataflash: Write error on page %i\n", pageaddr); ++			remaining = 0; ++			res = -EIO; ++		}  + -+	} /* end cur msg */ ++		remaining = remaining - writelen; ++		pageaddr++; ++		offset = 0; ++		writebuf += writelen; ++		*retlen += writelen;  + -+	return i; ++		if (remaining > priv->page_size) ++			writelen = priv->page_size; ++		else ++			writelen = remaining; ++	} ++ ++	/* Release SPI bus */ ++	spi_release_bus(priv->spi); ++ ++	kfree(tmpbuf); ++	kfree(command); ++	return res;  +}  + ++/* ......................................................................... */  + -+static irqreturn_t twi_interrupt(int irq, void *dev_id) -+{ -+	struct atmel_twi *twi = dev_id; -+	int status = twi_readl(twi, SR); ++/* ++ * Initialize and register DataFlash device with MTD subsystem. ++ */ ++static int __init add_dataflash(int channel, char *name, int IDsize, ++		int nr_pages, int pagesize, int pageoffset) ++{ ++	struct mtd_info *device; ++	struct dataflash_local *priv; ++#ifdef CONFIG_MTD_PARTITIONS ++	struct mtd_partition *mtd_parts = 0; ++	int mtd_parts_nr = 0; ++#endif  + -+	/* Save state for later debug prints */ -+	int old_mask = twi->intmask; -+	int old_status = status; ++	if (nr_devices >= DATAFLASH_MAX_DEVICES) { ++		printk(KERN_ERR "at91_dataflash: Too many devices detected\n"); ++		return 0; ++	}  + -+	if (twi->intmask & status) { -+		if (status & TWI_BIT(NACK)) -+			goto nack; ++	device = kmalloc(sizeof(struct mtd_info) + strlen(name) + 8, GFP_KERNEL); ++	if (!device) ++		return -ENOMEM; ++	memset(device, 0, sizeof(struct mtd_info)); ++ ++	device->name = (char *)&device[1]; ++	sprintf(device->name, "%s.spi%d", name, channel); ++	device->size = nr_pages * pagesize; ++	device->erasesize = pagesize; ++	device->writesize = pagesize; ++	device->owner = THIS_MODULE; ++	device->type = MTD_DATAFLASH; ++	device->flags = MTD_WRITEABLE; ++	device->erase = at91_dataflash_erase; ++	device->read = at91_dataflash_read; ++	device->write = at91_dataflash_write; ++ ++	priv = (struct dataflash_local *) kmalloc(sizeof(struct dataflash_local), GFP_KERNEL); ++	if (!priv) { ++		kfree(device); ++		return -ENOMEM; ++	} ++	memset(priv, 0, sizeof(struct dataflash_local));  + -+		status &= twi->intmask; ++	priv->spi = channel; ++	priv->page_size = pagesize; ++	priv->page_offset = pageoffset; ++	device->priv = priv;  + -+		if (status & TWI_BIT(TXCOMP)) -+		    goto complete; ++	mtd_devices[nr_devices] = device; ++	nr_devices++; ++	printk("at91_dataflash: %s detected [spi%i] (%i bytes)\n", name, channel, device->size);  + -+		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)); ++#ifdef CONFIG_MTD_PARTITIONS ++#ifdef CONFIG_MTD_CMDLINE_PARTS ++	mtd_parts_nr = parse_mtd_partitions(device, part_probes, &mtd_parts, 0); ++#endif ++	if (mtd_parts_nr <= 0) { ++		switch (IDsize) { ++			case SZ_2M: ++				mtd_parts = static_partitions_2M; ++				mtd_parts_nr = ARRAY_SIZE(static_partitions_2M); ++				break; ++			case SZ_4M: ++				mtd_parts = static_partitions_4M; ++				mtd_parts_nr = ARRAY_SIZE(static_partitions_4M); ++				break; ++			case SZ_8M: ++				mtd_parts = static_partitions_8M; ++				mtd_parts_nr = ARRAY_SIZE(static_partitions_8M); ++				break; ++		} ++	}  + -+			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]); ++	if (mtd_parts_nr > 0) { ++#ifdef DATAFLASH_ALWAYS_ADD_DEVICE ++		add_mtd_device(device); ++#endif ++		return add_mtd_partitions(device, mtd_parts, mtd_parts_nr); ++	} ++#endif ++	return add_mtd_device(device);		/* add whole device */ ++} ++ ++/* ++ * Detect and initialize DataFlash device connected to specified SPI channel. ++ * ++ *   Device            Density         ID code                 Nr Pages        Page Size       Page offset ++ *   AT45DB011B        1Mbit   (128K)  xx0011xx (0x0c)         512             264             9 ++ *   AT45DB021B        2Mbit   (256K)  xx0101xx (0x14)         1025            264             9 ++ *   AT45DB041B        4Mbit   (512K)  xx0111xx (0x1c)         2048            264             9 ++ *   AT45DB081B        8Mbit   (1M)    xx1001xx (0x24)         4096            264             9 ++ *   AT45DB0161B       16Mbit  (2M)    xx1011xx (0x2c)         4096            528             10 ++ *   AT45DB0321B       32Mbit  (4M)    xx1101xx (0x34)         8192            528             10 ++ *   AT45DB0642        64Mbit  (8M)    xx1111xx (0x3c)         8192            1056            11 ++ *   AT45DB1282        128Mbit (16M)   xx0100xx (0x10)         16384           1056            11 ++ */ ++static int __init at91_dataflash_detect(int channel) ++{ ++	int res = 0; ++	unsigned short status; ++ ++	spi_access_bus(channel); ++	status = at91_dataflash_status(); ++	spi_release_bus(channel); ++	if (status != 0xff) {			/* no dataflash device there */ ++		switch (status & 0x3c) { ++			case 0x0c:	/* 0 0 1 1 */ ++				res = add_dataflash(channel, "AT45DB011B", SZ_128K, 512, 264, 9); ++				break; ++			case 0x14:	/* 0 1 0 1 */ ++				res = add_dataflash(channel, "AT45DB021B", SZ_256K, 1025, 264, 9); ++				break; ++			case 0x1c:	/* 0 1 1 1 */ ++				res = add_dataflash(channel, "AT45DB041B", SZ_512K, 2048, 264, 9); ++				break; ++			case 0x24:	/* 1 0 0 1 */ ++				res = add_dataflash(channel, "AT45DB081B", SZ_1M, 4096, 264, 9); ++				break; ++			case 0x2c:	/* 1 0 1 1 */ ++				res = add_dataflash(channel, "AT45DB161B", SZ_2M, 4096, 528, 10); ++				break; ++			case 0x34:	/* 1 1 0 1 */ ++				res = add_dataflash(channel, "AT45DB321B", SZ_4M, 8192, 528, 10); ++				break; ++			case 0x3c:	/* 1 1 1 1 */ ++				res = add_dataflash(channel, "AT45DB642", SZ_8M, 8192, 1056, 11); ++				break; ++// Currently unsupported since Atmel removed the "Main Memory Program via Buffer" commands. ++//			case 0x10:	/* 0 1 0 0 */ ++//				res = add_dataflash(channel, "AT45DB1282", SZ_16M, 16384, 1056, 11); ++//				break; ++			default: ++				printk(KERN_ERR "at91_dataflash: Unknown device (%x)\n", status & 0x3c);  +		}  +	}  + -+	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 res; ++}  + -+	return IRQ_HANDLED; ++static int __init at91_dataflash_init(void) ++{ ++	spi_transfer_desc = kmalloc(sizeof(struct spi_transfer_list), GFP_KERNEL); ++	if (!spi_transfer_desc) ++		return -ENOMEM;  + -+nack: -+	dev_dbg(&twi->adapter.dev, "NACK received!\n"); -+	twi->nack = 1; ++	/* DataFlash (SPI chip select 0) */ ++	at91_dataflash_detect(0);  + -+complete: -+	twi_writel(twi, IDR, ~0UL); -+	complete(&twi->comp); ++#ifdef CONFIG_MTD_AT91_DATAFLASH_CARD ++	/* DataFlash card (SPI chip select 3) */ ++	at91_dataflash_detect(3); ++#endif  + -+	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 0; ++}  + -+	return IRQ_HANDLED; ++static void __exit at91_dataflash_exit(void) ++{ ++	int i; ++ ++	for (i = 0; i < DATAFLASH_MAX_DEVICES; i++) { ++		if (mtd_devices[i]) { ++#ifdef CONFIG_MTD_PARTITIONS ++			del_mtd_partitions(mtd_devices[i]); ++#else ++			del_mtd_device(mtd_devices[i]); ++#endif ++			kfree(mtd_devices[i]->priv); ++			kfree(mtd_devices[i]); ++		} ++	} ++	nr_devices = 0; ++	kfree(spi_transfer_desc);  +}  +  + -+/* -+ * Return list of supported functionality. -+ */ -+static u32 twi_func(struct i2c_adapter *adapter) ++module_init(at91_dataflash_init); ++module_exit(at91_dataflash_exit); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Andrew Victor"); ++MODULE_DESCRIPTION("DataFlash driver for Atmel AT91RM9200"); +Index: linux-2.6.22.1/drivers/mtd/devices/Makefile +=================================================================== +--- linux-2.6.22.1/drivers/mtd/devices/Makefile	(revision 1) ++++ linux-2.6.22.1/drivers/mtd/devices/Makefile	(arbetskopia) +@@ -18,3 +18,4 @@ + obj-$(CONFIG_MTD_DATAFLASH)	+= mtd_dataflash.o + obj-$(CONFIG_MTD_DATAFLASH26)	+= at91_dataflash26.o + obj-$(CONFIG_MTD_M25P80)	+= m25p80.o ++obj-$(CONFIG_MTD_AT91_DATAFLASH)+= at91_dataflash.o +Index: linux-2.6.22.1/drivers/mtd/chips/cfi_cmdset_0001.c +=================================================================== +--- linux-2.6.22.1/drivers/mtd/chips/cfi_cmdset_0001.c	(revision 1) ++++ linux-2.6.22.1/drivers/mtd/chips/cfi_cmdset_0001.c	(arbetskopia) +@@ -50,6 +50,7 @@ + #define I82802AC	0x00ac + #define MANUFACTURER_ST         0x0020 + #define M50LPW080       0x002F ++#define AT49BV640D	0x02de +  + static int cfi_intelext_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); + static int cfi_intelext_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); +@@ -156,6 +157,47 @@ + } + #endif +  ++/* Atmel chips don't use the same PRI format as Intel chips */ ++static void fixup_convert_atmel_pri(struct mtd_info *mtd, void *param)  +{ -+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; ++	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;  +}  + -+/* For now, we only handle combined mode (smbus) */ -+static struct i2c_algorithm twi_algorithm = { -+	.master_xfer	= twi_xfer, -+	.functionality	= twi_func, -+}; + #ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE + /* Some Intel Strata Flash prior to FPO revision C has bugs in this area */ + static void fixup_intel_strataflash(struct mtd_info *mtd, void* param) +@@ -233,6 +275,7 @@ + } +  + static struct cfi_fixup cfi_fixup_table[] = { ++	{ CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri, NULL }, + #ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE + 	{ CFI_MFR_ANY, CFI_ID_ANY, fixup_intel_strataflash, NULL }, + #endif +Index: linux-2.6.22.1/drivers/mtd/chips/cfi_cmdset_0002.c +=================================================================== +--- linux-2.6.22.1/drivers/mtd/chips/cfi_cmdset_0002.c	(revision 1) ++++ linux-2.6.22.1/drivers/mtd/chips/cfi_cmdset_0002.c	(arbetskopia) +@@ -185,6 +185,10 @@ + 		extp->TopBottom = 2; + 	else + 		extp->TopBottom = 3; ++ ++	/* burst write mode not supported */ ++	cfi->cfiq->BufWriteTimeoutTyp = 0; ++	cfi->cfiq->BufWriteTimeoutMax = 0; + } +  + static void fixup_use_secsi(struct mtd_info *mtd, void *param) +@@ -217,6 +221,7 @@ + } +  + static struct cfi_fixup cfi_fixup_table[] = { ++	{ CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri, NULL }, + #ifdef AMD_BOOTLOC_BUG + 	{ CFI_MFR_AMD, CFI_ID_ANY, fixup_amd_bootblock, NULL }, + #endif +@@ -229,7 +234,6 @@ + #if !FORCE_WORD_WRITE + 	{ CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL, }, + #endif +-	{ CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri, NULL }, + 	{ 0, 0, NULL, NULL } + }; + static struct cfi_fixup jedec_fixup_table[] = { +Index: linux-2.6.22.1/drivers/spi/Kconfig +=================================================================== +--- linux-2.6.22.1/drivers/spi/Kconfig	(revision 1) ++++ linux-2.6.22.1/drivers/spi/Kconfig	(arbetskopia) +@@ -55,6 +55,7 @@ + config SPI_ATMEL + 	tristate "Atmel SPI Controller" + 	depends on (ARCH_AT91 || AVR32) && SPI_MASTER ++	select SPI_AT91_MANUAL_CS if ARCH_AT91RM9200 + 	help + 	  This selects a driver for the Atmel SPI Controller, present on + 	  many AT32 (AVR32) and AT91 (ARM) chips. +@@ -100,6 +101,24 @@ + 	  inexpensive battery powered microcontroller evaluation board. + 	  This same cable can be used to flash new firmware. +  ++config SPI_AT91 ++	tristate "AT91RM9200 Bitbang SPI Master" ++	depends on SPI_MASTER && ARCH_AT91RM9200 && !SPI_ATMEL && EXPERIMENTAL ++	select SPI_BITBANG ++	select SPI_AT91_MANUAL_CS ++	help ++	  This is dumb PIO bitbanging driver for the Atmel AT91RM9200. ++	  The SPI_ATMEL driver will be its replacement, using the native ++	  SPI hardware and its DMA controller.  + ++config SPI_AT91_MANUAL_CS ++	bool ++	depends on ARCH_AT91RM9200 ++	help ++	  Works around an AT91RM9200 problem whereby the SPI chip-select ++	  will be wrongly disabled.  The workaround uses those pins as ++	  GPIOs instead of letting the SPI controller manage them. ++ + config SPI_IMX + 	tristate "Freescale iMX SPI controller" + 	depends on SPI_MASTER && ARCH_IMX && EXPERIMENTAL +Index: linux-2.6.22.1/drivers/spi/atmel_spi.c +=================================================================== +--- linux-2.6.22.1/drivers/spi/atmel_spi.c	(revision 1) ++++ linux-2.6.22.1/drivers/spi/atmel_spi.c	(arbetskopia) +@@ -412,8 +412,8 @@ + 		csr |= SPI_BIT(NCPHA); +  + 	/* TODO: DLYBS and DLYBCT */ +-	csr |= SPI_BF(DLYBS, 10); +-	csr |= SPI_BF(DLYBCT, 10); ++	csr |= SPI_BF(DLYBS, 0); ++	csr |= SPI_BF(DLYBCT, 0); +  + 	/* chipselect must have been muxed as GPIO (e.g. in board setup) */ + 	npcs_pin = (unsigned int)spi->controller_data; +Index: linux-2.6.22.1/drivers/spi/spi_at91_bitbang.c +=================================================================== +--- linux-2.6.22.1/drivers/spi/spi_at91_bitbang.c	(revision 0) ++++ linux-2.6.22.1/drivers/spi/spi_at91_bitbang.c	(revision 0) +@@ -0,0 +1,207 @@  +/* -+ * Main initialization routine. ++ * at91_spi.c - at91 SPI driver (BOOTSTRAP/BITBANG VERSION) ++ * ++ * Copyright (C) 2006 David Brownell ++ * ++ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.  + */ -+static int __devinit twi_probe(struct platform_device *pdev) ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/platform_device.h> ++ ++#include <linux/spi/spi.h> ++#include <linux/spi/spi_bitbang.h> ++ ++#include <asm/arch/gpio.h> ++ ++ ++/* ++ * FIXME this bitbanging version is just to help bootstrap systems until ++ * there's a native SPI+IRQ+DMA controller driver ... such a driver should ++ * be a drop-in replacement for this one, and much faster. ++ * ++ * remember: ++ * ++ *	- other at91 parts (like at91sam9) have multiple controllers ++ *	  and different pin muxing; this version is at91rm9200 specfic. ++ * ++ *	- at91sam9261 SPI0 pins are directly muxed with MMC/SD pins. ++ * ++ *	- rm9200 spi chipselects drop wrongly, so the native driver ++ *	  will need to use gpios much like this does. ++ * ++ *	- real hardware only allows 8..16 bits per word, while this ++ *	  bitbanger allows 1..32 (incompatible superset). ++ * ++ *	- this disregards clock parameters.  with inlined gpio calls, ++ *	  gcc 3.4.4 produces about 1.5 mbit/sec, more than 2x faster ++ *	  than using the subroutined veresion from txrx_word(). ++ * ++ *	- suspend/resume and <linux/clk.h> support is missing ... ++ */ ++ ++#define	spi_miso_bit	AT91_PIN_PA0 ++#define	spi_mosi_bit	AT91_PIN_PA1 ++#define	spi_sck_bit	AT91_PIN_PA2 ++ ++struct at91_spi { ++	struct spi_bitbang	bitbang; ++	struct platform_device	*pdev; ++}; ++ ++/*----------------------------------------------------------------------*/ ++ ++static inline void setsck(struct spi_device *spi, int is_on)  +{ -+	struct atmel_twi *twi; -+	struct resource *regs; -+	struct clk *pclk; -+	struct i2c_adapter *adapter; -+	int rc, irq; ++	at91_set_gpio_value(spi_sck_bit, is_on); ++}  + -+	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+	if (!regs) -+		return -ENXIO; ++static inline void setmosi(struct spi_device *spi, int is_on) ++{ ++	at91_set_gpio_value(spi_mosi_bit, is_on); ++}  + -+	pclk = clk_get(&pdev->dev, "pclk"); -+	if (IS_ERR(pclk)) -+		return PTR_ERR(pclk); -+	clk_enable(pclk); ++static inline int getmiso(struct spi_device *spi) ++{ ++	return at91_get_gpio_value(spi_miso_bit); ++}  + -+	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; -+	} ++static void at91_spi_chipselect(struct spi_device *spi, int is_active) ++{ ++	unsigned long cs = (unsigned long) spi->controller_data;  + -+	twi->pclk = pclk; -+	twi->regs = ioremap(regs->start, regs->end - regs->start + 1); -+	if (!twi->regs) -+		goto err_ioremap; ++	/* set default clock polarity */ ++	if (is_active) ++		setsck(spi, spi->mode & SPI_CPOL);  + -+	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; ++	/* only support active-low (default) */ ++	at91_set_gpio_value(cs, !is_active); ++}  + -+	rc = twi_hwinit(twi); -+	if (rc) { -+		dev_err(&pdev->dev, "Unable to set baudrate\n"); -+		goto err_hw_init; -+	} ++/* ++ * NOTE:  this is "as fast as we can"; it should be a function of ++ * the device clock ... ++ */ ++#define	spidelay(X)	do{} while(0)  + -+	adapter = &twi->adapter; -+	sprintf(adapter->name, "TWI"); -+	adapter->algo = &twi_algorithm; -+	adapter->class = I2C_CLASS_HWMON; -+	adapter->dev.parent = &pdev->dev; ++#define	EXPAND_BITBANG_TXRX ++#include <linux/spi/spi_bitbang.h>  + -+	platform_set_drvdata(pdev, twi); ++static u32 at91_spi_txrx_word_mode0(struct spi_device *spi, ++		unsigned nsecs, u32 word, u8 bits) ++{ ++	return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, 8); ++}  + -+	rc = i2c_add_adapter(adapter); -+	if (rc) { -+		dev_err(&pdev->dev, "Adapter %s registration failed\n", -+			adapter->name); -+		goto err_register; -+	} ++static u32 at91_spi_txrx_word_mode1(struct spi_device *spi, ++		unsigned nsecs, u32 word, u8 bits) ++{ ++	return bitbang_txrx_be_cpha1(spi, nsecs, 0, word, 8); ++}  + -+	dev_info(&pdev->dev, "Atmel TWI i2c bus device (baudrate %dk) at 0x%08lx.\n", -+		 baudrate/1000, (unsigned long)regs->start); ++static u32 at91_spi_txrx_word_mode2(struct spi_device *spi, ++		unsigned nsecs, u32 word, u8 bits) ++{ ++	return bitbang_txrx_be_cpha0(spi, nsecs, 1, word, 8); ++}  + -+	return 0; ++static u32 at91_spi_txrx_word_mode3(struct spi_device *spi, ++		unsigned nsecs, u32 word, u8 bits) ++{ ++	return bitbang_txrx_be_cpha1(spi, nsecs, 1, word, 8); ++}  + ++/*----------------------------------------------------------------------*/  + -+err_register: -+	platform_set_drvdata(pdev, NULL); ++static int __init at91_spi_probe(struct platform_device *pdev) ++{ ++	int			status; ++	struct spi_master	*master; ++	struct at91_spi		*at91_spi;  + -+err_hw_init: -+	free_irq(irq, twi); ++	if (pdev->id != 0)	/* SPI0 bus */ ++		return -EINVAL;  + -+err_irq: -+	iounmap(twi->regs); ++	master = spi_alloc_master(&pdev->dev, sizeof *at91_spi); ++	if (!master) ++		return -ENOMEM;  + -+err_ioremap: -+	kfree(twi); ++	at91_spi = spi_master_get_devdata(master); ++	at91_spi->pdev = pdev; ++	platform_set_drvdata(pdev, at91_spi);  + -+err_alloc_twi: -+	clk_disable(pclk); -+	clk_put(pclk); ++	/* SPI and bitbang hookup */ ++	master->bus_num = 0; ++	master->num_chipselect = 4;  + -+	return rc; ++	at91_spi->bitbang.master = spi_master_get(master); ++	at91_spi->bitbang.chipselect = at91_spi_chipselect; ++	at91_spi->bitbang.txrx_word[SPI_MODE_0] = at91_spi_txrx_word_mode0; ++	at91_spi->bitbang.txrx_word[SPI_MODE_1] = at91_spi_txrx_word_mode1; ++	at91_spi->bitbang.txrx_word[SPI_MODE_2] = at91_spi_txrx_word_mode2; ++	at91_spi->bitbang.txrx_word[SPI_MODE_3] = at91_spi_txrx_word_mode3; ++ ++	status = spi_bitbang_start(&at91_spi->bitbang); ++	if (status < 0) ++		(void) spi_master_put(at91_spi->bitbang.master); ++ ++	return status;  +}  + -+static int __devexit twi_remove(struct platform_device *pdev) ++static int __exit at91_spi_remove(struct platform_device *pdev)  +{ -+	struct atmel_twi *twi = platform_get_drvdata(pdev); -+	int res; ++	struct at91_spi	*at91_spi = platform_get_drvdata(pdev); ++	int status;  + -+	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); ++	/* stop() unregisters child devices too */ ++	status = spi_bitbang_stop(&at91_spi->bitbang); ++	(void) spi_master_put(at91_spi->bitbang.master);  + -+	return res; ++	platform_set_drvdata(pdev, NULL); ++	return status;  +}  + -+static struct platform_driver twi_driver = { -+	.probe		= twi_probe, -+	.remove		= __devexit_p(twi_remove), ++static struct platform_driver at91_spi_driver = { ++	.probe		= at91_spi_probe, ++	.remove		= __exit_p(at91_spi_remove),  +	.driver		= { -+		.name	= "atmel_twi", ++		.name	= "at91_spi",  +		.owner	= THIS_MODULE,  +	},  +};  + -+static int __init atmel_twi_init(void) ++static int __init at91_spi_init(void)  +{ -+	return platform_driver_register(&twi_driver); ++	at91_set_gpio_output(spi_sck_bit, 0); ++	at91_set_gpio_output(spi_mosi_bit, 0); ++	at91_set_gpio_input(spi_miso_bit, 1 /* pullup */); ++ ++	/* register driver */ ++	return platform_driver_register(&at91_spi_driver);  +}  + -+static void __exit atmel_twi_exit(void) ++static void __exit at91_spi_exit(void)  +{ -+	platform_driver_unregister(&twi_driver); ++	platform_driver_unregister(&at91_spi_driver);  +}  + -+module_init(atmel_twi_init); -+module_exit(atmel_twi_exit); ++device_initcall(at91_spi_init); ++module_exit(at91_spi_exit);  + -+MODULE_AUTHOR("Espen Krangnes"); -+MODULE_DESCRIPTION("I2C driver for Atmel TWI"); ++MODULE_ALIAS("at91_spi.0"); ++ ++MODULE_DESCRIPTION("AT91 SPI support (BOOTSTRAP/BITBANG VERSION)"); ++MODULE_AUTHOR("David Brownell");  +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 +Index: linux-2.6.22.1/drivers/spi/Makefile +=================================================================== +--- linux-2.6.22.1/drivers/spi/Makefile	(revision 1) ++++ linux-2.6.22.1/drivers/spi/Makefile	(arbetskopia) +@@ -23,6 +23,7 @@ + obj-$(CONFIG_SPI_MPC83xx)		+= spi_mpc83xx.o + obj-$(CONFIG_SPI_S3C24XX_GPIO)		+= spi_s3c24xx_gpio.o + obj-$(CONFIG_SPI_S3C24XX)		+= spi_s3c24xx.o ++obj-$(CONFIG_SPI_AT91)			+= spi_at91_bitbang.o + # 	... add above this line ... +  + # SPI protocol drivers (device/link on bus) +Index: linux-2.6.22.1/drivers/input/mouse/Kconfig +=================================================================== +--- linux-2.6.22.1/drivers/input/mouse/Kconfig	(revision 1) ++++ linux-2.6.22.1/drivers/input/mouse/Kconfig	(arbetskopia) +@@ -216,4 +216,20 @@   	help   	  Say Y here to support HIL pointers. @@ -5676,23 +14921,10 @@ index 50e06e8..7bbea09 100644  +	  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 +Index: linux-2.6.22.1/drivers/input/mouse/gpio_mouse.c +=================================================================== +--- linux-2.6.22.1/drivers/input/mouse/gpio_mouse.c	(revision 0) ++++ linux-2.6.22.1/drivers/input/mouse/gpio_mouse.c	(revision 0)  @@ -0,0 +1,196 @@  +/*  + * Driver for simulating a mouse on GPIO lines. @@ -5890,456 +15122,1613 @@ index 0000000..0936d6b  +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" +Index: linux-2.6.22.1/drivers/input/mouse/Makefile +=================================================================== +--- linux-2.6.22.1/drivers/input/mouse/Makefile	(revision 1) ++++ linux-2.6.22.1/drivers/input/mouse/Makefile	(arbetskopia) +@@ -15,6 +15,7 @@ + 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 - 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 + psmouse-objs := psmouse-base.o synaptics.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 @@ +Index: linux-2.6.22.1/drivers/video/s1d15605fb.c +=================================================================== +--- linux-2.6.22.1/drivers/video/s1d15605fb.c	(revision 0) ++++ linux-2.6.22.1/drivers/video/s1d15605fb.c	(revision 0) +@@ -0,0 +1,659 @@  +/* -+ * LEDs driver for GPIOs ++ *  drivers/video/s1d15605.c  + * -+ * Copyright (C) 2007 8D Technologies inc. -+ * Raphael Assenat <raph@8d.com> ++ * Adapted from several sources including: ++ * 1) Driver for AT91 LCD Controller ++ *    Copyright (C) 2006 Atmel ++ * ++ * 2) Copyright (C) 2005 S. Kevin Hester ++ * ++ *   This file is subject to the terms and conditions of the GNU General Public ++ *   License. See the file COPYING in the main directory of this archive for ++ *   more details. ++ * ++ *   This is a basic framebuffer driver for the Optrex F-51320 128x64 mono LCD ++ *   display.  This display uses a clone of the common Epson SED 1531 display ++ *   controller. ++ * ++ *   I've heavily borrowed code from the vfb.c driver.  + *  + * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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  + */ ++ ++#ifdef DEBUG ++#define MSG(string, args...) printk("s1d15605fb:" string, ##args) ++#else ++#define MSG(string, args...) ++#endif ++  +#include <linux/kernel.h> -+#include <linux/init.h>  +#include <linux/platform_device.h> -+#include <linux/leds.h> -+#include <linux/workqueue.h> ++#include <linux/dma-mapping.h> ++#include <linux/interrupt.h> ++#include <linux/clk.h> ++#include <linux/fb.h> ++#include <linux/init.h> ++#include <linux/delay.h>  + -+#include <asm/gpio.h> ++#include <asm/uaccess.h>  + -+struct gpio_led_data { -+	struct led_classdev cdev; -+	unsigned gpio; -+	struct work_struct work; -+	u8 new_level; -+	u8 can_sleep; -+	u8 active_low; ++#include <asm/arch/board.h> ++#include <asm/arch/gpio.h> ++ ++#ifdef CONFIG_PMAC_BACKLIGHT ++#include <asm/backlight.h> ++#endif ++ ++#define VIDEOWIDTH		128 ++#define VIDEOHEIGHT		64 ++#define VIDEODEPTH		1	/* bits/pixel */ ++#define VIDEOWIDTH_BYTES	((VIDEOWIDTH * VIDEODEPTH) / 8) ++ ++/* The number of bytes that actually go to the device */ ++#define ACTUALVIDEOMEMSIZE	(VIDEOWIDTH_BYTES * VIDEOHEIGHT) ++#define VIDEOMEMSIZE		PAGE_SIZE ++ ++static struct fb_var_screeninfo s1d15605_default __initdata = { ++	.xres		= VIDEOWIDTH, ++	.yres		= VIDEOHEIGHT, ++	.xres_virtual	= VIDEOWIDTH, ++	.yres_virtual	= VIDEOHEIGHT, ++	.bits_per_pixel	= VIDEODEPTH, ++	.red		= { 0, 1, 0 }, ++	.green		= { 0, 1, 0 }, ++	.blue		= { 0, 1, 0 }, ++	.activate	= FB_ACTIVATE_NOW, ++	.pixclock	= 20000, ++	.vmode		= FB_VMODE_NONINTERLACED,  +};  + -+static void gpio_led_work(struct work_struct *work) -+{ -+	struct gpio_led_data	*led_dat = -+		container_of(work, struct gpio_led_data, work); ++static struct fb_fix_screeninfo s1d15605_fix __initdata = { ++	.id		= "s1d15605", ++	.type		= FB_TYPE_PACKED_PIXELS, ++	.visual		= FB_VISUAL_MONO10, ++	.xpanstep	= 0, ++	.ypanstep	= 0, ++	.ywrapstep	= 0, ++	.accel		= FB_ACCEL_NONE, ++};  + -+	gpio_set_value_cansleep(led_dat->gpio, led_dat->new_level); -+} ++struct s1d15605fb_info { ++	struct fb_info		*info; ++	char			*mmio; ++	unsigned long		reset_pin; ++	struct platform_device	*pdev; ++};  + -+static void gpio_led_set(struct led_classdev *led_cdev, -+	enum led_brightness value) ++/* ++ * LCD device interface ++ */ ++#define	RESET_DISPLAY		0xE2 ++#define	LCD_BIAS_1_9		0xA2 ++#define	ADC_SELECT_REVERSE	0xA1 ++#define	COMMON_OUTPUT_NORMAL	0xC0 ++#define	V5_RESISTOR_RATIO	0x26 ++#define	ELECTRONIC_VOLUME_SET	0x81 ++#define	ELECTRONIC_VOLUME_INIT	0x20 ++#define	POWER_CONTROL_SET	0x28 ++#define	VOLTAGE_REGULATOR	0x02 ++#define	VOLTAGE_FOLLOWER	0x01 ++#define	BOOSTER_CIRCUIT		0x04 ++#define	DISPLAY_ON		0xAF ++#define	START_LINE_SET		0x40 ++#define	PAGE_ADDRESS_SET	0xB0 ++#define	COLUMN_ADDRESS_HIGH	0x10 ++#define	COLUMN_ADDRESS_LOW	0x00 ++#define	RESISTOR_RATIO_START	0x20 ++ ++#define	NUM_OF_PAGES		8 ++#define	NUM_OF_COLUMNS		128 ++ ++#define	WRITE_COMMAND(x)	__raw_writeb((x), (sinfo)->mmio) ++#define	READ_COMMAND		__raw_readb((sinfo)->mmio) ++#define	WRITE_DATA(x)		__raw_writeb((x), (sinfo)->mmio + (0x10000)) ++#define	READ_DATA		__raw_readb((sinfo)->mmio + (0x10000)) ++ ++ ++/* ++ *	s1d15605fb_resize_framebuffer ++ * ++ *	Free allocated space if different.  Allocate on new of changed. ++ *	Returns -ENOMEM if the new framebuffer can not be allocated, ++ *	zero on success. ++ */ ++static int s1d15605fb_resize_framebuffer(struct s1d15605fb_info *sinfo)  +{ -+	struct gpio_led_data *led_dat = -+		container_of(led_cdev, struct gpio_led_data, cdev); -+	int level; ++	struct fb_info			*info = sinfo->info; ++	struct fb_fix_screeninfo	*fix = &info->fix; ++	struct fb_var_screeninfo	*var = &info->var; ++	unsigned int			new_size; ++	void				*new_vaddr;  + -+	if (value == LED_OFF) -+		level = 0; -+	else -+		level = 1; ++	new_size = ((var->xres_virtual * var->yres_virtual * var->bits_per_pixel) / 8);  + -+	if (led_dat->active_low) -+		level = !level; ++	MSG("%s: x (%d) y (%d) bpp (%d): new size 0x%08x\n", __FUNCTION__, ++		var->xres_virtual, var->yres_virtual, var->bits_per_pixel, new_size);  + -+	/* 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); -+} ++	if (new_size == fix->smem_len) ++		return 0;  + -+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 (fix->smem_len) { ++		kfree(info->screen_base); ++	}  + -+	if (!pdata) -+		return -EBUSY; ++	new_vaddr = kmalloc(new_size, GFP_KERNEL);  + -+	leds_data = kzalloc(sizeof(struct gpio_led_data) * pdata->num_leds, -+				GFP_KERNEL); -+	if (!leds_data) ++	if (!new_vaddr) { ++		fix->smem_len = 0;  +		return -ENOMEM; ++	}  + -+	for (i = 0; i < pdata->num_leds; i++) { -+		cur_led = &pdata->leds[i]; -+		led_dat = &leds_data[i]; ++	info->screen_base = new_vaddr; ++	fix->smem_start = (unsigned)new_vaddr; ++	fix->smem_len = new_size; ++	fix->line_length = (var->xres_virtual * var->bits_per_pixel) / 8;  + -+		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; ++	dev_info(info->device, ++		"%luKiB frame buffer at %08lx (mapped at %p)\n", ++		(unsigned long)info->fix.smem_len / 1024, ++		(unsigned long)info->fix.smem_start, ++		info->screen_base);  + -+		ret = gpio_request(led_dat->gpio, led_dat->cdev.name); -+		if (ret < 0) -+			goto err; ++	return 0; ++}  + -+		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; ++/* ++ * The s1d15605 seems to be divided into eight 128 pixel wide pages (from top to ++ * bottom) each page seems to be eight pixels high, where these eight pixels are ++ * one byte ++ */ ++static void s1d15605_update(struct fb_info *info) ++{ ++	struct s1d15605fb_info	*sinfo = info->par; ++	int			page, i, row, colmask; ++	u8			retVal, *rowPtr; ++ ++	WRITE_COMMAND(START_LINE_SET); ++	for (page = 0; page < NUM_OF_PAGES; ++page) { ++		WRITE_COMMAND(PAGE_ADDRESS_SET + page); ++		WRITE_COMMAND(COLUMN_ADDRESS_HIGH); ++		WRITE_COMMAND(COLUMN_ADDRESS_LOW); ++ ++		for (i = 0; i < NUM_OF_COLUMNS; ++i) ++		{ ++			/* point of opportunity: optimization */ ++			colmask = (1 << (i & 0x7)); ++			rowPtr = (u8*)(info->screen_base); ++			rowPtr += (VIDEOWIDTH_BYTES * 8 * page); ++			rowPtr += (i >> 3); ++			retVal = 0; ++			for (row = 0; row < 8; ++row) ++			{ ++				retVal = (retVal >> 1) | (((*rowPtr) & colmask) ? 0x80 : 0); ++				rowPtr += VIDEOWIDTH_BYTES; ++			} ++			WRITE_DATA(retVal);  +		} ++	}  + -+		INIT_WORK(&led_dat->work, gpio_led_work); ++	WRITE_COMMAND(DISPLAY_ON); ++} ++ ++ ++/* ++ * Setting the video mode has been split into two parts. ++ * First part, xxxfb_check_var, must not write anything ++ * to hardware, it should only verify and adjust var. ++ * This means it doesn't alter par but it does use hardware ++ * data from it to check this var. ++ */ ++static int s1d15605_check_var(struct fb_var_screeninfo *var, struct fb_info *info) ++{ ++	/* ++	 * Some very basic checks ++	 */ ++	if (!var->xres) ++		var->xres = 1; ++	if (!var->yres) ++		var->yres = 1; ++	if (var->xres > var->xres_virtual) ++		var->xres_virtual = var->xres; ++	if (var->yres > var->yres_virtual) ++		var->yres_virtual = var->yres; ++ ++	if(var->bits_per_pixel > VIDEODEPTH) ++		return -EINVAL; ++ ++	/* ++	 * Memory limit ++	 */ ++	if (((var->yres_virtual * var->bits_per_pixel * var->yres_virtual) >> 3) > ++			ACTUALVIDEOMEMSIZE) ++		return -ENOMEM; ++ ++	/* ++	 * Now that we checked it we alter var. The reason being is that the video ++	 * mode passed in might not work but slight changes to it might make it ++	 * work. This way we let the user know what is acceptable. ++	 */ ++	switch (var->bits_per_pixel) { ++	case 1: ++		var->red.offset = var->green.offset = var->blue.offset = 0; ++		var->red.length = var->green.length = var->blue.length ++			= var->bits_per_pixel; ++		break; ++	default: ++		return -EINVAL;  +	}  + -+	platform_set_drvdata(pdev, leds_data); ++	var->xoffset = var->yoffset = 0; ++	var->red.msb_right = var->green.msb_right = var->blue.msb_right = ++		var->transp.msb_right = 0;  +  +	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); ++/* ++ * This routine actually sets the video mode. It's in here where we ++ * the hardware state info->par and fix which can be affected by the ++ * change in par. For this driver it doesn't do much. ++ */ ++static int s1d15605_set_par(struct fb_info *info) ++{ ++	int	ret;  + ++	MSG("%s:\n", __func__); ++	MSG("  * resolution: %ux%u (%ux%u virtual)\n", ++		 info->var.xres, info->var.yres, ++		 info->var.xres_virtual, info->var.yres_virtual); ++ ++	ret = s1d15605fb_resize_framebuffer(info->par); ++ ++	info->fix.visual = FB_VISUAL_MONO10;  +	return ret;  +}  + -+static int __exit gpio_led_remove(struct platform_device *pdev) ++ ++/* ++ * Set a single color register. The values supplied are already ++ * rounded down to the hardware's capabilities (according to the ++ * entries in the var structure). Return != 0 for invalid regno. ++ */ ++static int s1d15605_setcolreg(u_int regno, u_int red, u_int green, u_int blue, ++			u_int transp, struct fb_info *info)  +{ -+	int i; -+	struct gpio_led_platform_data *pdata = pdev->dev.platform_data; -+	struct gpio_led_data *leds_data; ++	if (regno > 1)	/* no. of hw registers - we only do mono now */ ++		return 1;  + -+	leds_data = platform_get_drvdata(pdev); ++	return 0; ++}  + -+	for (i = 0; i < pdata->num_leds; i++) { -+		led_classdev_unregister(&leds_data[i].cdev); -+		gpio_free(leds_data[i].gpio); ++ ++/* ++ * Currently, the routine will simply shut-off the backlight and prevent ++ * updates/refreshes.  Modify according to application. ++ * ++ * 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off ++ */ ++static int s1d15605_blank(int blank, struct fb_info *info) ++{ ++#ifdef CONFIG_PMAC_BACKLIGHT ++	if (blank) ++		pmac_backlight->props.power = FB_BLANK_POWERDOWN; ++	else ++		pmac_backlight->props.power = FB_BLANK_UNBLANK; ++	backlight_update_status(pmac_backlight); ++#endif ++	return 1; ++} ++ ++ ++/* ++ * Pan or Wrap the Display ++ * ++ * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag ++ */ ++/* ++static int s1d15605_pan_display(struct fb_var_screeninfo *var, ++			struct fb_info *info) ++{ ++	if (var->vmode & FB_VMODE_YWRAP) { ++		if (var->yoffset < 0 ++		    || var->yoffset >= info->var.yres_virtual ++		    || var->xoffset) ++			return -EINVAL; ++	} else { ++		if (var->xoffset + var->xres > info->var.xres_virtual || ++		    var->yoffset + var->yres > info->var.yres_virtual) ++			return -EINVAL;  +	} -+	 -+	kfree(leds_data); ++	info->var.xoffset = var->xoffset; ++	info->var.yoffset = var->yoffset; ++	if (var->vmode & FB_VMODE_YWRAP) ++		info->var.vmode |= FB_VMODE_YWRAP; ++	else ++		info->var.vmode &= ~FB_VMODE_YWRAP; ++	return 0; ++} ++*/ ++ ++ ++static void s1d15605_copyarea(struct fb_info *info, const struct fb_copyarea *region) ++{ ++	cfb_copyarea(info, region); ++	s1d15605_update(info); ++} ++ ++ ++static void s1d15605_fillrect (struct fb_info *info, const struct fb_fillrect *rect) ++{ ++	cfb_fillrect(info, rect); ++	s1d15605_update(info); ++} ++ ++ ++static void s1d15605_imageblit(struct fb_info *p, const struct fb_image *image) ++{ ++	cfb_imageblit(p, image); ++	s1d15605_update(p); ++} ++ ++ ++/* ++ * Write the users data to our framebuffer, and then trigger a psuedo DMA ++ */ ++static ssize_t s1d15605_write(struct file *file, const char *buf, ++			size_t count, loff_t *ppos) ++{ ++	unsigned long p = *ppos; ++	struct inode *inode = file->f_dentry->d_inode; ++	int fbidx = iminor(inode); ++	struct fb_info *info = registered_fb[fbidx]; ++	int err; ++ ++	if (p > info->fix.smem_len) ++		return -ENOSPC; ++	if (count >= info->fix.smem_len) ++		count = info->fix.smem_len; ++	err = 0; ++	if (count + p > info->fix.smem_len) { ++		count = info->fix.smem_len - p; ++		err = -ENOSPC; ++	} ++	if (count) { ++		char *base_addr; ++ ++		base_addr = info->screen_base; ++		count -= copy_from_user(base_addr+p, buf, count); ++		*ppos += count; ++		err = -EFAULT; ++	} ++ ++	s1d15605_update(info); ++ ++	if (count) ++		return count; ++ ++	return err; ++} ++ ++#ifdef	USE_PRIVATE_VMA_FXS ++static void s1d15605_vma_open(struct vm_area_struct *vma) ++{ ++	// FIXME - store stats in the device data via vm_private_data ++} ++ ++ ++static void s1d15605_vma_close(struct vm_area_struct *vma) ++{ ++	// FIXME - store stats in the device data via vm_private_data ++} ++ ++ ++static struct page *s1d15605_vma_nopage(struct vm_area_struct *vma, ++				unsigned long address, int *type) ++{ ++	struct page *page; ++	struct fb_info *info = vma->vm_private_data; ++ ++	page = virt_to_page(info->screen_base); ++	get_page(page); ++ ++	// FIXME - now someone has a link to our page, start periodically blitting ++	// latest updates to the actual device. ++ ++	return page; ++} ++ ++ ++static struct vm_operations_struct s1d15605_vm_ops = { ++	.open	= s1d15605_vma_open, ++	.close	= s1d15605_vma_close, ++	.nopage	= s1d15605_vma_nopage ++}; ++ ++ ++/* We don't do much here - because we have special vm_ops */ ++static int s1d15605_mmap(struct fb_info *info, struct vm_area_struct *vma) ++{ ++	vma->vm_ops = &s1d15605_vm_ops; ++	vma->vm_flags |= VM_RESERVED; ++	vma->vm_private_data = info; ++	s1d15605_vma_open(vma);  +  +	return 0;  +} ++#endif /* USE_PRIVATE_VMA_FXS */  + -+#ifdef CONFIG_PM -+static int gpio_led_suspend(struct platform_device *pdev, pm_message_t state) ++ ++static struct fb_ops s1d15605fb_ops = { ++	.owner		= THIS_MODULE, ++	.fb_check_var	= s1d15605_check_var, ++	.fb_set_par	= s1d15605_set_par, ++	.fb_setcolreg	= s1d15605_setcolreg, ++	.fb_blank	= s1d15605_blank, ++//	.fb_pan_display	= s1d15605_pan_display, ++	.fb_fillrect	= s1d15605_fillrect, ++	.fb_copyarea	= s1d15605_copyarea, ++	.fb_imageblit	= s1d15605_imageblit, ++	.fb_write	= s1d15605_write, ++#ifdef	USE_PRIVATE_VMA_FXS ++	.fb_mmap	= s1d15605_mmap, ++#endif ++}; ++ ++ ++static void s1d15605_device_init(struct s1d15605fb_info *sinfo) { ++ ++	char	value; ++ ++	/* release the reset line by reading the device - proto hardware */ ++	value = READ_COMMAND; ++	value = READ_COMMAND; ++ ++#ifdef CONFIG_MACH_KB9200 ++	/* new boards have dedicated reset line */ ++	gpio_set_value(sinfo->reset_pin, 1); ++#endif ++ ++	/* initialize the device within 5ms */ ++	WRITE_COMMAND(RESET_DISPLAY); ++	WRITE_COMMAND(LCD_BIAS_1_9); ++	WRITE_COMMAND(ADC_SELECT_REVERSE); ++	WRITE_COMMAND(COMMON_OUTPUT_NORMAL); ++	WRITE_COMMAND(V5_RESISTOR_RATIO); ++	WRITE_COMMAND(ELECTRONIC_VOLUME_SET); ++	WRITE_COMMAND(ELECTRONIC_VOLUME_INIT); ++	WRITE_COMMAND(POWER_CONTROL_SET | VOLTAGE_REGULATOR | VOLTAGE_FOLLOWER | BOOSTER_CIRCUIT); ++	WRITE_COMMAND(DISPLAY_ON); ++ ++	WRITE_COMMAND(RESISTOR_RATIO_START + 4); ++	WRITE_COMMAND(ELECTRONIC_VOLUME_SET); ++	WRITE_COMMAND(0x33); ++} ++ ++ ++static int s1d15605fb_probe(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); ++	struct device *dev = &pdev->dev; ++	struct fb_info *info; ++	struct s1d15605fb_info *sinfo; ++	int ret;  + -+	for (i = 0; i < pdata->num_leds; i++) -+		led_classdev_suspend(&leds_data[i].cdev); ++	MSG("%s\n", __func__); ++ ++	if (!(info = framebuffer_alloc(sizeof(struct s1d15605fb_info), dev))) { ++		dev_err(dev, "Cannot allocate framebuffer struct\n"); ++		return -ENOMEM; ++	} ++ ++	sinfo = info->par; ++	sinfo->info = info; ++	sinfo->pdev = pdev; ++ ++	if (pdev->num_resources < 2) { ++		dev_err(dev, "Resources unusable\n"); ++		ret = -ENODEV; ++		goto free_info; ++	} ++ ++	info->fbops = &s1d15605fb_ops; ++	strcpy(info->fix.id, pdev->name); ++ ++	info->fix.mmio_start = pdev->resource[0].start; ++	info->fix.mmio_len = pdev->resource[0].end - pdev->resource[0].start + 1; ++	sinfo->reset_pin = pdev->resource[1].start; ++ ++	ret = s1d15605fb_resize_framebuffer(sinfo); ++	if (ret < 0) { ++		dev_err(dev, "Cannot resize framebuffer: %d\n", ret); ++		goto free_fb; ++	} ++ ++	if (!request_mem_region(info->fix.mmio_start, ++				info->fix.mmio_len, pdev->name)) { ++		ret = -EBUSY; ++		goto free_fb; ++	} ++ ++	sinfo->mmio = ioremap(info->fix.mmio_start, info->fix.mmio_len); ++	if (!sinfo->mmio) { ++		dev_err(dev, "Cannot map LCD memory region\n"); ++		goto release_mem; ++	} ++ ++	s1d15605_device_init(sinfo); ++ ++	ret = fb_find_mode(&info->var, info, NULL, NULL, 0, NULL, 1); ++ ++	if (!ret || (ret == 4)) ++		info->var = s1d15605_default; ++ ++	info->fix = s1d15605_fix; ++	info->flags = FBINFO_FLAG_DEFAULT | ++/*		FBINFO_HWACCEL_YPAN | */ ++		FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_COPYAREA; ++ ++	ret = register_framebuffer(info); ++	if (ret < 0) { ++		dev_err(dev, "Failed to register framebuffer device: %d\n", ret); ++		goto unmap_mmio; ++	} ++ ++	dev_set_drvdata(dev, info); ++ ++	memset(info->screen_base, 0, info->fix.smem_len); ++	info->var.activate |= FB_ACTIVATE_NOW; ++	ret = fb_set_var(info, &info->var); ++	if (ret) { ++		dev_warn(dev, "Unable to set display parameters\n"); ++	} ++ ++	info->var.activate &= ~(FB_ACTIVATE_FORCE | FB_ACTIVATE_NOW); ++ ++	dev_dbg(dev, "%s SUCCESS\n", __func__); ++ ++	dev_info(dev, "Driver $Revision: 1.1 $\n");  +  +	return 0; ++ ++unmap_mmio: ++	iounmap(sinfo->mmio); ++release_mem: ++	release_mem_region(info->fix.mmio_start, info->fix.mmio_len); ++free_fb: ++	kfree(info->screen_base); ++ ++free_info: ++	framebuffer_release(info); ++ ++	dev_dbg(dev, "%s FAILED\n", __func__); ++	return ret;  +}  + -+static int gpio_led_resume(struct platform_device *pdev) ++ ++static int s1d15605fb_remove(struct platform_device *pdev)  +{ -+	struct gpio_led_platform_data *pdata = pdev->dev.platform_data; -+	struct gpio_led_data *leds_data; -+	int i; ++	struct device *dev = &pdev->dev; ++	struct fb_info *info = dev_get_drvdata(dev); ++	struct s1d15605fb_info *sinfo = info->par;  + -+	leds_data = platform_get_drvdata(pdev); ++	if (!sinfo) ++		return 0;  + -+	for (i = 0; i < pdata->num_leds; i++) -+		led_classdev_resume(&leds_data[i].cdev); ++	unregister_framebuffer(info);  + ++	iounmap(sinfo->mmio); ++	release_mem_region(info->fix.mmio_start, info->fix.mmio_len); ++ ++	kfree(info->screen_base); ++ ++	dev_set_drvdata(dev, NULL); ++	framebuffer_release(info);  +	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, ++ ++static struct platform_driver s1d15605fb_driver = { ++	.probe		= s1d15605fb_probe, ++	.remove		= s1d15605fb_remove,  +	.driver		= { -+		.name	= "leds-gpio", ++		.name	= "s1d15605fb",  +		.owner	= THIS_MODULE,  +	},  +};  + -+static int __init gpio_led_init(void) ++ ++static int __init s1d15605fb_init(void)  +{ -+	return platform_driver_probe(&gpio_led_driver, gpio_led_probe); ++	return platform_driver_register(&s1d15605fb_driver);  +}  + -+static void __exit gpio_led_exit(void) ++ ++static void __exit s1d15605fb_exit(void)  +{ -+	platform_driver_unregister(&gpio_led_driver); ++	platform_driver_unregister(&s1d15605fb_driver);  +}  + -+module_init(gpio_led_init); -+module_exit(gpio_led_exit);  + -+MODULE_AUTHOR("Raphael Assenat <raph@8d.com>"); -+MODULE_DESCRIPTION("GPIO LED driver"); ++module_init(s1d15605fb_init); ++module_exit(s1d15605fb_exit); ++ ++ ++MODULE_AUTHOR("KwikByte"); ++MODULE_DESCRIPTION("Epson S1D15605 LCD Controller framebuffer 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 +Index: linux-2.6.22.1/drivers/video/Kconfig +=================================================================== +--- linux-2.6.22.1/drivers/video/Kconfig	(revision 1) ++++ linux-2.6.22.1/drivers/video/Kconfig	(arbetskopia) +@@ -822,6 +822,17 @@ + 	  framebuffer.  Product specs at + 	  <http://www.erd.epson.com/vdc/html/products.htm>. +  ++config FB_S1D15605 ++	tristate "Epson S1D15605 framebuffer support" ++	depends on FB ++	default m if MACH_KB9200 ++	select FB_CFB_FILLRECT ++	select FB_CFB_COPYAREA ++	select FB_CFB_IMAGEBLIT ++	help ++	  Build in support for the S1D15605 Epson Research 128x64 ++	  LCD controller as a framebuffer. ++ + config FB_S1D13XXX + 	tristate "Epson S1D13XXX framebuffer support" + 	depends on FB +@@ -835,7 +846,7 @@ +  + config FB_ATMEL + 	tristate "AT91/AT32 LCD Controller support" +-	depends on FB && (ARCH_AT91SAM9261 || ARCH_AT91SAM9263 || AVR32) ++	depends on FB && (ARCH_AT91SAM9261 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || AVR32) + 	select FB_CFB_FILLRECT + 	select FB_CFB_COPYAREA + 	select FB_CFB_IMAGEBLIT +@@ -849,6 +860,16 @@ + 	  Say Y if you want to map Frame Buffer in internal SRAM. Say N if you want + 	  to let frame buffer in external SDRAM. - 	  If you are not sure, say Y here. ++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 +Index: linux-2.6.22.1/drivers/video/atmel_lcdfb.c +=================================================================== +--- linux-2.6.22.1/drivers/video/atmel_lcdfb.c	(revision 1) ++++ linux-2.6.22.1/drivers/video/atmel_lcdfb.c	(arbetskopia) +@@ -37,7 +37,9 @@ + #endif -+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). + #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,12 +76,35 @@ + 	.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;  + -+	  The SSC peripheral supports a wide variety of serial frame based -+	  communications, i.e. I2S, SPI, etc. ++	value = xres; ++	if ((lcdcon2 & ATMEL_LCDC_DISTYPE) != ATMEL_LCDC_DISTYPE_TFT) { ++		/* STN display */ ++		if ((lcdcon2 & ATMEL_LCDC_DISTYPE) == ATMEL_LCDC_DISTYPE_STNCOLOR) { ++			value *= 3; ++		} ++		if ( (lcdcon2 & ATMEL_LCDC_IFWIDTH) == ATMEL_LCDC_IFWIDTH_4 ++		   || ( (lcdcon2 & ATMEL_LCDC_IFWIDTH) == ATMEL_LCDC_IFWIDTH_8 ++		      && (lcdcon2 & ATMEL_LCDC_SCANMOD) == ATMEL_LCDC_SCANMOD_DUAL )) ++			value = DIV_ROUND_UP(value, 4); ++		else ++			value = DIV_ROUND_UP(value, 8); ++	} ++ ++	return value; ++} ++ + static void atmel_lcdfb_update_dma(struct fb_info *info, + 			       struct fb_var_screeninfo *var) + { +@@ -181,6 +206,7 @@ + 	var->xoffset = var->yoffset = 0; -+	  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 @@ + 	switch (var->bits_per_pixel) { ++	case 1: + 	case 2: + 	case 4: + 	case 8: +@@ -195,8 +221,11 @@ + 		var->blue.offset = 10; + 		var->red.length = var->green.length = var->blue.length = 5; + 		break; ++	case 32: ++		var->transp.offset = 24; ++		var->transp.length = 8; ++		/* fall through */ + 	case 24: +-	case 32: + 		var->red.offset = 0; + 		var->green.offset = 8; + 		var->blue.offset = 16; +@@ -228,8 +257,10 @@ + static int atmel_lcdfb_set_par(struct fb_info *info) + { + 	struct atmel_lcdfb_info *sinfo = info->par; ++	unsigned long hozval_linesz; + 	unsigned long value; + 	unsigned long clk_value_khz; ++	unsigned long bits_per_line; +  + 	dev_dbg(info->device, "%s:\n", __func__); + 	dev_dbg(info->device, "  * resolution: %ux%u (%ux%u virtual)\n", +@@ -241,12 +272,15 @@ +  + 	lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0); +  +-	if (info->var.bits_per_pixel <= 8) ++	if (info->var.bits_per_pixel == 1) ++		info->fix.visual = FB_VISUAL_MONO01; ++	else if (info->var.bits_per_pixel <= 8) + 		info->fix.visual = FB_VISUAL_PSEUDOCOLOR; + 	else + 		info->fix.visual = FB_VISUAL_TRUECOLOR; +  +-	info->fix.line_length = info->var.xres_virtual * (info->var.bits_per_pixel / 8); ++	bits_per_line = info->var.xres_virtual * info->var.bits_per_pixel; ++	info->fix.line_length = DIV_ROUND_UP(bits_per_line, 8); +  + 	/* Re-initialize the DMA engine... */ + 	dev_dbg(info->device, "  * update DMA engine\n"); +@@ -262,19 +296,22 @@ + 	/* Set pixel clock */ + 	clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000; +  +-	value = clk_value_khz / PICOS2KHZ(info->var.pixclock); ++	value = DIV_ROUND_UP(clk_value_khz, PICOS2KHZ(info->var.pixclock)); +  +-	if (clk_value_khz % PICOS2KHZ(info->var.pixclock)) +-		value++; +- + 	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 @@ + 	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 @@ + 			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; +Index: linux-2.6.22.1/drivers/video/Makefile +=================================================================== +--- linux-2.6.22.1/drivers/video/Makefile	(revision 1) ++++ linux-2.6.22.1/drivers/video/Makefile	(arbetskopia) +@@ -87,7 +87,8 @@ + obj-$(CONFIG_FB_SA1100)           += sa1100fb.o + obj-$(CONFIG_FB_HIT)              += hitfb.o + obj-$(CONFIG_FB_EPSON1355)	  += epson1355fb.o +-obj-$(CONFIG_FB_ATMEL)		  += atmel_lcdfb.o ++obj-$(CONFIG_FB_S1D15605)	  += s1d15605fb.o ++obj-$(CONFIG_FB_ATMEL)            += atmel_lcdfb.o + obj-$(CONFIG_FB_PVR2)             += pvr2fb.o + obj-$(CONFIG_FB_VOODOO1)          += sstfb.o + obj-$(CONFIG_FB_ARMCLCD)	  += amba-clcd.o +Index: linux-2.6.22.1/drivers/video/backlight/Kconfig +=================================================================== +--- linux-2.6.22.1/drivers/video/backlight/Kconfig	(revision 1) ++++ linux-2.6.22.1/drivers/video/backlight/Kconfig	(arbetskopia) +@@ -8,26 +8,44 @@ + 	  Enable this to be able to choose the drivers for controlling the + 	  backlight and the LCD panel on some platforms, for example on PDAs. +  +-config BACKLIGHT_CLASS_DEVICE +-        tristate "Lowlevel Backlight controls" ++# ++# LCD ++# ++config LCD_CLASS_DEVICE ++        tristate "Lowlevel LCD controls" + 	depends on BACKLIGHT_LCD_SUPPORT + 	default m + 	help +-	  This framework adds support for low-level control of the LCD +-          backlight. This includes support for brightness and power. ++	  This framework adds support for low-level control of LCD. ++	  Some framebuffer devices connect to platform-specific LCD modules ++	  in order to have a platform-specific way to control the flat panel ++	  (contrast and applying power to the LCD (not to the backlight!)). +  + 	  To have support for your specific LCD panel you will have to + 	  select the proper drivers which depend on this option. +  +-config LCD_CLASS_DEVICE +-        tristate "Lowlevel LCD controls" ++config LCD_LTV350QV ++	tristate "Samsung LTV350QV LCD Panel" ++	depends on LCD_CLASS_DEVICE && SPI_MASTER ++	default n ++	help ++	  If you have a Samsung LTV350QV LCD panel, say y to include a ++	  power control driver for it.  The panel starts up in power ++	  off state, so you need this driver in order to see any ++	  output. ++ ++	  The LTV350QV panel is present on all ATSTK1000 boards. ++ ++# ++# Backlight ++# ++config BACKLIGHT_CLASS_DEVICE ++        tristate "Lowlevel Backlight controls" + 	depends on BACKLIGHT_LCD_SUPPORT + 	default m + 	help +-	  This framework adds support for low-level control of LCD. +-	  Some framebuffer devices connect to platform-specific LCD modules +-	  in order to have a platform-specific way to control the flat panel +-	  (contrast and applying power to the LCD (not to the backlight!)). ++	  This framework adds support for low-level control of the LCD ++          backlight. This includes support for brightness and power. +  + 	  To have support for your specific LCD panel you will have to + 	  select the proper drivers which depend on this option. +@@ -71,3 +89,11 @@ + 	help + 	  If you have a Intel LE80578 (Carillo Ranch) say Y to enable the + 	  backlight driver. ++ ++config BACKLIGHT_KB920x ++	tristate "KwikByte KB9202 Backlight Driver" ++	depends on BACKLIGHT_CLASS_DEVICE && MACH_KB9200 ++	default y ++	help ++	  If you have a KwikByte KB9202 board, say Y to enable the ++	  backlight driver. +Index: linux-2.6.22.1/drivers/video/backlight/ltv350qv.c +=================================================================== +--- linux-2.6.22.1/drivers/video/backlight/ltv350qv.c	(revision 0) ++++ linux-2.6.22.1/drivers/video/backlight/ltv350qv.c	(revision 0) +@@ -0,0 +1,340 @@  +/* -+ * Atmel SSC driver ++ * Power control for Samsung LTV350QV Quarter VGA LCD Panel  + * -+ * Copyright (C) 2007 Atmel Corporation ++ * 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/platform_device.h> -+#include <linux/list.h> -+#include <linux/clk.h> ++#include <linux/delay.h>  +#include <linux/err.h> -+#include <linux/io.h> -+#include <linux/list.h> -+#include <linux/spinlock.h> -+#include <linux/atmel-ssc.h> ++#include <linux/fb.h> ++#include <linux/init.h> ++#include <linux/lcd.h> ++#include <linux/module.h> ++#include <linux/spi/spi.h>  + -+/* Serialize access to ssc_list and user count */ -+static DEFINE_SPINLOCK(user_lock); -+static LIST_HEAD(ssc_list); ++#include "ltv350qv.h"  + -+struct ssc_device *ssc_request(unsigned int ssc_num) ++#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)  +{ -+	int ssc_valid = 0; -+	struct ssc_device *ssc; ++	struct spi_message msg; ++	struct spi_transfer index_xfer = { ++		.len		= 3, ++		.cs_change	= 1, ++	}; ++	struct spi_transfer value_xfer = { ++		.len		= 3, ++		.cs_change	= 1, ++	};  + -+	spin_lock(&user_lock); -+	list_for_each_entry(ssc, &ssc_list, list) { -+		if (ssc->pdev->id == ssc_num) { -+			ssc_valid = 1; -+			break; -+		} -+	} ++	spi_message_init(&msg);  + -+	if (!ssc_valid) { -+		spin_unlock(&user_lock); -+		dev_dbg(&ssc->pdev->dev, "could not find requested device\n"); -+		return ERR_PTR(-ENODEV); -+	} ++	/* 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);  + -+	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); ++	/* 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);  + -+	clk_enable(ssc->clk); ++	return spi_sync(lcd->spi, &msg); ++}  + -+	return ssc; ++/* 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;  +} -+EXPORT_SYMBOL(ssc_request);  + -+void ssc_free(struct ssc_device *ssc) ++static int ltv350qv_power_off(struct ltv350qv *lcd)  +{ -+	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); ++	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;  +} -+EXPORT_SYMBOL(ssc_free);  + -+static int __init ssc_probe(struct platform_device *pdev) ++static int ltv350qv_power(struct ltv350qv *lcd, int power)  +{ -+	int retval = 0; -+	struct resource *regs; -+	struct ssc_device *ssc; ++	int ret = 0;  + -+	ssc = kzalloc(sizeof(struct ssc_device), GFP_KERNEL); -+	if (!ssc) { -+		dev_dbg(&pdev->dev, "out of memory\n"); -+		retval = -ENOMEM; -+		goto out; -+	} ++	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);  + -+	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+	if (!regs) { -+		dev_dbg(&pdev->dev, "no mmio resource defined\n"); -+		retval = -ENXIO; -+		goto out_free; -+	} ++	if (!ret) ++		lcd->power = power;  + -+	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; -+	} ++	return ret; ++}  + -+	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; -+	} ++static int ltv350qv_set_power(struct lcd_device *ld, int power) ++{ ++	struct ltv350qv *lcd;  + -+	/* disable all interrupts */ -+	clk_enable(ssc->clk); -+	ssc_writel(ssc->regs, IDR, ~0UL); -+	ssc_readl(ssc->regs, SR); -+	clk_disable(ssc->clk); ++	lcd = class_get_devdata(&ld->class_dev); ++	return ltv350qv_power(lcd, power); ++}  + -+	ssc->irq = platform_get_irq(pdev, 0); -+	if (!ssc->irq) { -+		dev_dbg(&pdev->dev, "could not get irq\n"); -+		retval = -ENXIO; -+		goto out_unmap; ++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;  + -+	spin_lock(&user_lock); -+	list_add_tail(&ssc->list, &ssc_list); -+	spin_unlock(&user_lock); ++	ret = ltv350qv_power(lcd, FB_BLANK_UNBLANK); ++	if (ret) ++		goto out_unregister;  + -+	platform_set_drvdata(pdev, ssc); ++	dev_set_drvdata(&spi->dev, lcd);  + -+	dev_info(&pdev->dev, "Atmel SSC device at 0x%p (irq %d)\n", -+			ssc->regs, ssc->irq); ++	return 0;  + -+	goto out; ++out_unregister: ++	lcd_device_unregister(ld); ++out_free_lcd: ++	kfree(lcd); ++	return ret; ++}  + -+out_unmap: -+	iounmap(ssc->regs); -+out_clk: -+	clk_put(ssc->clk); -+out_free: -+	kfree(ssc); -+out: -+	return retval; ++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;  +}  + -+static int __devexit ssc_remove(struct platform_device *pdev) ++#ifdef CONFIG_PM ++static int ltv350qv_suspend(struct spi_device *spi, ++			    pm_message_t state, u32 level)  +{ -+	struct ssc_device *ssc = platform_get_drvdata(pdev); ++	struct ltv350qv *lcd = dev_get_drvdata(&spi->dev);  + -+	spin_lock(&user_lock); -+	iounmap(ssc->regs); -+	clk_put(ssc->clk); -+	list_del(&ssc->list); -+	kfree(ssc); -+	spin_unlock(&user_lock); ++	if (level == SUSPEND_POWER_DOWN) ++		return ltv350qv_power(lcd, FB_BLANK_POWERDOWN);  +  +	return 0;  +}  + -+static struct platform_driver ssc_driver = { -+	.remove		= __devexit_p(ssc_remove), ++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"); +Index: linux-2.6.22.1/drivers/video/backlight/ltv350qv.h +=================================================================== +--- linux-2.6.22.1/drivers/video/backlight/ltv350qv.h	(revision 0) ++++ linux-2.6.22.1/drivers/video/backlight/ltv350qv.h	(revision 0) +@@ -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 */ +Index: linux-2.6.22.1/drivers/video/backlight/Makefile +=================================================================== +--- linux-2.6.22.1/drivers/video/backlight/Makefile	(revision 1) ++++ linux-2.6.22.1/drivers/video/backlight/Makefile	(arbetskopia) +@@ -1,9 +1,12 @@ + # 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 + obj-$(CONFIG_BACKLIGHT_LOCOMO)	+= locomolcd.o + obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o + obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o ++obj-$(CONFIG_BACKLIGHT_KB920x)	+= kb920x_bl.o +Index: linux-2.6.22.1/drivers/video/backlight/kb920x_bl.c +=================================================================== +--- linux-2.6.22.1/drivers/video/backlight/kb920x_bl.c	(revision 0) ++++ linux-2.6.22.1/drivers/video/backlight/kb920x_bl.c	(revision 0) +@@ -0,0 +1,164 @@ ++/* ++ * Backlight Driver for KB9202 ++ * ++ * Copyright (c) 2006 KwikByte ++ * ++ * Based on Sharp's Corgi Backlight Driver ++ * ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License.  See the file "COPYING" in the main directory of this archive ++ * for more details. ++ */ ++ ++#include <linux/module.h> ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/platform_device.h> ++#include <linux/spinlock.h> ++#include <linux/fb.h> ++#include <linux/backlight.h> ++ ++#include <asm/arch/gpio.h> ++ ++/* The backlight is on(1)/off(0) */ ++#define	KB9202_DEFAULT_INTENSITY	1 ++#define	KB9202_MAX_INTENSITY		1 ++ ++static int kb9202bl_suspended; ++static int current_intensity = 0; ++static DEFINE_SPINLOCK(bl_lock); ++ ++static int kb9202bl_set_intensity(struct backlight_device *bd) ++{ ++	unsigned long flags; ++	int intensity = bd->props.brightness; ++ ++	if (bd->props.power != FB_BLANK_UNBLANK) ++		intensity = 0; ++	if (bd->props.fb_blank != FB_BLANK_UNBLANK) ++		intensity = 0; ++	if (kb9202bl_suspended) ++		intensity = 0; ++ ++	if ((!current_intensity) && (bd->props.power == FB_BLANK_UNBLANK)) ++		intensity = 1; ++ ++	spin_lock_irqsave(&bl_lock, flags); ++	if (intensity) ++		gpio_set_value(AT91_PIN_PC23, 1); ++	else ++		gpio_set_value(AT91_PIN_PC23, 0); ++	spin_unlock_irqrestore(&bl_lock, flags); ++ ++	current_intensity = intensity; ++ ++	return 0; ++} ++ ++static int kb9202bl_get_intensity(struct backlight_device *bd) ++{ ++	return current_intensity; ++} ++ ++static struct backlight_ops kb9202bl_ops = { ++	.get_brightness	= kb9202bl_get_intensity, ++	.update_status	= kb9202bl_set_intensity, ++}; ++ ++static int __init kb9202bl_probe(struct platform_device *pdev) ++{ ++	struct backlight_device *bd; ++ ++	bd = backlight_device_register ("kb9202-bl", &pdev->dev, NULL, &kb9202bl_ops); ++	if (IS_ERR(bd)) ++		return PTR_ERR(bd); ++ ++	platform_set_drvdata(pdev, bd); ++ ++	bd->props.max_brightness = KB9202_MAX_INTENSITY; ++	bd->props.brightness = KB9202_DEFAULT_INTENSITY; ++	(void) kb9202bl_set_intensity(bd); ++ ++	return 0; ++} ++ ++static int kb9202bl_remove(struct platform_device *pdev) ++{ ++	struct backlight_device *bd = platform_get_drvdata(pdev); ++ ++	bd->props.brightness = 0; ++	bd->props.power = 0; ++	(void) kb9202bl_set_intensity(bd); ++ ++	backlight_device_unregister(bd); ++ ++	return 0; ++} ++ ++#ifdef CONFIG_PM ++static int kb9202bl_suspend(struct platform_device *dev, pm_message_t state) ++{ ++	struct backlight_device *bd = platform_get_drvdata(pdev); ++ ++	kb9202bl_suspended = 1; ++	(void) kb9202bl_set_intensity(bd); ++	return 0; ++} ++ ++static int kb9202bl_resume(struct platform_device *dev) ++{ ++	struct backlight_device *bd = platform_get_drvdata(pdev); ++ ++	kb9202bl_suspended = 0; ++	(void) kb9202bl_set_intensity(bd); ++	return 0; ++} ++#else ++#define kb9202bl_suspend	NULL ++#define kb9202bl_resume		NULL ++#endif ++ ++static struct platform_driver kb9202bl_driver = { ++	.probe		= kb9202bl_probe, ++	.remove		= kb9202bl_remove, ++	.suspend	= kb9202bl_suspend, ++	.resume		= kb9202bl_resume,  +	.driver		= { -+		.name		= "ssc", ++		.name	= "kb9202-bl", ++		.owner	= THIS_MODULE,  +	},  +};  + -+static int __init ssc_init(void) ++static struct platform_device *kb9202bl_device; ++ ++static int __init kb9202bl_init(void)  +{ -+	return platform_driver_probe(&ssc_driver, ssc_probe); ++	int ret; ++ ++	ret = platform_driver_register(&kb9202bl_driver); ++	if (!ret) { ++		kb9202bl_device = platform_device_alloc("kb9202-bl", -1); ++		if (!kb9202bl_device) ++			return -ENOMEM; ++ ++		ret = platform_device_add(kb9202bl_device); ++		if (ret) { ++			platform_device_put(kb9202bl_device); ++			platform_driver_unregister(&kb9202bl_driver); ++		} ++	} ++	return ret;  +} -+module_init(ssc_init);  + -+static void __exit ssc_exit(void) ++static void __exit kb9202bl_exit(void)  +{ -+	platform_driver_unregister(&ssc_driver); ++	platform_device_unregister(kb9202bl_device); ++	platform_driver_unregister(&kb9202bl_driver);  +} -+module_exit(ssc_exit);  + -+MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>"); -+MODULE_DESCRIPTION("SSC driver for Atmel AVR32 and AT91"); ++module_init(kb9202bl_init); ++module_exit(kb9202bl_exit); ++ ++MODULE_AUTHOR("KwikByte <kb9200_dev@kwikbyte.com>"); ++MODULE_DESCRIPTION("KB9202 Backlight Driver");  +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 +Index: linux-2.6.22.1/drivers/mmc/host/Kconfig +=================================================================== +--- linux-2.6.22.1/drivers/mmc/host/Kconfig	(revision 1) ++++ linux-2.6.22.1/drivers/mmc/host/Kconfig	(arbetskopia) +@@ -74,6 +74,16 @@   	  If unsure, say N. @@ -6356,22 +16745,106 @@ index e23082f..1de1716 100644   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 +Index: linux-2.6.22.1/drivers/mmc/host/at91_mci.c +=================================================================== +--- linux-2.6.22.1/drivers/mmc/host/at91_mci.c	(revision 1) ++++ linux-2.6.22.1/drivers/mmc/host/at91_mci.c	(arbetskopia) +@@ -85,7 +85,7 @@ +  + #define AT91_MCI_ERRORS	(AT91_MCI_RINDE | AT91_MCI_RDIRE | AT91_MCI_RCRCE	\ + 		| AT91_MCI_RENDE | AT91_MCI_RTOE | AT91_MCI_DCRCE		\ +-		| AT91_MCI_DTOE | AT91_MCI_OVRE | AT91_MCI_UNRE)			 ++		| AT91_MCI_DTOE | AT91_MCI_OVRE | AT91_MCI_UNRE) +  + #define at91_mci_read(host, reg)	__raw_readl((host)->baseaddr + (reg)) + #define at91_mci_write(host, reg, val)	__raw_writel((val), (host)->baseaddr + (reg)) +@@ -560,9 +560,7 @@ + 	pr_debug("Status = %08X [%08X %08X %08X %08X]\n", + 		 status, cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]); +  +-	if (status & (AT91_MCI_RINDE | AT91_MCI_RDIRE | AT91_MCI_RCRCE | +-			AT91_MCI_RENDE | AT91_MCI_RTOE | AT91_MCI_DCRCE | +-			AT91_MCI_DTOE | AT91_MCI_OVRE | AT91_MCI_UNRE)) { ++	if (status & (AT91_MCI_ERRORS)) { + 		if ((status & AT91_MCI_RCRCE) && !(mmc_resp_type(cmd) & MMC_RSP_CRC)) { + 			cmd->error = MMC_ERR_NONE; + 		} +@@ -663,15 +661,15 @@ +  + 	int_status = at91_mci_read(host, AT91_MCI_SR); + 	int_mask = at91_mci_read(host, AT91_MCI_IMR); +-	 ++ + 	pr_debug("MCI irq: status = %08X, %08X, %08X\n", int_status, int_mask, + 		int_status & int_mask); +-	 ++ + 	int_status = int_status & int_mask; -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 + 	if (int_status & AT91_MCI_ERRORS) { + 		completed = 1; +-		 ++ + 		if (int_status & AT91_MCI_UNRE) + 			pr_debug("MMC: Underrun error\n"); + 		if (int_status & AT91_MCI_OVRE) +@@ -819,7 +817,7 @@ + 	mmc->f_min = 375000; + 	mmc->f_max = 25000000; + 	mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; +-	mmc->caps = MMC_CAP_BYTEBLOCK; ++	mmc->caps = MMC_CAP_BYTEBLOCK | MMC_CAP_MULTIWRITE; +  + 	mmc->max_blk_size = 4095; + 	mmc->max_blk_count = mmc->max_req_size; +@@ -893,6 +891,8 @@ +  + 	mmc_add_host(mmc); +  ++	device_init_wakeup(&pdev->dev, 1); ++ + 	/* + 	 * monitor card insertion/removal if we can + 	 */ +@@ -922,6 +922,8 @@ +  + 	host = mmc_priv(mmc); +  ++	device_init_wakeup(&pdev->dev, 0); ++ + 	if (host->present != -1) { + 		free_irq(host->board->det_pin, host); + 		cancel_delayed_work(&host->mmc->detect); +@@ -949,8 +951,12 @@ + static int at91_mci_suspend(struct platform_device *pdev, pm_message_t state) + { + 	struct mmc_host *mmc = platform_get_drvdata(pdev); ++	struct at91mci_host *host = mmc_priv(mmc); + 	int ret = 0; +  ++	if (device_may_wakeup(&pdev->dev)) ++		enable_irq_wake(host->board->det_pin); ++ + 	if (mmc) + 		ret = mmc_suspend_host(mmc, state); +  +@@ -960,8 +966,12 @@ + static int at91_mci_resume(struct platform_device *pdev) + { + 	struct mmc_host *mmc = platform_get_drvdata(pdev); ++	struct at91mci_host *host = mmc_priv(mmc); + 	int ret = 0; +  ++	if (device_may_wakeup(&pdev->dev)) ++		disable_irq_wake(host->board->det_pin); ++ + 	if (mmc) + 		ret = mmc_resume_host(mmc); +  +Index: linux-2.6.22.1/drivers/mmc/host/atmel-mci.c +=================================================================== +--- linux-2.6.22.1/drivers/mmc/host/atmel-mci.c	(revision 0) ++++ linux-2.6.22.1/drivers/mmc/host/atmel-mci.c	(revision 0)  @@ -0,0 +1,1217 @@  +/*  + * Atmel MultiMedia Card Interface driver @@ -7590,11 +18063,10 @@ index 0000000..74d343f  +  +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 +Index: linux-2.6.22.1/drivers/mmc/host/atmel-mci.h +=================================================================== +--- linux-2.6.22.1/drivers/mmc/host/atmel-mci.h	(revision 0) ++++ linux-2.6.22.1/drivers/mmc/host/atmel-mci.h	(revision 0)  @@ -0,0 +1,192 @@  +/*  + * Atmel MultiMedia Card Interface driver @@ -7788,122 +18260,1577 @@ index 0000000..60d15c4  +	__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 +Index: linux-2.6.22.1/drivers/mmc/host/Makefile +=================================================================== +--- linux-2.6.22.1/drivers/mmc/host/Makefile	(revision 1) ++++ linux-2.6.22.1/drivers/mmc/host/Makefile	(arbetskopia) +@@ -14,5 +14,6 @@ + obj-$(CONFIG_MMC_AU1X)		+= au1xmmc.o + obj-$(CONFIG_MMC_OMAP)		+= omap.o + obj-$(CONFIG_MMC_AT91)		+= at91_mci.o ++obj-$(CONFIG_MMC_ATMELMCI)	+= atmel-mci.o + obj-$(CONFIG_MMC_TIFM_SD)	+= tifm_sd.o - 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 +Index: linux-2.6.22.1/drivers/misc/Kconfig +=================================================================== +--- linux-2.6.22.1/drivers/misc/Kconfig	(revision 1) ++++ linux-2.6.22.1/drivers/misc/Kconfig	(arbetskopia) +@@ -187,5 +187,15 @@ -+/* Atmel chips don't use the same PRI format as Intel chips */ -+static void fixup_convert_atmel_pri(struct mtd_info *mtd, void *param) + 	  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 +Index: linux-2.6.22.1/drivers/misc/atmel-ssc.c +=================================================================== +--- linux-2.6.22.1/drivers/misc/atmel-ssc.c	(revision 0) ++++ linux-2.6.22.1/drivers/misc/atmel-ssc.c	(revision 0) +@@ -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)  +{ -+	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; ++	int ssc_valid = 0; ++	struct ssc_device *ssc;  + -+	/* Reverse byteswapping */ -+	extp->FeatureSupport = cpu_to_le32(extp->FeatureSupport); -+	extp->BlkStatusRegMask = cpu_to_le16(extp->BlkStatusRegMask); -+	extp->ProtRegAddr = cpu_to_le16(extp->ProtRegAddr); ++	spin_lock(&user_lock); ++	list_for_each_entry(ssc, &ssc_list, list) { ++		if (ssc->pdev->id == ssc_num) { ++			ssc_valid = 1; ++			break; ++		} ++	}  + -+	memcpy(&atmel_pri, extp, sizeof(atmel_pri)); -+	memset((char *)extp + 5, 0, sizeof(*extp) - 5); ++	if (!ssc_valid) { ++		spin_unlock(&user_lock); ++		dev_dbg(&ssc->pdev->dev, "could not find requested device\n"); ++		return ERR_PTR(-ENODEV); ++	}  + -+	printk(KERN_ERR "atmel Features: %02x\n", atmel_pri.Features); ++	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);  + -+	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); ++	clk_enable(ssc->clk);  + -+	extp->FeatureSupport = features; ++	return ssc; ++} ++EXPORT_SYMBOL(ssc_request);  + -+	/* burst write mode not supported */ -+	cfi->cfiq->BufWriteTimeoutTyp = 0; -+	cfi->cfiq->BufWriteTimeoutMax = 0; ++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);  + - #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 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"); +Index: linux-2.6.22.1/drivers/misc/Makefile +=================================================================== +--- linux-2.6.22.1/drivers/misc/Makefile	(revision 1) ++++ linux-2.6.22.1/drivers/misc/Makefile	(arbetskopia) +@@ -14,3 +14,4 @@ + 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 +Index: linux-2.6.22.1/drivers/rtc/Kconfig +=================================================================== +--- linux-2.6.22.1/drivers/rtc/Kconfig	(revision 1) ++++ linux-2.6.22.1/drivers/rtc/Kconfig	(arbetskopia) +@@ -379,6 +379,13 @@ + 	  To compile this driver as a module, choose M here: the + 	  module will be called rtc-pl031. - 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; ++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.  + -+	/* burst write mode not supported */ -+	cfi->cfiq->BufWriteTimeoutTyp = 0; -+	cfi->cfiq->BufWriteTimeoutMax = 0; - } + config RTC_DRV_AT91RM9200 + 	tristate "AT91RM9200" + 	depends on RTC_CLASS && ARCH_AT91RM9200 +Index: linux-2.6.22.1/drivers/rtc/rtc-at32ap700x.c +=================================================================== +--- linux-2.6.22.1/drivers/rtc/rtc-at32ap700x.c	(revision 0) ++++ linux-2.6.22.1/drivers/rtc/rtc-at32ap700x.c	(revision 0) +@@ -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"); +Index: linux-2.6.22.1/drivers/rtc/Makefile +=================================================================== +--- linux-2.6.22.1/drivers/rtc/Makefile	(revision 1) ++++ linux-2.6.22.1/drivers/rtc/Makefile	(arbetskopia) +@@ -19,6 +19,7 @@ + obj-$(CONFIG_RTC_DRV_X1205)	+= rtc-x1205.o + obj-$(CONFIG_RTC_DRV_ISL1208)	+= rtc-isl1208.o + obj-$(CONFIG_RTC_DRV_TEST)	+= rtc-test.o ++obj-$(CONFIG_RTC_DRV_AT32AP700X)	+= rtc-at32ap700x.o + obj-$(CONFIG_RTC_DRV_DS1307)	+= rtc-ds1307.o + obj-$(CONFIG_RTC_DRV_DS1672)	+= rtc-ds1672.o + obj-$(CONFIG_RTC_DRV_DS1742)	+= rtc-ds1742.o +Index: linux-2.6.22.1/drivers/char/watchdog/Kconfig +=================================================================== +--- linux-2.6.22.1/drivers/char/watchdog/Kconfig	(revision 1) ++++ linux-2.6.22.1/drivers/char/watchdog/Kconfig	(arbetskopia) +@@ -187,6 +187,26 @@ - 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) - } + 	  Say N if you are unsure. - 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 ++# 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 +Index: linux-2.6.22.1/drivers/char/watchdog/Makefile +=================================================================== +--- linux-2.6.22.1/drivers/char/watchdog/Makefile	(revision 1) ++++ linux-2.6.22.1/drivers/char/watchdog/Makefile	(arbetskopia) +@@ -36,6 +36,9 @@ + obj-$(CONFIG_EP93XX_WATCHDOG) += ep93xx_wdt.o + obj-$(CONFIG_PNX4008_WATCHDOG) += pnx4008_wdt.o +  ++# AVR32 Architecture ++obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o ++ + # X86 (i386 + ia64 + x86_64) Architecture + obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o + obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o +Index: linux-2.6.22.1/drivers/char/watchdog/at32ap700x_wdt.c +=================================================================== +--- linux-2.6.22.1/drivers/char/watchdog/at32ap700x_wdt.c	(revision 0) ++++ linux-2.6.22.1/drivers/char/watchdog/at32ap700x_wdt.c	(revision 0) +@@ -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); +Index: linux-2.6.22.1/drivers/char/at91_spi.c +=================================================================== +--- linux-2.6.22.1/drivers/char/at91_spi.c	(revision 0) ++++ linux-2.6.22.1/drivers/char/at91_spi.c	(revision 0) +@@ -0,0 +1,336 @@ ++/* ++ * Serial Peripheral Interface (SPI) driver for the Atmel AT91RM9200 (Thunder) ++ * ++ *  Copyright (C) SAN People (Pty) Ltd ++ * ++ * 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/init.h> ++#include <linux/dma-mapping.h> ++#include <linux/module.h> ++#include <linux/sched.h> ++#include <linux/completion.h> ++#include <linux/interrupt.h> ++#include <linux/clk.h> ++#include <linux/platform_device.h> ++#include <linux/atmel_pdc.h> ++#include <asm/io.h> ++#include <asm/semaphore.h> ++ ++#include <asm/arch/at91_spi.h> ++#include <asm/arch/board.h> ++#include <asm/arch/spi.h> ++ ++#undef DEBUG_SPI ++ ++static struct spi_local spi_dev[NR_SPI_DEVICES];	/* state of the SPI devices */ ++static int spi_enabled = 0; ++static struct semaphore spi_lock;			/* protect access to SPI bus */ ++static int current_device = -1;				/* currently selected SPI device */ ++static struct clk *spi_clk;				/* SPI clock */ ++static void __iomem *spi_base;				/* SPI peripheral base-address */ ++ ++DECLARE_COMPLETION(transfer_complete); ++ ++ ++#define at91_spi_read(reg)		__raw_readl(spi_base + (reg)) ++#define at91_spi_write(reg, val)	__raw_writel((val), spi_base + (reg)) ++ ++ ++/* ......................................................................... */ ++ ++/* ++ * Access and enable the SPI bus. ++ * This MUST be called before any transfers are performed. ++ */ ++void spi_access_bus(short device) ++{ ++	/* Ensure that requested device is valid */ ++	if ((device < 0) || (device >= NR_SPI_DEVICES)) ++		panic("at91_spi: spi_access_bus called with invalid device"); ++ ++	if (spi_enabled == 0) { ++		clk_enable(spi_clk);				/* Enable Peripheral clock */ ++		at91_spi_write(AT91_SPI_CR, AT91_SPI_SPIEN);	/* Enable SPI */ ++#ifdef DEBUG_SPI ++		printk("SPI on\n"); ++#endif ++	} ++	spi_enabled++; ++ ++	/* Lock the SPI bus */ ++	down(&spi_lock); ++	current_device = device; ++ ++	/* Configure SPI bus for device */ ++	at91_spi_write(AT91_SPI_MR, AT91_SPI_MSTR | AT91_SPI_MODFDIS | (spi_dev[device].pcs << 16)); ++} ++ ++/* ++ * Relinquish control of the SPI bus. ++ */ ++void spi_release_bus(short device) ++{ ++	if (device != current_device) ++		panic("at91_spi: spi_release called with invalid device"); ++ ++	/* Release the SPI bus */ ++	current_device = -1; ++	up(&spi_lock); ++ ++	spi_enabled--; ++	if (spi_enabled == 0) { ++		at91_spi_write(AT91_SPI_CR, AT91_SPI_SPIDIS);	/* Disable SPI */ ++		clk_disable(spi_clk);				/* Disable Peripheral clock */ ++#ifdef DEBUG_SPI ++		printk("SPI off\n"); ++#endif ++	} ++} ++ ++/* ++ * Perform a data transfer over the SPI bus ++ */ ++int spi_transfer(struct spi_transfer_list* list) ++{ ++	struct spi_local *device = (struct spi_local *) &spi_dev[current_device]; ++	int tx_size; ++ ++	if (!list) ++		panic("at91_spi: spi_transfer called with NULL transfer list"); ++	if (current_device == -1) ++		panic("at91_spi: spi_transfer called without acquiring bus"); ++ ++#ifdef DEBUG_SPI ++	printk("SPI transfer start [%i]\n", list->nr_transfers); ++#endif ++ ++	/* If we are in 16-bit mode, we need to modify what we pass to the PDC */ ++	tx_size = (at91_spi_read(AT91_SPI_CSR(current_device)) & AT91_SPI_BITS_16) ? 2 : 1; ++ ++	/* Store transfer list */ ++	device->xfers = list; ++	list->curr = 0; ++ ++	/* Assume there must be at least one transfer */ ++	device->tx = dma_map_single(NULL, list->tx[0], list->txlen[0], DMA_TO_DEVICE); ++	device->rx = dma_map_single(NULL, list->rx[0], list->rxlen[0], DMA_FROM_DEVICE); ++ ++	/* Program PDC registers */ ++	at91_spi_write(ATMEL_PDC_TPR, device->tx); ++	at91_spi_write(ATMEL_PDC_RPR, device->rx); ++	at91_spi_write(ATMEL_PDC_TCR, list->txlen[0] / tx_size); ++	at91_spi_write(ATMEL_PDC_RCR, list->rxlen[0] / tx_size); ++ ++	/* Is there a second transfer? */ ++	if (list->nr_transfers > 1) { ++		device->txnext = dma_map_single(NULL, list->tx[1], list->txlen[1], DMA_TO_DEVICE); ++		device->rxnext = dma_map_single(NULL, list->rx[1], list->rxlen[1], DMA_FROM_DEVICE); ++ ++		/* Program Next PDC registers */ ++		at91_spi_write(ATMEL_PDC_TNPR, device->txnext); ++		at91_spi_write(ATMEL_PDC_RNPR, device->rxnext); ++		at91_spi_write(ATMEL_PDC_TNCR, list->txlen[1] / tx_size); ++		at91_spi_write(ATMEL_PDC_RNCR, list->rxlen[1] / tx_size); ++	} ++	else { ++		device->txnext = 0; ++		device->rxnext = 0; ++		at91_spi_write(ATMEL_PDC_TNCR, 0); ++		at91_spi_write(ATMEL_PDC_RNCR, 0); ++	} ++ ++	// TODO: If we are doing consecutive transfers (at high speed, or ++	//   small buffers), then it might be worth modifying the 'Delay between ++	//   Consecutive Transfers' in the CSR registers. ++	//   This is an issue if we cannot chain the next buffer fast enough ++	//   in the interrupt handler. ++ ++	/* Enable transmitter and receiver */ ++	at91_spi_write(ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN | ATMEL_PDC_TXTEN); ++ ++	at91_spi_write(AT91_SPI_IER, AT91_SPI_ENDRX);		/* enable buffer complete interrupt */ ++	wait_for_completion(&transfer_complete); ++ ++#ifdef DEBUG_SPI ++	printk("SPI transfer end\n"); ++#endif ++ ++	return 0; ++} ++ ++/* ......................................................................... */ ++ ++/* ++ * Handle interrupts from the SPI controller. ++ */ ++static irqreturn_t at91spi_interrupt(int irq, void *dev_id) ++{ ++	unsigned int status; ++	struct spi_local *device = (struct spi_local *) &spi_dev[current_device]; ++	struct spi_transfer_list *list = device->xfers; ++ ++#ifdef DEBUG_SPI ++	printk("SPI interrupt %i\n", current_device); ++#endif ++ ++	if (!list) ++		panic("at91_spi: spi_interrupt with a NULL transfer list"); ++ ++		status = at91_spi_read(AT91_SPI_SR) & at91_spi_read(AT91_SPI_IMR);	/* read status */ ++ ++	dma_unmap_single(NULL, device->tx, list->txlen[list->curr], DMA_TO_DEVICE); ++	dma_unmap_single(NULL, device->rx, list->rxlen[list->curr], DMA_FROM_DEVICE); ++ ++	device->tx = device->txnext;	/* move next transfer to current transfer */ ++	device->rx = device->rxnext; ++ ++	list->curr = list->curr + 1; ++	if (list->curr == list->nr_transfers) {		/* all transfers complete */ ++		at91_spi_write(AT91_SPI_IDR, AT91_SPI_ENDRX);		/* disable interrupt */ ++ ++		/* Disable transmitter and receiver */ ++		at91_spi_write(ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS); ++ ++		device->xfers = NULL; ++		complete(&transfer_complete); ++	} ++	else if (list->curr+1 == list->nr_transfers) {	/* no more next transfers */ ++		device->txnext = 0; ++		device->rxnext = 0; ++		at91_spi_write(ATMEL_PDC_TNCR, 0); ++		at91_spi_write(ATMEL_PDC_RNCR, 0); ++	} ++	else { ++		int i = (list->curr)+1; ++ ++		/* If we are in 16-bit mode, we need to modify what we pass to the PDC */ ++		int tx_size = (at91_spi_read(AT91_SPI_CSR(current_device)) & AT91_SPI_BITS_16) ? 2 : 1; ++ ++		device->txnext = dma_map_single(NULL, list->tx[i], list->txlen[i], DMA_TO_DEVICE); ++		device->rxnext = dma_map_single(NULL, list->rx[i], list->rxlen[i], DMA_FROM_DEVICE); ++		at91_spi_write(ATMEL_PDC_TNPR, device->txnext); ++		at91_spi_write(ATMEL_PDC_RNPR, device->rxnext); ++		at91_spi_write(ATMEL_PDC_TNCR, list->txlen[i] / tx_size); ++		at91_spi_write(ATMEL_PDC_RNCR, list->rxlen[i] / tx_size); ++	} ++	return IRQ_HANDLED; ++} ++ ++/* ......................................................................... */ ++ ++/* ++ * Initialize the SPI controller ++ */ ++static int __init at91spi_probe(struct platform_device *pdev) ++{ ++	int i; ++	unsigned long scbr; ++	struct resource *res; ++ ++	init_MUTEX(&spi_lock); ++ ++	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++	if (!res) ++		return -ENXIO; ++ ++	if (!request_mem_region(res->start, res->end - res->start + 1, "at91_spi")) ++		return -EBUSY; ++ ++	spi_base = ioremap(res->start, res->end - res->start + 1); ++	if (!spi_base) { ++		release_mem_region(res->start, res->end - res->start + 1); ++		return -ENOMEM; ++	} ++ ++	spi_clk = clk_get(NULL, "spi_clk"); ++	if (IS_ERR(spi_clk)) { ++		printk(KERN_ERR "at91_spi: no clock defined\n"); ++		iounmap(spi_base); ++		release_mem_region(res->start, res->end - res->start + 1); ++		return -ENODEV; ++	} ++ ++	at91_spi_write(AT91_SPI_CR, AT91_SPI_SWRST);	/* software reset of SPI controller */ ++ ++	/* ++	 * Calculate the correct SPI baud-rate divisor. ++	 */ ++	scbr = clk_get_rate(spi_clk) / (2 * DEFAULT_SPI_CLK); ++	scbr = scbr + 1;		/* round up */ ++ ++	printk(KERN_INFO "at91_spi: Baud rate set to %ld\n", clk_get_rate(spi_clk) / (2 * scbr)); ++ ++	/* Set Chip Select registers to good defaults */ ++	for (i = 0; i < 4; i++) { ++		at91_spi_write(AT91_SPI_CSR(i), AT91_SPI_CPOL | AT91_SPI_BITS_8 | (16 << 16) | (scbr << 8)); ++	} ++ ++	at91_spi_write(ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS); ++ ++	memset(&spi_dev, 0, sizeof(spi_dev)); ++	spi_dev[0].pcs = 0xE; ++	spi_dev[1].pcs = 0xD; ++	spi_dev[2].pcs = 0xB; ++	spi_dev[3].pcs = 0x7; ++ ++	if (request_irq(AT91RM9200_ID_SPI, at91spi_interrupt, 0, "spi", NULL)) { ++		clk_put(spi_clk); ++		iounmap(spi_base); ++		release_mem_region(res->start, res->end - res->start + 1); ++		return -EBUSY; ++	} ++ ++	at91_spi_write(AT91_SPI_CR, AT91_SPI_SPIEN);		/* Enable SPI */ ++ ++	return 0; ++} ++ ++static int __devexit at91spi_remove(struct platform_device *pdev) ++{ ++	struct resource *res; ++ ++	at91_spi_write(AT91_SPI_CR, AT91_SPI_SPIDIS);		/* Disable SPI */ ++	clk_put(spi_clk); ++ ++	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++	iounmap(spi_base); ++	release_mem_region(res->start, res->end - res->start + 1); ++ ++	free_irq(AT91RM9200_ID_SPI, 0); ++	return 0; ++} ++ ++static struct platform_driver at91spi_driver = { ++	.probe		= at91spi_probe, ++	.remove		= __devexit_p(at91spi_remove), ++	.driver		= { ++		.name	= "at91_spi", ++		.owner	= THIS_MODULE, ++	}, ++}; ++ ++static int __init at91spi_init(void) ++{ ++	return platform_driver_register(&at91spi_driver); ++} ++ ++static void __exit at91spi_exit(void) ++{ ++	platform_driver_unregister(&at91spi_driver); ++} ++ ++EXPORT_SYMBOL(spi_access_bus); ++EXPORT_SYMBOL(spi_release_bus); ++EXPORT_SYMBOL(spi_transfer); ++ ++module_init(at91spi_init); ++module_exit(at91spi_exit); ++ ++MODULE_LICENSE("GPL") ++MODULE_AUTHOR("Andrew Victor") ++MODULE_DESCRIPTION("SPI driver for Atmel AT91RM9200") +Index: linux-2.6.22.1/drivers/char/Kconfig +=================================================================== +--- linux-2.6.22.1/drivers/char/Kconfig	(revision 1) ++++ linux-2.6.22.1/drivers/char/Kconfig	(arbetskopia) +@@ -1083,5 +1083,21 @@ +  + source "drivers/s390/char/Kconfig" +  ++config AT91_SPI ++	bool "SPI driver (legacy) for AT91RM9200 processors" ++	depends on ARCH_AT91RM9200 ++	default y ++	help ++	  The SPI driver gives access to this serial bus on the AT91RM9200 ++	  processor. ++ ++config AT91_SPIDEV ++	bool "SPI device interface (legacy) for AT91RM9200 processors" ++	depends on ARCH_AT91RM9200 && AT91_SPI ++	default n ++	help ++	  The SPI driver gives user mode access to this serial ++	  bus on the AT91RM9200 processor. ++ + endmenu +  +Index: linux-2.6.22.1/drivers/char/at91_spidev.c +=================================================================== +--- linux-2.6.22.1/drivers/char/at91_spidev.c	(revision 0) ++++ linux-2.6.22.1/drivers/char/at91_spidev.c	(revision 0) +@@ -0,0 +1,236 @@ ++/* ++ * User-space interface to the SPI bus on Atmel AT91RM9200 ++ * ++ *  Copyright (C) 2003 SAN People (Pty) Ltd ++ * ++ * Based on SPI driver by Rick Bronson ++ * ++ * 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/module.h> ++#include <linux/init.h> ++#include <linux/slab.h> ++#include <linux/highmem.h> ++#include <linux/pagemap.h> ++#include <asm/arch/spi.h> ++ ++#ifdef CONFIG_DEVFS_FS ++#include <linux/devfs_fs_kernel.h> ++#endif ++ ++ ++#undef DEBUG_SPIDEV ++ ++/* ......................................................................... */ ++ ++/* ++ * Read or Write to SPI bus. ++ */ ++static ssize_t spidev_rd_wr(struct file *file, char *buf, size_t count, loff_t *offset) ++{ ++	unsigned int spi_device = (unsigned int) file->private_data; ++ ++	struct mm_struct * mm; ++	struct page ** maplist; ++	struct spi_transfer_list* list; ++	int    pgcount; ++ ++	unsigned int ofs, pagelen; ++	int res, i, err; ++ ++	if (!count) { ++		return 0; ++	} ++ ++	list = kmalloc(sizeof(struct spi_transfer_list), GFP_KERNEL); ++	if (!list) { ++		return -ENOMEM; ++	} ++ ++	mm = current->mm; ++ ++	pgcount = ((unsigned long)buf+count+PAGE_SIZE-1)/PAGE_SIZE - (unsigned long)buf/PAGE_SIZE; ++ ++	if (pgcount >= MAX_SPI_TRANSFERS) { ++		kfree(list); ++		return -EFBIG; ++	} ++ ++	maplist = kmalloc (pgcount * sizeof (struct page *), GFP_KERNEL); ++ ++	if (!maplist) { ++		kfree(list); ++		return -ENOMEM; ++	} ++	flush_cache_all(); ++	down_read(&mm->mmap_sem); ++	err= get_user_pages(current, mm, (unsigned long)buf, pgcount, 1, 0, maplist, NULL); ++	up_read(&mm->mmap_sem); ++ ++	if (err < 0) { ++		kfree(list); ++		kfree(maplist); ++		return err; ++	} ++	pgcount = err; ++ ++#ifdef DEBUG_SPIDEV ++	printk("spidev_rd_rw: %i %i\n", count, pgcount); ++#endif ++ ++	/* Set default return value = transfer length */ ++	res = count; ++ ++	/* ++	 * At this point, the virtual area buf[0] .. buf[count-1] will have ++	 * corresponding pages mapped in the physical memory and locked until ++	 * we unmap the kiobuf.  The pages cannot be swapped out or moved ++	 * around. ++	 */ ++	ofs = (unsigned long) buf & (PAGE_SIZE -1); ++	pagelen = PAGE_SIZE - ofs; ++	if (count < pagelen) ++		pagelen = count; ++ ++	for (i = 0; i < pgcount; i++) { ++		flush_dcache_page(maplist[i]); ++ ++		list->tx[i] = list->rx[i] = page_address(maplist[i]) + ofs; ++		list->txlen[i] = list->rxlen[i] = pagelen; ++ ++#ifdef DEBUG_SPIDEV ++		printk("  %i: %x  (%i)\n", i, list->tx[i], list->txlen[i]); ++#endif ++ ++		ofs = 0;	/* all subsequent transfers start at beginning of a page */ ++		count = count - pagelen; ++		pagelen = (count < PAGE_SIZE) ? count : PAGE_SIZE; ++	} ++	list->nr_transfers = pgcount; ++ ++	/* Perform transfer on SPI bus */ ++	spi_access_bus(spi_device); ++	spi_transfer(list); ++	spi_release_bus(spi_device); ++ ++	while (pgcount--) { ++		page_cache_release (maplist[pgcount]); ++	} ++	flush_cache_all(); ++ ++	kfree(maplist); ++	kfree(list); ++ ++	return res; ++} ++ ++static int spidev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) ++{ ++	int spi_device = MINOR(inode->i_rdev); ++ ++	if (spi_device >= NR_SPI_DEVICES) ++		return -ENODEV; ++ ++	// TODO: This interface can be used to configure the SPI bus. ++	// Configurable options could include: Speed, Clock Polarity, Clock Phase ++ ++	switch(cmd) { ++		default: ++			return -ENOIOCTLCMD; ++	} ++} ++ ++/* ++ * Open the SPI device ++ */ ++static int spidev_open(struct inode *inode, struct file *file) ++{ ++	unsigned int spi_device = MINOR(inode->i_rdev); ++ ++	if (spi_device >= NR_SPI_DEVICES) ++		return -ENODEV; ++ ++	/* ++	 * 'private_data' is actually a pointer, but we overload it with the ++	 * value we want to store. ++	 */ ++	file->private_data = (void *)spi_device; ++ ++	return 0; ++} ++ ++/* ++ * Close the SPI device ++ */ ++static int spidev_close(struct inode *inode, struct file *file) ++{ ++	return 0; ++} ++ ++/* ......................................................................... */ ++ ++static struct file_operations spidev_fops = { ++	.owner		= THIS_MODULE, ++	.llseek		= no_llseek, ++	.read		= spidev_rd_wr, ++	.write		= (int (*) (struct file *file, const char *buf, size_t count, loff_t *offset))spidev_rd_wr, ++	.ioctl		= spidev_ioctl, ++	.open		= spidev_open, ++	.release	= spidev_close, ++}; ++ ++/* ++ * Install the SPI /dev interface driver ++ */ ++static int __init at91_spidev_init(void) ++{ ++#ifdef CONFIG_DEVFS_FS ++	int i; ++#endif ++ ++	if (register_chrdev(SPI_MAJOR, "spi", &spidev_fops)) { ++		printk(KERN_ERR "at91_spidev: Unable to get major %d for SPI bus\n", SPI_MAJOR); ++		return -EIO; ++	} ++ ++#ifdef CONFIG_DEVFS_FS ++	devfs_mk_dir("spi"); ++	for (i = 0; i < NR_SPI_DEVICES; i++) { ++		devfs_mk_cdev(MKDEV(SPI_MAJOR, i), S_IFCHR | S_IRUSR | S_IWUSR, "spi/%d",i); ++	} ++#endif ++	printk(KERN_INFO "AT91 SPI driver loaded\n"); ++ ++	return 0; ++} ++ ++/* ++ * Remove the SPI /dev interface driver ++ */ ++static void __exit at91_spidev_exit(void) ++{ ++#ifdef CONFIG_DEVFS_FS ++	int i; ++	for (i = 0; i < NR_SPI_DEVICES; i++) { ++		devfs_remove("spi/%d", i); ++	} ++ ++	devfs_remove("spi"); ++#endif ++ ++	if (unregister_chrdev(SPI_MAJOR, "spi")) { ++		printk(KERN_ERR "at91_spidev: Unable to release major %d for SPI bus\n", SPI_MAJOR); ++		return; ++	} ++} ++ ++module_init(at91_spidev_init); ++module_exit(at91_spidev_exit); ++ ++MODULE_LICENSE("GPL") ++MODULE_AUTHOR("Andrew Victor") ++MODULE_DESCRIPTION("SPI /dev interface for Atmel AT91RM9200") +Index: linux-2.6.22.1/drivers/char/Makefile +=================================================================== +--- linux-2.6.22.1/drivers/char/Makefile	(revision 1) ++++ linux-2.6.22.1/drivers/char/Makefile	(arbetskopia) +@@ -93,6 +93,8 @@ + obj-$(CONFIG_GPIO_VR41XX)	+= vr41xx_giu.o + obj-$(CONFIG_GPIO_TB0219)	+= tb0219.o + obj-$(CONFIG_TELCLOCK)		+= tlclk.o ++obj-$(CONFIG_AT91_SPI)		+= at91_spi.o ++obj-$(CONFIG_AT91_SPIDEV)	+= at91_spidev.o +  + obj-$(CONFIG_WATCHDOG)		+= watchdog/ + obj-$(CONFIG_MWAVE)		+= mwave/ +Index: linux-2.6.22.1/drivers/net/macb.c +=================================================================== +--- linux-2.6.22.1/drivers/net/macb.c	(revision 1) ++++ linux-2.6.22.1/drivers/net/macb.c	(arbetskopia)  @@ -17,13 +17,14 @@   #include <linux/init.h>   #include <linux/netdevice.h> @@ -7922,7 +19849,7 @@ index 0e04f7a..c20a585 100644   #include "macb.h" -@@ -85,172 +86,202 @@ static void __init macb_get_hwaddr(struct macb *bp) +@@ -85,172 +86,202 @@   		memcpy(bp->dev->dev_addr, addr, sizeof(addr));   } @@ -7988,14 +19915,14 @@ index 0e04f7a..c20a585 100644  +			   u16 value)   {  -	struct macb *bp = netdev_priv(dev); -- ++	struct macb *bp = bus->priv; +   -	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) @@ -8244,7 +20171,7 @@ index 0e04f7a..c20a585 100644   }   static void macb_update_stats(struct macb *bp) -@@ -265,16 +296,6 @@ static void macb_update_stats(struct macb *bp) +@@ -265,16 +296,6 @@   		*p += __raw_readl(reg);   } @@ -8261,7 +20188,7 @@ index 0e04f7a..c20a585 100644   static void macb_tx(struct macb *bp)   {   	unsigned int tail; -@@ -519,9 +540,6 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) +@@ -519,9 +540,6 @@   	spin_lock(&bp->lock);   	while (status) { @@ -8271,7 +20198,7 @@ index 0e04f7a..c20a585 100644   		/* 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) +@@ -535,7 +553,8 @@   				 * until we have processed the buffers   				 */   				macb_writel(bp, IDR, MACB_RX_INT_FLAGS); @@ -8281,7 +20208,7 @@ index 0e04f7a..c20a585 100644   				__netif_rx_schedule(dev);   			}   		} -@@ -765,7 +784,7 @@ static void macb_init_hw(struct macb *bp) +@@ -765,7 +784,7 @@   	macb_writel(bp, TBQP, bp->tx_ring_dma);   	/* Enable TX and RX */ @@ -8290,7 +20217,7 @@ index 0e04f7a..c20a585 100644   	/* Enable interrupts */   	macb_writel(bp, IER, (MACB_BIT(RCOMP) -@@ -776,18 +795,126 @@ static void macb_init_hw(struct macb *bp) +@@ -776,20 +795,128 @@   			      | MACB_BIT(TCOMP)   			      | MACB_BIT(ISR_ROVR)   			      | MACB_BIT(HRESP))); @@ -8365,8 +20292,14 @@ index 0e04f7a..c20a585 100644  +	struct dev_mc_list *curr;  +	unsigned long mc_filter[2];  +	unsigned int i, bitnr; -+	struct macb *bp = netdev_priv(dev); -+ + 	struct macb *bp = netdev_priv(dev); +  +-	/* Set some reasonable default settings */ +-	macb_mdio_write(dev, bp->mii.phy_id, MII_ADVERTISE, +-			ADVERTISE_CSMA | ADVERTISE_ALL); +-	macb_mdio_write(dev, bp->mii.phy_id, MII_BMCR, +-			(BMCR_SPEED100 | BMCR_ANENABLE +-			 | BMCR_ANRESTART | BMCR_FULLDPLX));  +	mc_filter[0] = mc_filter[1] = 0;  +  +	curr = dev->mc_list; @@ -8379,22 +20312,16 @@ index 0e04f7a..c20a585 100644  +  +	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)); ++	struct macb *bp = netdev_priv(dev); ++  +	cfg = macb_readl(bp, NCFGR);  +  +	if (dev->flags & IFF_PROMISC) @@ -8421,10 +20348,12 @@ index 0e04f7a..c20a585 100644  +	}  +  +	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) + { + 	struct macb *bp = netdev_priv(dev); +@@ -797,6 +924,10 @@   	dev_dbg(&bp->pdev->dev, "open\n"); @@ -8435,23 +20364,24 @@ index 0e04f7a..c20a585 100644   	if (!is_valid_ether_addr(dev->dev_addr))   		return -EADDRNOTAVAIL; -@@ -810,12 +941,11 @@ static int macb_open(struct net_device *dev) +@@ -810,13 +941,12 @@   	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); ++ + 	netif_start_queue(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) +  +@@ -825,10 +955,11 @@   	struct macb *bp = netdev_priv(dev);   	unsigned long flags; @@ -8465,7 +20395,7 @@ index 0e04f7a..c20a585 100644   	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) +@@ -845,6 +976,9 @@   	struct net_device_stats *nstat = &bp->stats;   	struct macb_stats *hwstat = &bp->hw_stats; @@ -8475,7 +20405,7 @@ index 0e04f7a..c20a585 100644   	/* 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) +@@ -882,18 +1016,27 @@   static int macb_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)   {   	struct macb *bp = netdev_priv(dev); @@ -8506,7 +20436,7 @@ index 0e04f7a..c20a585 100644   {   	struct macb *bp = netdev_priv(dev); -@@ -902,104 +1045,34 @@ static void macb_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *inf +@@ -902,104 +1045,34 @@   	strcpy(info->bus_info, bp->pdev->dev.bus_id);   } @@ -8534,7 +20464,9 @@ index 0e04f7a..c20a585 100644  -	return generic_mii_ioctl(&bp->mii, if_mii(rq), cmd, NULL);  -} -- ++	if (!phydev) ++		return -ENODEV; +   -static ssize_t macb_mii_show(const struct device *_dev, char *buf,  -			unsigned long addr)  -{ @@ -8549,8 +20481,9 @@ index 0e04f7a..c20a585 100644  -	}  -  -	return ret; --} -- ++	return phy_mii_ioctl(phydev, if_mii(rq), cmd); + } +   -#define MII_ENTRY(name, addr)					\  -static ssize_t show_##name(struct device *_dev,			\  -			   struct device_attribute *attr,	\ @@ -8587,13 +20520,10 @@ index 0e04f7a..c20a585 100644  -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; @@ -8616,7 +20546,7 @@ index 0e04f7a..c20a585 100644   	unsigned long pclk_hz;   	u32 config;   	int err = -ENXIO; -@@ -1073,6 +1146,7 @@ static int __devinit macb_probe(struct platform_device *pdev) +@@ -1073,6 +1146,7 @@   	dev->stop = macb_close;   	dev->hard_start_xmit = macb_start_xmit;   	dev->get_stats = macb_get_stats; @@ -8624,7 +20554,7 @@ index 0e04f7a..c20a585 100644   	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) +@@ -1080,10 +1154,6 @@   	dev->base_addr = regs->start; @@ -8635,7 +20565,7 @@ index 0e04f7a..c20a585 100644   	/* 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) +@@ -1096,20 +1166,9 @@   		config = MACB_BF(CLK, MACB_CLK_DIV64);   	macb_writel(bp, NCFGR, config); @@ -8651,27 +20581,27 @@ index 0e04f7a..c20a585 100644  -		dev_err(&pdev->dev, "Failed to detect PHY, aborting.\n");  -		goto err_out_free_irq;  -	} -- - 	pdata = pdev->dev.platform_data; -+ ++	pdata = pdev->dev.platform_data; +  +-	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) +@@ -1131,18 +1190,27 @@   		goto err_out_free_irq;   	} --	platform_set_drvdata(pdev, dev);  +	if (macb_mii_init(bp) != 0) {  +		goto err_out_unregister_netdev;  +	} ++ + 	platform_set_drvdata(pdev, dev);  -	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->name, dev->base_addr, dev->irq,   	       dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],   	       dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); @@ -8687,7 +20617,7 @@ index 0e04f7a..c20a585 100644   err_out_free_irq:   	free_irq(dev->irq, dev);   err_out_iounmap: -@@ -1153,7 +1221,9 @@ err_out_disable_clocks: +@@ -1153,7 +1221,9 @@   	clk_put(bp->hclk);   #endif   	clk_disable(bp->pclk); @@ -8697,7 +20627,7 @@ index 0e04f7a..c20a585 100644   	clk_put(bp->pclk);   err_out_free_dev:   	free_netdev(dev); -@@ -1171,7 +1241,8 @@ static int __devexit macb_remove(struct platform_device *pdev) +@@ -1171,7 +1241,8 @@   	if (dev) {   		bp = netdev_priv(dev); @@ -8707,11 +20637,11 @@ index 0e04f7a..c20a585 100644   		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 { +Index: linux-2.6.22.1/drivers/net/macb.h +=================================================================== +--- linux-2.6.22.1/drivers/net/macb.h	(revision 1) ++++ linux-2.6.22.1/drivers/net/macb.h	(arbetskopia) +@@ -383,11 +383,11 @@   	unsigned int		rx_pending, tx_pending; @@ -8728,448 +20658,473 @@ index b3bb218..4e3283e 100644   };   #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. +Index: linux-2.6.22.1/drivers/net/Kconfig +=================================================================== +--- linux-2.6.22.1/drivers/net/Kconfig	(revision 1) ++++ linux-2.6.22.1/drivers/net/Kconfig	(arbetskopia) +@@ -191,7 +191,7 @@ + config MACB + 	tristate "Atmel MACB support" + 	depends on NET_ETHERNET && (AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263) +-	select MII ++	select PHYLIB + 	help + 	  The Atmel MACB ethernet interface is found on many AT32 and AT91 + 	  parts. Say Y to include support for the MACB chip. +Index: linux-2.6.22.1/drivers/net/arm/at91_ether.c +=================================================================== +--- linux-2.6.22.1/drivers/net/arm/at91_ether.c	(revision 1) ++++ linux-2.6.22.1/drivers/net/arm/at91_ether.c	(arbetskopia) +@@ -894,6 +894,7 @@ + 			skb_reserve(skb, 2); + 			memcpy(skb_put(skb, pktlen), p_recv, pktlen); +  ++			skb->dev = dev; + 			skb->protocol = eth_type_trans(skb, dev); + 			dev->last_rx = jiffies; + 			lp->stats.rx_bytes += pktlen; +@@ -978,14 +979,22 @@ + 	struct net_device *dev; + 	struct at91_private *lp; + 	unsigned int val; +-	int res; ++	struct resource *res; ++	int ret; -+config RTC_DRV_AT32AP700X -+	tristate "AT32AP700X series RTC" -+	depends on RTC_CLASS && PLATFORM_AT32AP + 	dev = alloc_etherdev(sizeof(struct at91_private)); + 	if (!dev) + 		return -ENOMEM; +  +-	dev->base_addr = AT91_VA_BASE_EMAC; +-	dev->irq = AT91RM9200_ID_EMAC; ++	/* Get I/O base address and IRQ */ ++	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++	if (!res) { ++		free_netdev(dev); ++		return -ENODEV; ++	} ++	dev->base_addr = res->start; ++	dev->irq = platform_get_irq(pdev, 0); ++ + 	SET_MODULE_OWNER(dev); +  + 	/* Install the interrupt handler */ +@@ -1058,12 +1067,12 @@ + 	lp->phy_address = phy_address;	/* MDI address of PHY */ +  + 	/* Register the network interface */ +-	res = register_netdev(dev); +-	if (res) { ++	ret = register_netdev(dev); ++	if (ret) { + 		free_irq(dev->irq, dev); + 		free_netdev(dev); + 		dma_free_coherent(NULL, sizeof(struct recv_desc_bufs), lp->dlist, (dma_addr_t)lp->dlist_phys); +-		return res; ++		return ret; + 	} +  + 	/* Determine current link speed */ +Index: linux-2.6.22.1/drivers/leds/Kconfig +=================================================================== +--- linux-2.6.22.1/drivers/leds/Kconfig	(revision 1) ++++ linux-2.6.22.1/drivers/leds/Kconfig	(arbetskopia) +@@ -77,6 +77,13 @@ + 	  This option enables support for the Soekris net4801 and net4826 error + 	  LED. +  ++config LEDS_AT91 ++	tristate "LED support using AT91 GPIOs" ++	depends on LEDS_CLASS && ARCH_AT91 && !LEDS  +	help -+	  Driver for the internal RTC (Realtime Clock) on Atmel AVR32 -+	  AT32AP700x family processors. ++	  This option enables support for LEDs connected to GPIO lines ++	  on AT91-based boards.  + - 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 @@ + config LEDS_WRAP + 	tristate "LED Support for the WRAP series LEDs" + 	depends on LEDS_CLASS && SCx200_GPIO +@@ -95,6 +102,14 @@ + 	help + 	  This option enables support for the front LED on Cobalt Server +  ++config LEDS_GPIO ++	tristate "LED Support for GPIO connected LEDs" ++	depends on LEDS_CLASS && GENERIC_GPIO ++	help ++	  This option enables support for the LEDs connected to GPIO ++	  outputs. To be useful the particular board must have LEDs ++	  and they must be connected to the GPIO lines. ++ + comment "LED Triggers" +  + config LEDS_TRIGGERS +Index: linux-2.6.22.1/drivers/leds/leds-at91.c +=================================================================== +--- linux-2.6.22.1/drivers/leds/leds-at91.c	(revision 0) ++++ linux-2.6.22.1/drivers/leds/leds-at91.c	(revision 0) +@@ -0,0 +1,140 @@  +/* -+ * An RTC driver for the AVR32 AT32AP700x processor series. ++ * AT91 GPIO based LED driver  + * -+ * Copyright (C) 2007 Atmel Corporation ++ * Copyright (C) 2006 David Brownell  + * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. ++ * This 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/init.h>  +#include <linux/platform_device.h> -+#include <linux/rtc.h> -+#include <linux/io.h> ++#include <linux/leds.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. -+ */ ++#include <asm/arch/board.h> ++#include <asm/arch/gpio.h>  + -+#define RTC_CTRL		0x00 -+#define RTC_CTRL_EN		   0 -+#define RTC_CTRL_PCLR		   1 -+#define RTC_CTRL_TOPEN		   2 -+#define RTC_CTRL_PSEL		   8 ++static LIST_HEAD(at91_led_list);	/* list of AT91 LEDs */  + -+#define RTC_VAL			0x04 ++struct at91_led { ++	struct led_classdev	cdev; ++	struct list_head	list; ++	struct at91_gpio_led	*led_data; ++};  + -+#define RTC_TOP			0x08 ++/* ++ * Change the state of the LED. ++ */ ++static void at91_led_set(struct led_classdev *cdev, enum led_brightness value) ++{ ++	struct at91_led	*led = container_of(cdev, struct at91_led, cdev); ++	short		active = (value == LED_OFF);  + -+#define RTC_IER			0x10 -+#define RTC_IER_TOPI		   0 ++	if (led->led_data->flags & 1)	/* active high/low? */ ++		active = !active; ++	at91_set_gpio_value(led->led_data->gpio, active); ++}  + -+#define RTC_IDR			0x14 -+#define RTC_IDR_TOPI		   0 ++static int __devexit at91_led_remove(struct platform_device *pdev) ++{ ++	struct at91_led		*led;  + -+#define RTC_IMR			0x18 -+#define RTC_IMR_TOPI		   0 ++	list_for_each_entry (led, &at91_led_list, list) ++		led_classdev_unregister(&led->cdev);  + -+#define RTC_ISR			0x1c -+#define RTC_ISR_TOPI		   0 ++#warning "Free allocated memory" ++	// TODO: Free memory.	kfree(led);  + -+#define RTC_ICR			0x20 -+#define RTC_ICR_TOPI		   0 ++	return 0; ++}  + -+#define RTC_BIT(name)		(1 << RTC_##name) -+#define RTC_BF(name, value)	((value) << RTC_##name) ++static int __init at91_led_probe(struct platform_device *pdev) ++{ ++	int			status = 0; ++	struct at91_gpio_led	*pdata = pdev->dev.platform_data; ++	unsigned		nr_leds; ++	struct at91_led		*led;  + -+#define rtc_readl(dev, reg)				\ -+	__raw_readl((dev)->regs + RTC_##reg) -+#define rtc_writel(dev, reg, value)			\ -+	__raw_writel((value), (dev)->regs + RTC_##reg) ++	if (!pdata) ++		return -ENODEV;  + -+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; -+}; ++	nr_leds = pdata->index;		/* first index stores number of LEDs */  + -+static int at32_rtc_readtime(struct device *dev, struct rtc_time *tm) ++	while (nr_leds--) { ++		led = kzalloc(sizeof(struct at91_led), GFP_KERNEL); ++		if (!led) { ++			dev_err(&pdev->dev, "No memory for device\n"); ++			status = -ENOMEM; ++			goto cleanup; ++		} ++		led->led_data = pdata; ++		led->cdev.name = pdata->name; ++		led->cdev.brightness_set = at91_led_set, ++		led->cdev.default_trigger = pdata->trigger; ++ ++		status = led_classdev_register(&pdev->dev, &led->cdev); ++		if (status < 0) { ++			dev_err(&pdev->dev, "led_classdev_register failed - %d\n", status); ++cleanup: ++			at91_led_remove(pdev); ++			break; ++		} ++		list_add(&led->list, &at91_led_list); ++		pdata++; ++	} ++	return status; ++} ++ ++#ifdef CONFIG_PM ++static int at91_led_suspend(struct platform_device *dev, pm_message_t state)  +{ -+	struct rtc_at32ap700x *rtc = dev_get_drvdata(dev); -+	unsigned long now; ++	struct at91_led	*led;  + -+	now = rtc_readl(rtc, VAL); -+	rtc_time_to_tm(now, tm); ++	list_for_each_entry (led, &at91_led_list, list) ++		led_classdev_suspend(&led->cdev);  +  +	return 0;  +}  + -+static int at32_rtc_settime(struct device *dev, struct rtc_time *tm) ++static int at91_led_resume(struct platform_device *dev)  +{ -+	struct rtc_at32ap700x *rtc = dev_get_drvdata(dev); -+	unsigned long now; -+	int ret; ++	struct at91_led	*led;  + -+	ret = rtc_tm_to_time(tm, &now); -+	if (ret == 0) -+		rtc_writel(rtc, VAL, now); ++	list_for_each_entry (led, &at91_led_list, list) ++		led_classdev_resume(&led->cdev);  + -+	return ret; ++	return 0;  +} ++#else ++#define	at91_led_suspend	NULL ++#define	at91_led_resume		NULL ++#endif  + -+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; ++static struct platform_driver at91_led_driver = { ++	.probe		= at91_led_probe, ++	.remove		= __devexit_p(at91_led_remove), ++	.suspend	= at91_led_suspend, ++	.resume		= at91_led_resume, ++	.driver		= { ++		.name	= "at91_leds", ++		.owner	= THIS_MODULE, ++	}, ++};  + -+	return 0; ++static int __init at91_led_init(void) ++{ ++	return platform_driver_register(&at91_led_driver);  +} ++module_init(at91_led_init);  + -+static int at32_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) ++static void __exit at91_led_exit(void)  +{ -+	struct rtc_at32ap700x *rtc = dev_get_drvdata(dev); -+	unsigned long rtc_unix_time; -+	unsigned long alarm_unix_time; -+	int ret; ++	platform_driver_unregister(&at91_led_driver); ++} ++module_exit(at91_led_exit);  + -+	rtc_unix_time = rtc_readl(rtc, VAL); ++MODULE_DESCRIPTION("AT91 GPIO LED driver"); ++MODULE_AUTHOR("David Brownell"); ++MODULE_LICENSE("GPL"); +Index: linux-2.6.22.1/drivers/leds/leds-gpio.c +=================================================================== +--- linux-2.6.22.1/drivers/leds/leds-gpio.c	(revision 0) ++++ linux-2.6.22.1/drivers/leds/leds-gpio.c	(revision 0) +@@ -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>  + -+	ret = rtc_tm_to_time(&alrm->time, &alarm_unix_time); -+	if (ret) -+		return ret; ++#include <asm/gpio.h>  + -+	if (alarm_unix_time < rtc_unix_time) -+		return -EINVAL; ++struct gpio_led_data { ++	struct led_classdev cdev; ++	unsigned gpio; ++	struct work_struct work; ++	u8 new_level; ++	u8 can_sleep; ++	u8 active_low; ++};  + -+	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); ++static void gpio_led_work(struct work_struct *work) ++{ ++	struct gpio_led_data	*led_dat = ++		container_of(work, struct gpio_led_data, work);  + -+	return ret; ++	gpio_set_value_cansleep(led_dat->gpio, led_dat->new_level);  +}  + -+static int at32_rtc_ioctl(struct device *dev, unsigned int cmd, -+			unsigned long arg) ++static void gpio_led_set(struct led_classdev *led_cdev, ++	enum led_brightness value)  +{ -+	struct rtc_at32ap700x *rtc = dev_get_drvdata(dev); -+	int ret = 0; -+ -+	spin_lock_irq(&rtc->lock); ++	struct gpio_led_data *led_dat = ++		container_of(led_cdev, struct gpio_led_data, cdev); ++	int level;  + -+	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; -+	} ++	if (value == LED_OFF) ++		level = 0; ++	else ++		level = 1;  + -+	spin_unlock_irq(&rtc->lock); ++	if (led_dat->active_low) ++		level = !level;  + -+	return ret; ++	/* 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 irqreturn_t at32_rtc_interrupt(int irq, void *dev_id) ++static int __init gpio_led_probe(struct platform_device *pdev)  +{ -+	struct rtc_at32ap700x *rtc = (struct rtc_at32ap700x *)dev_id; -+	unsigned long isr = rtc_readl(rtc, ISR); -+	unsigned long events = 0; -+	int ret = IRQ_NONE; ++	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;  + -+	spin_lock(&rtc->lock); ++	if (!pdata) ++		return -EBUSY;  + -+	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; -+	} ++	leds_data = kzalloc(sizeof(struct gpio_led_data) * pdata->num_leds, ++				GFP_KERNEL); ++	if (!leds_data) ++		return -ENOMEM;  + -+	spin_unlock(&rtc->lock); ++	for (i = 0; i < pdata->num_leds; i++) { ++		cur_led = &pdata->leds[i]; ++		led_dat = &leds_data[i];  + -+	return ret; -+} ++		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;  + -+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, -+}; ++		ret = gpio_request(led_dat->gpio, led_dat->cdev.name); ++		if (ret < 0) ++			goto err;  + -+static int __init at32_rtc_probe(struct platform_device *pdev) -+{ -+	struct resource	*regs; -+	struct rtc_at32ap700x *rtc; -+	int irq = -1; -+	int ret; ++		gpio_direction_output(led_dat->gpio, led_dat->active_low);  + -+	rtc = kzalloc(sizeof(struct rtc_at32ap700x), GFP_KERNEL); -+	if (!rtc) { -+		dev_dbg(&pdev->dev, "out of memory\n"); -+		return -ENOMEM; -+	} ++		ret = led_classdev_register(&pdev->dev, &led_dat->cdev); ++		if (ret < 0) { ++			gpio_free(led_dat->gpio); ++			goto err; ++		}  + -+	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+	if (!regs) { -+		dev_dbg(&pdev->dev, "no mmio resource defined\n"); -+		ret = -ENXIO; -+		goto out; ++		INIT_WORK(&led_dat->work, gpio_led_work);  +	}  + -+	irq = platform_get_irq(pdev, 0); -+	if (irq < 0) { -+		dev_dbg(&pdev->dev, "could not get irq\n"); -+		ret = -ENXIO; -+		goto out; -+	} ++	platform_set_drvdata(pdev, leds_data);  + -+	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; -+	} ++	return 0;  + -+	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; ++err: ++	if (i > 0) { ++		for (i = i - 1; i >= 0; i--) { ++			led_classdev_unregister(&leds_data[i].cdev); ++			gpio_free(leds_data[i].gpio); ++		}  +	} -+	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)); -+	} ++	flush_scheduled_work(); ++	kfree(leds_data);  + -+	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; -+	} ++	return ret; ++}  + -+	platform_set_drvdata(pdev, rtc); ++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;  + -+	dev_info(&pdev->dev, "Atmel RTC for AT32AP700x at %08lx irq %ld\n", -+			(unsigned long)rtc->regs, rtc->irq); ++	leds_data = platform_get_drvdata(pdev);  + -+	return 0; ++	for (i = 0; i < pdata->num_leds; i++) { ++		led_classdev_unregister(&leds_data[i].cdev); ++		gpio_free(leds_data[i].gpio); ++	} ++	 ++	kfree(leds_data);  + -+out_iounmap: -+	iounmap(rtc->regs); -+out_free_irq: -+	free_irq(irq, rtc); -+out: -+	kfree(rtc); -+	return ret; ++	return 0;  +}  + -+static int __exit at32_rtc_remove(struct platform_device *pdev) ++#ifdef CONFIG_PM ++static int gpio_led_suspend(struct platform_device *pdev, pm_message_t state)  +{ -+	struct rtc_at32ap700x *rtc = platform_get_drvdata(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);  + -+	free_irq(rtc->irq, rtc); -+	iounmap(rtc->regs); -+	rtc_device_unregister(rtc->rtc); -+	kfree(rtc); -+	platform_set_drvdata(pdev, NULL); ++	for (i = 0; i < pdata->num_leds; i++) ++		led_classdev_suspend(&leds_data[i].cdev);  +  +	return 0;  +}  + -+MODULE_ALIAS("at32ap700x_rtc"); ++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;  + -+static struct platform_driver at32_rtc_driver = { -+	.remove		= __exit_p(at32_rtc_remove), ++	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	= "at32ap700x_rtc", ++		.name	= "leds-gpio",  +		.owner	= THIS_MODULE,  +	},  +};  + -+static int __init at32_rtc_init(void) ++static int __init gpio_led_init(void)  +{ -+	return platform_driver_probe(&at32_rtc_driver, at32_rtc_probe); ++	return platform_driver_probe(&gpio_led_driver, gpio_led_probe);  +} -+module_init(at32_rtc_init);  + -+static void __exit at32_rtc_exit(void) ++static void __exit gpio_led_exit(void)  +{ -+	platform_driver_unregister(&at32_rtc_driver); ++	platform_driver_unregister(&gpio_led_driver);  +} -+module_exit(at32_rtc_exit);  + -+MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>"); -+MODULE_DESCRIPTION("Real time clock for AVR32 AT32AP700x"); ++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/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); +Index: linux-2.6.22.1/drivers/leds/Makefile +=================================================================== +--- linux-2.6.22.1/drivers/leds/Makefile	(revision 1) ++++ linux-2.6.22.1/drivers/leds/Makefile	(arbetskopia) +@@ -16,6 +16,8 @@ + 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 ++obj-$(CONFIG_LEDS_AT91)			+= leds-at91.o - 	/* 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 + # LED Triggers + obj-$(CONFIG_LEDS_TRIGGER_TIMER)	+= ledtrig-timer.o +Index: linux-2.6.22.1/drivers/usb/gadget/Kconfig +=================================================================== +--- linux-2.6.22.1/drivers/usb/gadget/Kconfig	(revision 1) ++++ linux-2.6.22.1/drivers/usb/gadget/Kconfig	(arbetskopia) +@@ -175,7 +175,20 @@   	default USB_GADGET   	select USB_GADGET_SELECTED @@ -9180,32 +21135,20 @@ index f771a7c..0c3d55b 100644  +	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 + 	depends on ARCH_OMAP +Index: linux-2.6.22.1/drivers/usb/gadget/atmel_usba_udc.c +=================================================================== +--- linux-2.6.22.1/drivers/usb/gadget/atmel_usba_udc.c	(revision 0) ++++ linux-2.6.22.1/drivers/usb/gadget/atmel_usba_udc.c	(revision 0)  @@ -0,0 +1,2072 @@  +/*  + * Driver for the Atmel USBA high speed USB device controller @@ -11279,11 +23222,36 @@ index 0000000..34dbae3  +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 +Index: linux-2.6.22.1/drivers/usb/gadget/ether.c +=================================================================== +--- linux-2.6.22.1/drivers/usb/gadget/ether.c	(revision 1) ++++ linux-2.6.22.1/drivers/usb/gadget/ether.c	(arbetskopia) +@@ -277,7 +277,7 @@ + #define DEV_CONFIG_CDC + #endif +  +-#ifdef CONFIG_USB_GADGET_HUSB2DEV ++#ifdef CONFIG_USB_GADGET_ATMEL_USBA + #define DEV_CONFIG_CDC + #endif +  +Index: linux-2.6.22.1/drivers/usb/gadget/at91_udc.c +=================================================================== +--- linux-2.6.22.1/drivers/usb/gadget/at91_udc.c	(revision 1) ++++ linux-2.6.22.1/drivers/usb/gadget/at91_udc.c	(arbetskopia) +@@ -1803,7 +1803,7 @@ + 	 */ + 	if ((!udc->suspended && udc->addr) + 			|| !wake +-			|| at91_suspend_entering_slow_clock()) { ++			|| clk_must_disable(udc->fclk)) { + 		pullup(udc, 0); + 		wake = 0; + 	} else +Index: linux-2.6.22.1/drivers/usb/gadget/atmel_usba_udc.h +=================================================================== +--- linux-2.6.22.1/drivers/usb/gadget/atmel_usba_udc.h	(revision 0) ++++ linux-2.6.22.1/drivers/usb/gadget/atmel_usba_udc.h	(revision 0)  @@ -0,0 +1,402 @@  +/*  + * Driver for the Atmel USBA high speed USB device controller @@ -11687,23 +23655,10 @@ index 0000000..408d2ce  +#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 +Index: linux-2.6.22.1/drivers/usb/gadget/gadget_chips.h +=================================================================== +--- linux-2.6.22.1/drivers/usb/gadget/gadget_chips.h	(revision 1) ++++ linux-2.6.22.1/drivers/usb/gadget/gadget_chips.h	(arbetskopia)  @@ -75,10 +75,10 @@   #define	gadget_is_pxa27x(g)	0   #endif @@ -11718,7 +23673,7 @@ index d041b91..96e4dbc 100644   #endif   #ifdef CONFIG_USB_GADGET_S3C2410 -@@ -181,7 +181,7 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget) +@@ -181,7 +181,7 @@   		return 0x16;   	else if (gadget_is_mpc8272(gadget))   		return 0x17; @@ -11727,10 +23682,22 @@ index d041b91..96e4dbc 100644   		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 +Index: linux-2.6.22.1/drivers/usb/gadget/Makefile +=================================================================== +--- linux-2.6.22.1/drivers/usb/gadget/Makefile	(revision 1) ++++ linux-2.6.22.1/drivers/usb/gadget/Makefile	(arbetskopia) +@@ -8,6 +8,7 @@ + obj-$(CONFIG_USB_OMAP)		+= omap_udc.o + obj-$(CONFIG_USB_LH7A40X)	+= lh7a40x_udc.o + obj-$(CONFIG_USB_AT91)		+= at91_udc.o ++obj-$(CONFIG_USB_ATMEL_USBA)	+= atmel_usba_udc.o + obj-$(CONFIG_USB_FSL_USB2)	+= fsl_usb2_udc.o +  + # +Index: linux-2.6.22.1/drivers/usb/gadget/inode.c +=================================================================== +--- linux-2.6.22.1/drivers/usb/gadget/inode.c	(revision 1) ++++ linux-2.6.22.1/drivers/usb/gadget/inode.c	(arbetskopia)  @@ -37,7 +37,7 @@   #include <linux/device.h>   #include <linux/moduleparam.h> @@ -11740,3081 +23707,869 @@ index 46d0e52..855f8cc 100644   #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; -+ +Index: linux-2.6.22.1/drivers/usb/host/ohci-at91.c +=================================================================== +--- linux-2.6.22.1/drivers/usb/host/ohci-at91.c	(revision 1) ++++ linux-2.6.22.1/drivers/usb/host/ohci-at91.c	(arbetskopia) +@@ -299,7 +299,7 @@ + 	 * + 	 * REVISIT: some boards will be able to turn VBUS off... + 	 */ +-	if (at91_suspend_entering_slow_clock()) { ++	if (clk_must_disable(fclk)) { + 		ohci_usb_reset (ohci); + 		at91_stop_clock();   	} +Index: linux-2.6.22.1/drivers/i2c/busses/Kconfig +=================================================================== +--- linux-2.6.22.1/drivers/i2c/busses/Kconfig	(revision 1) ++++ linux-2.6.22.1/drivers/i2c/busses/Kconfig	(arbetskopia) +@@ -4,6 +4,26 @@ - 	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. + menu "I2C Hardware Bus support" --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 ++config I2C_ATMELTWI ++	tristate "Atmel TWI/I2C" ++	depends on I2C  +	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. ++	  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  + -+	  The LTV350QV panel is present on all ATSTK1000 boards. ++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.  + -+# -+# 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 + config I2C_ALI1535 + 	tristate "ALI 1535" + 	depends on PCI +@@ -80,6 +100,14 @@ + 	  This supports the use of the I2C interface on Atmel AT91 + 	  processors. - obj-$(CONFIG_LCD_CLASS_DEVICE)     += lcd.o -+obj-$(CONFIG_LCD_LTV350QV)	+= ltv350qv.o ++config I2C_AT91_CLOCKRATE ++	prompt "Atmel AT91 I2C/TWI clock-rate" ++	depends on I2C_AT91 ++	int ++	default 100000 ++	help ++	  Set the AT91 I2C/TWI clock-rate.  + - 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 @@ + config I2C_AU1550 + 	tristate "Au1550/Au1200 SMBus interface" + 	depends on SOC_AU1550 || SOC_AU1200 +@@ -598,6 +626,14 @@ + 	  This driver can also be built as a module.  If so, the module + 	  will be called i2c-voodoo3. +  ++config I2C_PCA ++	tristate "PCA9564" ++	depends on I2C ++	select I2C_ALGOPCA ++	help ++	  This driver support the Philips PCA 9564 Parallel bus to I2C ++	  bus controller. ++ + config I2C_PCA_ISA + 	tristate "PCA9564 on an ISA bus" + 	depends on ISA +Index: linux-2.6.22.1/drivers/i2c/busses/i2c-atmeltwi.c +=================================================================== +--- linux-2.6.22.1/drivers/i2c/busses/i2c-atmeltwi.c	(revision 0) ++++ linux-2.6.22.1/drivers/i2c/busses/i2c-atmeltwi.c	(revision 0) +@@ -0,0 +1,383 @@  +/* -+ * Power control for Samsung LTV350QV Quarter VGA LCD Panel ++ * i2c Support for Atmel's Two-Wire Interface (TWI)  + * -+ * Copyright (C) 2006, 2007 Atmel Corporation ++ * Based on the work of Copyright (C) 2004 Rick Bronson ++ * Converted to 2.6 by Andrew Victor <andrew at sanpeople.com> ++ * Ported to AVR32 and heavily modified by Espen Krangnes ++ * <ekrangnes at atmel.com> ++ * ++ * Copyright (C) 2006 Atmel Corporation ++ * ++ * Borrowed heavily from the original work by: ++ * Copyright (C) 2000 Philip Edelbrock <phil at stimpy.netroedge.com> ++ * ++ * 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 version 2 as -+ * published by the Free Software Foundation. ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version.  + */ -+#include <linux/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 <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"  + -+#include "ltv350qv.h" ++static unsigned int baudrate = CONFIG_I2C_ATMELTWI_BAUDRATE; ++module_param(baudrate, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); ++MODULE_PARM_DESC(baudrate, "The TWI baudrate");  + -+#define POWER_IS_ON(pwr)	((pwr) <= FB_BLANK_NORMAL)  + -+struct ltv350qv { -+	struct spi_device	*spi; -+	u8			*buffer; -+	int			power; -+	struct lcd_device	*ld; ++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)  +  +/* -+ * 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. ++ * Initialize the TWI hardware registers.  + */ -+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) ++static int __devinit twi_hwinit(struct atmel_twi *twi)  +{ -+	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); ++	unsigned long cdiv, ckdiv=0;  + -+	/* 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; ++	twi_writel(twi, IDR, ~0UL); ++	twi_writel(twi, CR, TWI_BIT(SWRST));	/*Reset peripheral*/ ++	twi_readl(twi, SR);  + -+	/* Wait more than 2 frames */ -+	msleep(20); ++	cdiv = (clk_get_rate(twi->pclk) / (2 * baudrate)) - 4;  + -+	/* 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; ++	while (cdiv > 255) { ++		ckdiv++; ++		cdiv = cdiv >> 1; ++	}  + -+	/* Display should now be ON. Phew. */ ++	if (ckdiv > 7) ++		return -EINVAL; ++	else ++		twi_writel(twi, CWGR, (TWI_BF(CKDIV, ckdiv) ++			       | TWI_BF(CHDIV, cdiv) ++			       | TWI_BF(CLDIV, cdiv)));  +	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) ++/* ++ * 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 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)); ++	int timeout = msecs_to_jiffies(100);  + -+	/* Power down setting 1 */ -+	ret |= ltv350qv_write_reg(lcd, LTV_PWRCTL2, 0x0000); ++	twi->intmask = mask; ++	init_completion(&twi->comp);  + -+	/* Wait at least 1 ms */ -+	msleep(1); ++	twi_writel(twi, IER, mask);  + -+	/* Power down setting 2 */ -+	ret |= ltv350qv_write_reg(lcd, LTV_PWRCTL1, LTV_VCOM_DISABLE); ++	if (!wait_for_completion_timeout(&twi->comp, timeout)) { ++		/* RESET TWI interface */ ++		twi_writel(twi, CR, TWI_BIT(SWRST));  + -+	/* -+	 * 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; ++		/* Reinitialize TWI */ ++		twi_hwinit(twi);  + -+	/* Display power should now be OFF */ ++		return -ETIMEDOUT; ++	}  +	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) ++/* ++ * Generic i2c master transfer entrypoint. ++ */ ++static int twi_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)  +{ -+	struct ltv350qv *lcd; -+ -+	lcd = class_get_devdata(&ld->class_dev); -+	return ltv350qv_power(lcd, power); -+} ++	struct atmel_twi *twi = to_atmel_twi(adap); ++	struct i2c_msg *pmsg; ++	int i;  + -+static int ltv350qv_get_power(struct lcd_device *ld) -+{ -+	struct ltv350qv *lcd; ++	/* get first message */ ++	pmsg = msgs;  + -+	lcd = class_get_devdata(&ld->class_dev); -+	return lcd->power; -+} ++	dev_dbg(&adap->dev, "twi_xfer: processing %d messages:\n", num);  + -+static struct lcd_ops ltv_ops = { -+	.get_power	= ltv350qv_get_power, -+	.set_power	= ltv350qv_set_power, -+}; ++	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));  + -+static int __devinit ltv350qv_probe(struct spi_device *spi) -+{ -+	struct ltv350qv *lcd; -+	struct lcd_device *ld; -+	int ret; ++		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);  + -+	lcd = kzalloc(sizeof(struct ltv350qv), GFP_KERNEL); -+	if (!lcd) -+		return -ENOMEM; ++		/* enable */ ++		twi_writel(twi, CR, TWI_BIT(MSEN));  + -+	lcd->spi = spi; -+	lcd->power = FB_BLANK_POWERDOWN; -+	lcd->buffer = kzalloc(8, GFP_KERNEL); ++		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));  + -+	ld = lcd_device_register("ltv350qv", lcd, <v_ops); -+	if (IS_ERR(ld)) { -+		ret = PTR_ERR(ld); -+		goto out_free_lcd; -+	} -+	lcd->ld = ld; ++			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; ++			}  + -+	ret = ltv350qv_power(lcd, FB_BLANK_UNBLANK); -+	if (ret) -+		goto out_unregister; ++			if (twi->nack) ++			    return -ENODEV; ++		}  + -+	dev_set_drvdata(&spi->dev, lcd); ++		/* Disable TWI interface */ ++		twi_writel(twi, CR, TWI_BIT(MSDIS));  + -+	return 0; ++	} /* end cur msg */  + -+out_unregister: -+	lcd_device_unregister(ld); -+out_free_lcd: -+	kfree(lcd); -+	return ret; ++	return i;  +}  + -+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); ++static irqreturn_t twi_interrupt(int irq, void *dev_id) ++{ ++	struct atmel_twi *twi = dev_id; ++	int status = twi_readl(twi, SR);  + -+	return 0; -+} ++	/* Save state for later debug prints */ ++	int old_mask = twi->intmask; ++	int old_status = status;  + -+#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 (twi->intmask & status) { ++		if (status & TWI_BIT(NACK)) ++			goto nack;  + -+	if (level == SUSPEND_POWER_DOWN) -+		return ltv350qv_power(lcd, FB_BLANK_POWERDOWN); ++		status &= twi->intmask;  + -+	return 0; -+} ++		if (status & TWI_BIT(TXCOMP)) ++		    goto complete;  + -+static int ltv350qv_resume(struct spi_device *spi, u32 level) -+{ -+	struct ltv350qv *lcd = dev_get_drvdata(&spi->dev); ++		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 (level == RESUME_POWER_ON) -+		return ltv350qv_power(lcd, FB_BLANK_UNBLANK); ++			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]); ++		} ++	}  + -+	return 0; -+} -+#else -+#define ltv350qv_suspend	NULL -+#define ltv350qv_resume		NULL -+#endif ++	dev_dbg(&twi->adapter.dev, ++		"TWI ISR, SR 0x%08X, intmask 0x%08X, acks_left %i.\n", ++		old_status, old_mask, twi->acks_left);  + -+/* 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); ++	return IRQ_HANDLED;  + -+	ltv350qv_power(lcd, FB_BLANK_POWERDOWN); -+} ++nack: ++	dev_dbg(&twi->adapter.dev, "NACK received!\n"); ++	twi->nack = 1;  + -+static struct spi_driver ltv350qv_driver = { -+	.driver = { -+		.name		= "ltv350qv", -+		.bus		= &spi_bus_type, -+		.owner		= THIS_MODULE, -+	}, ++complete: ++	twi_writel(twi, IDR, ~0UL); ++	complete(&twi->comp);  + -+	.probe		= ltv350qv_probe, -+	.remove		= __devexit_p(ltv350qv_remove), -+	.shutdown	= ltv350qv_shutdown, -+	.suspend	= ltv350qv_suspend, -+	.resume		= ltv350qv_resume, -+}; ++	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);  + -+static int __init ltv350qv_init(void) -+{ -+	return spi_register_driver(<v350qv_driver); ++	return IRQ_HANDLED;  +}  + -+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. ++ * Return list of supported functionality.  + */ -+#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); ++static u32 twi_func(struct i2c_adapter *adapter) ++{ ++	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; ++}  + -+struct usba_platform_data { -+	int vbus_pin; ++/* For now, we only handle combined mode (smbus) */ ++static struct i2c_algorithm twi_algorithm = { ++	.master_xfer	= twi_xfer, ++	.functionality	= twi_func,  +}; -+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. ++ * Main initialization routine.  + */ -+#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); -+}; ++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;  + -+struct dma_request_sg { -+	struct dma_request req; ++	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++	if (!regs) ++		return -ENXIO;  + -+	int nr_sg; -+	struct scatterlist *sg; -+	unsigned long block_size; -+	unsigned int nr_blocks; ++	pclk = clk_get(&pdev->dev, "pclk"); ++	if (IS_ERR(pclk)) ++		return PTR_ERR(pclk); ++	clk_enable(pclk);  + -+	dma_addr_t data_reg; -+	unsigned short periph_id; ++	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; ++	}  + -+	unsigned char direction; -+	unsigned char width; -+}; -+#define to_dma_request_sg(_req)				\ -+	container_of(_req, struct dma_request_sg, req) ++	twi->pclk = pclk; ++	twi->regs = ioremap(regs->start, regs->end - regs->start + 1); ++	if (!twi->regs) ++		goto err_ioremap;  + -+struct dma_request_cyclic { -+	struct dma_request req; ++	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;  + -+        int periods; -+	unsigned long buffer_size; ++	rc = twi_hwinit(twi); ++	if (rc) { ++		dev_err(&pdev->dev, "Unable to set baudrate\n"); ++		goto err_hw_init; ++	}  + -+        dma_addr_t buffer_start; -+	dma_addr_t data_reg; ++	adapter = &twi->adapter; ++	sprintf(adapter->name, "TWI"); ++	adapter->algo = &twi_algorithm; ++	adapter->class = I2C_CLASS_HWMON; ++	adapter->dev.parent = &pdev->dev;  + -+	unsigned short periph_id; -+	unsigned char direction; -+	unsigned char width; ++	platform_set_drvdata(pdev, twi);  + -+        void *dev_id; -+}; -+#define to_dma_request_cyclic(_req)				\ -+	container_of(_req, struct dma_request_cyclic, req) ++	rc = i2c_add_adapter(adapter); ++	if (rc) { ++		dev_err(&pdev->dev, "Adapter %s registration failed\n", ++			adapter->name); ++		goto err_register; ++	}  + -+struct dma_request_memcpy { -+	struct dma_request req; ++	dev_info(&pdev->dev, "Atmel TWI i2c bus device (baudrate %dk) at 0x%08lx.\n", ++		 baudrate/1000, (unsigned long)regs->start);  + -+	dma_addr_t src_addr; -+	unsigned int src_width; -+	unsigned int src_stride; ++	return 0;  + -+	dma_addr_t dst_addr; -+	unsigned int dst_width; -+	unsigned int dst_stride;  + -+	size_t length; ++err_register: ++	platform_set_drvdata(pdev, NULL);  + -+	unsigned short src_reverse:1; -+	unsigned short dst_reverse:1; -+}; -+#define to_dma_request_memcpy(_req)				\ -+	container_of(_req, struct dma_request_memcpy, req) ++err_hw_init: ++	free_irq(irq, twi);  + -+struct dma_controller { -+	struct list_head list; -+	int id; -+	struct device *dev; ++err_irq: ++	iounmap(twi->regs);  + -+	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); -+}; ++err_ioremap: ++	kfree(twi);  + -+static inline int -+dma_alloc_channel(struct dma_controller *dmac) -+{ -+	return dmac->alloc_channel(dmac); -+} ++err_alloc_twi: ++	clk_disable(pclk); ++	clk_put(pclk);  + -+static inline void -+dma_release_channel(struct dma_controller *dmac, int chan) -+{ -+	dmac->release_channel(dmac, chan); ++	return rc;  +}  + -+static inline int -+dma_prepare_request_sg(struct dma_controller *dmac, -+		       struct dma_request_sg *req) ++static int __devexit twi_remove(struct platform_device *pdev)  +{ -+	return dmac->prepare_request_sg(dmac, req); -+} ++	struct atmel_twi *twi = platform_get_drvdata(pdev); ++	int res;  + -+static inline int -+dma_prepare_request_cyclic(struct dma_controller *dmac, -+			   struct dma_request_cyclic *req) -+{ -+	return dmac->prepare_request_cyclic(dmac, req); -+} ++	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);  + -+static inline int -+dma_prepare_request_memcpy(struct dma_controller *dmac, -+			   struct dma_request_memcpy *req) -+{ -+	return dmac->prepare_request_memcpy(dmac, req); ++	return res;  +}  + -+static inline int -+dma_start_request(struct dma_controller *dmac, -+		  unsigned int channel) -+{ -+	return dmac->start_request(dmac, channel); -+} ++static struct platform_driver twi_driver = { ++	.probe		= twi_probe, ++	.remove		= __devexit_p(twi_remove), ++	.driver		= { ++		.name	= "atmel_twi", ++		.owner	= THIS_MODULE, ++	}, ++};  + -+static inline int -+dma_stop_request(struct dma_controller *dmac, -+                 unsigned int channel) ++static int __init atmel_twi_init(void)  +{ -+	return dmac->stop_request(dmac, channel); ++	return platform_driver_register(&twi_driver);  +}  + -+static inline dma_addr_t -+dma_get_current_pos(struct dma_controller *dmac, -+                    unsigned int channel) ++static void __exit atmel_twi_exit(void)  +{ -+	return dmac->get_current_pos(dmac, channel); ++	platform_driver_unregister(&twi_driver);  +}  + -+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 ++module_init(atmel_twi_init); ++module_exit(atmel_twi_exit);  + -+/* 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 ++MODULE_AUTHOR("Espen Krangnes"); ++MODULE_DESCRIPTION("I2C driver for Atmel TWI"); ++MODULE_LICENSE("GPL"); +Index: linux-2.6.22.1/drivers/i2c/busses/atmeltwi.h +=================================================================== +--- linux-2.6.22.1/drivers/i2c/busses/atmeltwi.h	(revision 0) ++++ linux-2.6.22.1/drivers/i2c/busses/atmeltwi.h	(revision 0) +@@ -0,0 +1,117 @@ ++/* ++ * Register definitions for the Atmel Two-Wire Interface ++ */  + -+/* 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 ++#ifndef __ASM_AVR32_TWI_H__ ++#define __ASM_AVR32_TWI_H__  + -+/* SSC PDC Receive Pointer Register */ -+#define SSC_PDC_RPR			0x00000100 ++/* 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  + -+/* SSC PDC Receive Counter Register */ -+#define SSC_PDC_RCR			0x00000104 ++/* 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  + -+/* SSC PDC Transmit Pointer Register */ -+#define SSC_PDC_TPR			0x00000108 ++/* 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  + -+/* SSC PDC Receive Next Pointer Register */ -+#define SSC_PDC_RNPR			0x00000110 ++/* Bitfields in SMR */ ++#define TWI_SADR_OFFSET				16 ++#define TWI_SADR_SIZE				7  + -+/* SSC PDC Receive Next Counter Register */ -+#define SSC_PDC_RNCR			0x00000114 ++/* Bitfields in IADR */ ++#define TWI_IADR_OFFSET				0 ++#define TWI_IADR_SIZE				24  + -+/* SSC PDC Transmit Counter Register */ -+#define SSC_PDC_TCR			0x0000010c ++/* 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  + -+/* SSC PDC Transmit Next Pointer Register */ -+#define SSC_PDC_TNPR			0x00000118 ++/* 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  + -+/* SSC PDC Transmit Next Counter Register */ -+#define SSC_PDC_TNCR			0x0000011c ++/* Bitfields in RHR */ ++#define TWI_RXDATA_OFFSET			0 ++#define TWI_RXDATA_SIZE				8  + -+/* 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 ++/* Bitfields in THR */ ++#define TWI_TXDATA_OFFSET			0 ++#define TWI_TXDATA_SIZE				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 ++/* 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 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)) ++#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 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]; -+	}; -+}; ++#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 /* _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 ++#endif /* __ASM_AVR32_TWI_H__ */ +Index: linux-2.6.22.1/drivers/i2c/busses/Makefile +=================================================================== +--- linux-2.6.22.1/drivers/i2c/busses/Makefile	(revision 1) ++++ linux-2.6.22.1/drivers/i2c/busses/Makefile	(arbetskopia) +@@ -30,6 +30,7 @@ + obj-$(CONFIG_I2C_PARPORT)	+= i2c-parport.o + obj-$(CONFIG_I2C_PARPORT_LIGHT)	+= i2c-parport-light.o + obj-$(CONFIG_I2C_PASEMI)	+= i2c-pasemi.o ++obj-$(CONFIG_I2C_PCA)		+= i2c-pca.o + obj-$(CONFIG_I2C_PCA_ISA)	+= i2c-pca-isa.o + obj-$(CONFIG_I2C_PIIX4)		+= i2c-piix4.o + obj-$(CONFIG_I2C_PNX)		+= i2c-pnx.o +@@ -52,6 +53,7 @@ + obj-$(CONFIG_I2C_VOODOO3)	+= i2c-voodoo3.o + obj-$(CONFIG_SCx200_ACB)	+= scx200_acb.o + obj-$(CONFIG_SCx200_I2C)	+= scx200_i2c.o ++obj-$(CONFIG_I2C_ATMELTWI)	+= i2c-atmeltwi.o -+/* 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 @@ + ifeq ($(CONFIG_I2C_DEBUG_BUS),y) + EXTRA_CFLAGS += -DDEBUG +Index: linux-2.6.22.1/drivers/i2c/busses/i2c-pca.c +=================================================================== +--- linux-2.6.22.1/drivers/i2c/busses/i2c-pca.c	(revision 0) ++++ linux-2.6.22.1/drivers/i2c/busses/i2c-pca.c	(revision 0) +@@ -0,0 +1,213 @@  +/* -+ * 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. ++ *  Platform driver for PCA9564 I2C bus controller.  + * -+ * @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 ++ *  (C) 2006 Andrew Victor  + * -+ * 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. ++ *  Based on i2c-pca-isa.c driver for PCA9564 on ISA boards ++ *    Copyright (C) 2004 Arcom Control Systems  + * -+ * 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 ++ *  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.  + * -+ * Copyright (C) 2006-2007 Atmel Norway ++ *  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.  + * -+ * 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. ++ *  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., 675 Mass Ave, Cambridge, MA 02139, USA.  + */  + -+/*#define DEBUG*/ -+ -+#include <linux/clk.h> -+#include <linux/err.h> ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/moduleparam.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/wait.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); ++#include <linux/i2c.h> ++#include <linux/i2c-algo-pca.h>  + -+	block_size = frames_to_bytes(runtime, runtime->period_size); -+	status = ssc_readl(chip->ssc->regs, IMR); ++#include <asm/io.h>  + -+	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; ++#include "../algos/i2c-algo-pca.h"  + -+		offset = block_size * next_period; ++#define PCA_OWN_ADDRESS		0x55	/* our address for slave mode */ ++#define PCA_CLOCK		I2C_PCA_CON_59kHz  + -+		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; -+	} ++//#define REG_SHIFT		2 ++#define REG_SHIFT		0  + -+	ssc_readl(chip->ssc->regs, IMR); -+	spin_unlock(&chip->lock); ++//#define DEBUG_IO  + -+	if (status & SSC_BIT(IMR_ENDTX)) -+		snd_pcm_period_elapsed(chip->substream); ++#define PCA_IO_SIZE 4  + -+	return retval; -+} ++static void __iomem *base_addr; ++static int irq; ++static wait_queue_head_t pca_wait;  + -+/* -+ * Mixer functions. -+ */ -+static int snd_at73c213_mono_get(struct snd_kcontrol *kcontrol, -+				 struct snd_ctl_elem_value *ucontrol) ++static int pca_getown(struct i2c_algo_pca_data *adap)  +{ -+	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; ++	return PCA_OWN_ADDRESS;  +}  + -+static int snd_at73c213_mono_put(struct snd_kcontrol *kcontrol, -+				 struct snd_ctl_elem_value *ucontrol) ++static int pca_getclock(struct i2c_algo_pca_data *adap)  +{ -+	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; ++	return PCA_CLOCK;  +}  + -+static int snd_at73c213_stereo_info(struct snd_kcontrol *kcontrol, -+				  struct snd_ctl_elem_info *uinfo) ++static void pca_writebyte(struct i2c_algo_pca_data *adap, int reg, int val)  +{ -+	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; ++#ifdef DEBUG_IO ++	static char *names[] = { "T/O", "DAT", "ADR", "CON" }; ++	printk("*** write %s at %#lx <= %#04x\n", names[reg], (unsigned long) base_addr+reg, val); ++#endif ++	udelay(1); ++	outb(val, base_addr + (reg << REG_SHIFT));  +}  + -+static int snd_at73c213_stereo_get(struct snd_kcontrol *kcontrol, -+				 struct snd_ctl_elem_value *ucontrol) ++static int pca_readbyte(struct i2c_algo_pca_data *adap, int reg)  +{ -+	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; ++	int res;  + -+	if (invert) { -+		ucontrol->value.integer.value[0] = -+			(mask - ucontrol->value.integer.value[0]); -+		ucontrol->value.integer.value[1] = -+			(mask - ucontrol->value.integer.value[1]); ++	udelay(1); ++	res = inb(base_addr + (reg << REG_SHIFT)); ++#ifdef DEBUG_IO ++	{ ++		static char *names[] = { "STA", "DAT", "ADR", "CON" }; ++		printk("*** read  %s => %#04x\n", names[reg], res);  +	} -+ -+	spin_unlock_irq(&chip->lock); -+ -+	return 0; ++#endif ++	return res;  +}  + -+static int snd_at73c213_stereo_put(struct snd_kcontrol *kcontrol, -+				 struct snd_ctl_elem_value *ucontrol) ++static int pca_waitforinterrupt(struct i2c_algo_pca_data *adap)  +{ -+	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); ++	int ret = 0;  + -+	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; ++	if (irq > -1) { ++		ret = wait_event_interruptible(pca_wait, ++				pca_readbyte(adap, I2C_PCA_CON) & I2C_PCA_CON_SI); ++	} else { ++		while ((pca_readbyte(adap, I2C_PCA_CON) & I2C_PCA_CON_SI) == 0) ++			udelay(100);  +	} -+ -+	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; ++	return ret;  +}  + -+static int snd_at73c213_aux_capture_volume_info( -+		struct snd_kcontrol *kcontrol, -+		struct snd_ctl_elem_info *uinfo) ++static irqreturn_t pca_handler(int this_irq, void *dev_id)  +{ -+	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))		\ ++	wake_up_interruptible(&pca_wait); ++	return IRQ_HANDLED;  +}  + -+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 struct i2c_algo_pca_data pca_i2c_data = { ++	.get_own		= pca_getown, ++	.get_clock		= pca_getclock, ++	.write_byte		= pca_writebyte, ++	.read_byte		= pca_readbyte, ++	.wait_for_interrupt	= pca_waitforinterrupt,  +};  + -+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 struct i2c_adapter pca_i2c_ops = { ++	.owner          = THIS_MODULE, ++	.id		= I2C_HW_A_PLAT, ++	.algo_data	= &pca_i2c_data, ++	.name		= "PCA9564", ++	.class		= I2C_CLASS_HWMON, ++};  + -+static int __devinit snd_at73c213_dev_init(struct snd_card *card, -+					 struct spi_device *spi) ++static int __devinit pca_i2c_probe(struct platform_device *pdev)  +{ -+	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); ++	struct resource *res;  + -+	goto out; ++	init_waitqueue_head(&pca_wait);  + -+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]; ++	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++	if (!res) ++		return -ENODEV;  + -+	board = spi->dev.platform_data; -+	if (!board) { -+		dev_dbg(&spi->dev, "no platform_data\n"); ++	if (!request_mem_region(res->start, PCA_IO_SIZE, "PCA9564"))  +		return -ENXIO; -+	}  + -+	if (!board->dac_clk) { -+		dev_dbg(&spi->dev, "no DAC clk\n"); -+		return -ENXIO; -+	} ++	base_addr = ioremap(res->start, PCA_IO_SIZE); ++	if (base_addr == NULL) ++		goto out_region;  + -+	if (IS_ERR(board->dac_clk)) { -+		dev_dbg(&spi->dev, "no DAC clk\n"); -+		return PTR_ERR(board->dac_clk); ++	irq = platform_get_irq(pdev, 0); ++	if (irq > -1) { ++		if (request_irq(irq, pca_handler, 0, "pca9564", NULL) < 0) { ++			printk(KERN_ERR "i2c-pca: Request irq%d failed\n", irq); ++			goto out_remap; ++		}  +	}  + -+	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; ++	/* set up the driverfs linkage to our parent device */ ++	pca_i2c_ops.dev.parent = &pdev->dev;  + -+	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; ++	if (i2c_pca_add_bus(&pca_i2c_ops) < 0) { ++		printk(KERN_ERR "i2c-pca: Failed to add i2c bus\n"); ++		goto out_irq;  +	}  + -+	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; ++	return 0;  + -+out: -+	/* Stop DAC master clock. */ -+	clk_disable(chip->board->dac_clk); ++ out_irq: ++	if (irq > -1) ++		free_irq(irq, &pca_i2c_ops);  + -+	ssc_free(chip->ssc); -+	snd_card_free(card); -+	dev_set_drvdata(&spi->dev, NULL); ++ out_remap: ++	iounmap(base_addr);  + -+	return 0; ++ out_region: ++	release_mem_region(res->start, PCA_IO_SIZE); ++	return -ENODEV;  +}  + -+#ifdef CONFIG_PM -+static int snd_at73c213_suspend(struct spi_device *spi, pm_message_t msg) ++static int __devexit pca_i2c_remove(struct platform_device *pdev)  +{ -+	struct snd_card *card = dev_get_drvdata(&spi->dev); -+	struct snd_at73c213 *chip = card->private_data; ++	struct resource *res;  + -+	ssc_writel(chip->ssc->regs, CR, SSC_BIT(CR_TXDIS)); -+	clk_disable(chip->board->dac_clk); ++	i2c_del_adapter(&pca_i2c_ops);  + -+	return 0; -+} ++	if (irq > 0) ++		free_irq(irq, NULL);  + -+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; ++	iounmap(base_addr);  + -+	clk_enable(chip->board->dac_clk); -+	ssc_writel(chip->ssc->regs, CR, SSC_BIT(CR_TXEN)); ++	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++	release_mem_region(res->start, PCA_IO_SIZE);  +  +	return 0;  +} -+#else -+#define snd_at73c213_suspend NULL -+#define snd_at73c213_resume NULL -+#endif  + -+static struct spi_driver at73c213_driver = { ++static struct platform_driver pca_i2c_driver = { ++	.probe		= pca_i2c_probe, ++	.remove		= __devexit_p(pca_i2c_remove),  +	.driver		= { -+		.name	= "at73c213", ++		.name	= "pca9564", ++		.owner	= THIS_MODULE,  +	}, -+	.probe		= snd_at73c213_probe, -+	.suspend	= snd_at73c213_suspend, -+	.resume		= snd_at73c213_resume, -+	.remove		= __devexit_p(snd_at73c213_remove),  +};  + -+static int __init at73c213_init(void) ++static int __init pca_i2c_init(void)  +{ -+	return spi_register_driver(&at73c213_driver); ++	return platform_driver_register(&pca_i2c_driver);  +} -+module_init(at73c213_init);  + -+static void __exit at73c213_exit(void) ++static void __exit pca_i2c_exit(void)  +{ -+	spi_unregister_driver(&at73c213_driver); ++	platform_driver_unregister(&pca_i2c_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 ++module_init(pca_i2c_init); ++module_exit(pca_i2c_exit);  + -+/* 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 */ ++MODULE_AUTHOR("Andrew Victor"); ++MODULE_DESCRIPTION("PCA9564 platform driver"); ++MODULE_LICENSE("GPL"); +Index: linux-2.6.22.1/drivers/i2c/busses/i2c-at91.c +=================================================================== +--- linux-2.6.22.1/drivers/i2c/busses/i2c-at91.c	(revision 1) ++++ linux-2.6.22.1/drivers/i2c/busses/i2c-at91.c	(arbetskopia) +@@ -31,8 +31,11 @@ + #include <asm/arch/board.h> + #include <asm/arch/cpu.h> +  +-#define TWI_CLOCK		100000		/* Hz. max 400 Kbits/sec */ +  ++/* Clockrate is configurable - max 400 Kbits/sec */ ++static unsigned int clockrate = CONFIG_I2C_AT91_CLOCKRATE; ++module_param(clockrate, uint, 0); ++MODULE_PARM_DESC(clockrate, "The TWI clockrate"); +  + static struct clk *twi_clk; + static void __iomem *twi_base; +@@ -53,7 +56,7 @@ + 	at91_twi_write(AT91_TWI_CR, AT91_TWI_MSEN);	/* Set Master mode */ +  + 	/* Calcuate clock dividers */ +-	cdiv = (clk_get_rate(twi_clk) / (2 * TWI_CLOCK)) - 3; ++	cdiv = (clk_get_rate(twi_clk) / (2 * clockrate)) - 3; + 	cdiv = cdiv + 1;	/* round up */ + 	ckdiv = 0; + 	while (cdiv > 255) { +@@ -61,11 +64,12 @@ + 		cdiv = cdiv >> 1; + 	} +  +-	if (cpu_is_at91rm9200()) {			/* AT91RM9200 Errata #22 */ +-		if (ckdiv > 5) { +-			printk(KERN_ERR "AT91 I2C: Invalid TWI_CLOCK value!\n"); +-			ckdiv = 5; +-		} ++	if (cpu_is_at91rm9200() && (ckdiv > 5)) {	/* AT91RM9200 Errata #22 */ ++		printk(KERN_ERR "AT91 I2C: Invalid TWI clockrate!\n"); ++		ckdiv = 5; ++	} else if (ckdiv > 7) { ++		printk(KERN_ERR "AT91 I2C: Invalid TWI clockrate!\n"); ++		ckdiv = 7; + 	} +  + 	at91_twi_write(AT91_TWI_CWGR, (ckdiv << 16) | (cdiv << 8) | cdiv); diff --git a/target/device/Atmel/linux/kernel-patches-2.6.22.1/linux-2.6.22.1-005-atags-support.patch b/target/device/Atmel/linux/kernel-patches-2.6.22.1/linux-2.6.22.1-005-atags-support.patch new file mode 100644 index 000000000..0068ef17c --- /dev/null +++ b/target/device/Atmel/linux/kernel-patches-2.6.22.1/linux-2.6.22.1-005-atags-support.patch @@ -0,0 +1,122 @@ +--- linux-2.6.22/arch/arm/kernel/head-common.S	2007-05-16 10:13:04.000000000 -0500 ++++ linux-2.6.22-bgat/arch/arm/kernel/head-common.S	2007-05-30 21:54:45.000000000 -0500 +@@ -20,7 +20,8 @@ + 	.long	_end				@ r7 + 	.long	processor_id			@ r4 + 	.long	__machine_arch_type		@ r5 +-	.long	cr_alignment			@ r6 ++	.long	__atags_pointer			@ r6 ++	.long	cr_alignment			@ r7 + 	.long	init_thread_union + THREAD_START_SP @ sp +  + /* +@@ -29,6 +30,7 @@ +  * +  *  r0  = cp#15 control register +  *  r1  = machine ID ++ *  r2  = atags pointer +  *  r9  = processor ID +  */ + 	.type	__mmap_switched, %function +@@ -47,11 +49,12 @@ + 	strcc	fp, [r6],#4 + 	bcc	1b +  +-	ldmia	r3, {r4, r5, r6, sp} ++	ldmia	r3, {r4, r5, r6, r7, sp} + 	str	r9, [r4]			@ Save processor ID + 	str	r1, [r5]			@ Save machine type ++	str	r2, [r6]			@ Save atags pointer + 	bic	r4, r0, #CR_A			@ Clear 'A' bit +-	stmia	r6, {r0, r4}			@ Save control register values ++	stmia	r7, {r0, r4}			@ Save control register values + 	b	start_kernel +  + /* +@@ -215,3 +218,34 @@ + 	bl	__lookup_machine_type + 	mov	r0, r5 + 	ldmfd	sp!, {r4 - r6, pc} ++ ++/* Determine validity of the r2 atags pointer.  The heuristic requires ++ * that the pointer be aligned, in the first 16k of physical RAM and ++ * that the ATAG_CORE marker is first and present.  Future revisions ++ * of this function may be more lenient with the physical address and ++ * may also be able to move the ATAGS block if necessary. ++ * ++ * r8  = machinfo ++ * ++ * Returns: ++ *  r2 either valid atags pointer, or zero ++ *  r5, r6 corrupted ++ */ ++ ++	.type	__vet_atags, %function ++__vet_atags: ++	tst	r2, #0x3			@ aligned? ++	bne	1f ++ ++	ldr	r5, [r2, #0]			@ is first tag ATAG_CORE? ++	subs	r5, r5, #ATAG_CORE_SIZE ++	bne	1f ++	ldr	r5, [r2, #4] ++	ldr	r6, =ATAG_CORE ++	cmp	r5, r6 ++	bne	1f ++ ++	mov	pc, lr				@ atag pointer is ok ++ ++1:	mov	r2, #0 ++	mov	pc, lr +--- linux-2.6.22/arch/arm/kernel/head.S	2007-05-30 08:29:34.000000000 -0500 ++++ linux-2.6.22-bgat/arch/arm/kernel/head.S	2007-05-30 22:05:53.000000000 -0500 +@@ -29,6 +29,10 @@ + #define KERNEL_RAM_VADDR	(PAGE_OFFSET + TEXT_OFFSET) + #define KERNEL_RAM_PADDR	(PHYS_OFFSET + TEXT_OFFSET) +  ++#define ATAG_CORE 0x54410001 ++#define ATAG_CORE_SIZE ((2*4 + 3*4) >> 2) ++ ++ + /* +  * swapper_pg_dir is the virtual address of the initial page table. +  * We place the page tables 16K below KERNEL_RAM_VADDR.  Therefore, we must +@@ -61,7 +65,7 @@ +  * +  * This is normally called from the decompressor code.  The requirements +  * are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0, +- * r1 = machine nr. ++ * r1 = machine nr, r2 = atags pointer. +  * +  * This code is mostly position independent, so if you link the kernel at +  * 0xc0008000, you call this at __pa(0xc0008000). +@@ -85,6 +89,7 @@ + 	bl	__lookup_machine_type		@ r5=machinfo + 	movs	r8, r5				@ invalid machine (r5=0)? + 	beq	__error_a			@ yes, error 'a' ++	bl	__vet_atags + 	bl	__create_page_tables +  + 	/* +--- linux-2.6.22/arch/arm/kernel/setup.c	2007-05-30 08:29:34.000000000 -0500 ++++ linux-2.6.22-bgat/arch/arm/kernel/setup.c	2007-05-30 22:07:08.000000000 -0500 +@@ -63,6 +63,8 @@ + unsigned int __machine_arch_type; + EXPORT_SYMBOL(__machine_arch_type); +  ++unsigned int __atags_pointer __initdata; ++ + unsigned int system_rev; + EXPORT_SYMBOL(system_rev); +  +@@ -780,7 +782,9 @@ + 	if (mdesc->soft_reboot) + 		reboot_setup("s"); +  +-	if (mdesc->boot_params) ++	if (__atags_pointer) ++		tags = phys_to_virt(__atags_pointer); ++	else if (mdesc->boot_params) + 		tags = phys_to_virt(mdesc->boot_params); +  + 	/*  | 
