diff options
author | Ulf Samuelsson <ulf.samuelsson@atmel.com> | 2008-03-18 09:36:16 +0000 |
---|---|---|
committer | Ulf Samuelsson <ulf.samuelsson@atmel.com> | 2008-03-18 09:36:16 +0000 |
commit | 896cfb2afef3db898961aaa4db93b1ec6becf014 (patch) | |
tree | 72062564e0d95f275428f643aa1eb829153379ee /target | |
parent | 771ecd45c1a6f64f7d996416b773a44472731a09 (diff) |
Remove duplicate patches and arrange according to architecture
Diffstat (limited to 'target')
-rw-r--r-- | target/device/Atmel/Linux/kernel-patches-2.6.20.4/linux-2.6.20.4-atmel.patch | 26777 | ||||
-rw-r--r-- | target/device/Atmel/arch-arm/kernel-patches-2.6.21.1/2.6.21.1-at91.patch (renamed from target/device/Atmel/Linux/kernel-patches-2.6.21.1/2.6.21.1-at91.patch) | 0 | ||||
-rw-r--r-- | target/device/Atmel/arch-arm/kernel-patches-2.6.21.1/linux-2.6.21.1-at91-1-update.patch (renamed from target/device/Atmel/Linux/kernel-patches-2.6.21.1/linux-2.6.21.1-at91-1-update.patch) | 0 |
3 files changed, 0 insertions, 26777 deletions
diff --git a/target/device/Atmel/Linux/kernel-patches-2.6.20.4/linux-2.6.20.4-atmel.patch b/target/device/Atmel/Linux/kernel-patches-2.6.20.4/linux-2.6.20.4-atmel.patch deleted file mode 100644 index 9cd333429..000000000 --- a/target/device/Atmel/Linux/kernel-patches-2.6.20.4/linux-2.6.20.4-atmel.patch +++ /dev/null @@ -1,26777 +0,0 @@ -diff -urN linux-2.6.20.4-0rig/arch/arm/configs/at91sam9263ek_defconfig linux-2.6.20.4-atmel/arch/arm/configs/at91sam9263ek_defconfig ---- linux-2.6.20.4-0rig/arch/arm/configs/at91sam9263ek_defconfig 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/arm/configs/at91sam9263ek_defconfig 2007-03-24 16:39:15.000000000 +0100 -@@ -0,0 +1,1184 @@ -+# -+# Automatically generated make config: don't edit -+# Linux kernel version: 2.6.20-rc1 -+# Mon Jan 8 16:06:54 2007 -+# -+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" -+ -+# -+# Code maturity level options -+# -+CONFIG_EXPERIMENTAL=y -+CONFIG_BROKEN_ON_SMP=y -+CONFIG_INIT_ENV_ARG_LIMIT=32 -+ -+# -+# General setup -+# -+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 is not set -+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 -+ -+# -+# Loadable module support -+# -+CONFIG_MODULES=y -+CONFIG_MODULE_UNLOAD=y -+# CONFIG_MODULE_FORCE_UNLOAD is not set -+# CONFIG_MODVERSIONS is not set -+# CONFIG_MODULE_SRCVERSION_ALL is not set -+CONFIG_KMOD=y -+ -+# -+# 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 -+# -+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" -+ -+# -+# 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_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 -+ -+# -+# Atmel AT91 System-on-Chip -+# -+# CONFIG_ARCH_AT91RM9200 is not set -+# CONFIG_ARCH_AT91SAM9260 is not set -+# CONFIG_ARCH_AT91SAM9261 is not set -+CONFIG_ARCH_AT91SAM9263=y -+ -+# -+# AT91SAM9263 Board Type -+# -+CONFIG_MACH_AT91SAM9263EK=y -+ -+# -+# AT91 Board Options -+# -+CONFIG_MTD_AT91_DATAFLASH_CARD=y -+# CONFIG_MTD_NAND_AT91_BUSWIDTH_16 is not set -+ -+# -+# AT91 Feature Selections -+# -+# CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set -+ -+# -+# Processor Type -+# -+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 -+ -+# -+# Processor Features -+# -+# 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 -+ -+# -+# Bus support -+# -+ -+# -+# PCCARD (PCMCIA/CardBus) support -+# -+# CONFIG_PCCARD is not set -+ -+# -+# 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_LEDS is not set -+CONFIG_ALIGNMENT_TRAP=y -+ -+# -+# Boot options -+# -+CONFIG_ZBOOT_ROM_TEXT=0x0 -+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 -+ -+# -+# Floating point emulation -+# -+ -+# -+# At least one emulation must be selected -+# -+CONFIG_FPE_NWFPE=y -+# CONFIG_FPE_NWFPE_XP is not set -+# CONFIG_FPE_FASTFPE is not set -+# CONFIG_VFP is not set -+ -+# -+# Userspace binary formats -+# -+CONFIG_BINFMT_ELF=y -+# CONFIG_BINFMT_AOUT is not set -+# CONFIG_BINFMT_MISC is not set -+# CONFIG_ARTHUR is not set -+ -+# -+# Power management options -+# -+# CONFIG_PM is not set -+# CONFIG_APM is not set -+ -+# -+# Networking -+# -+CONFIG_NET=y -+ -+# -+# 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 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=y -+# 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 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 -+ -+# -+# DCCP Configuration (EXPERIMENTAL) -+# -+# CONFIG_IP_DCCP is not set -+ -+# -+# SCTP Configuration (EXPERIMENTAL) -+# -+# CONFIG_IP_SCTP is not set -+ -+# -+# 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 -+ -+# -+# 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 -+ -+# -+# Device Drivers -+# -+ -+# -+# Generic Driver Options -+# -+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 -+ -+# -+# Connector - unified userspace <-> kernelspace linker -+# -+# CONFIG_CONNECTOR is not set -+ -+# -+# Memory Technology Devices (MTD) -+# -+CONFIG_MTD=y -+# CONFIG_MTD_DEBUG is not set -+# CONFIG_MTD_CONCAT is not set -+CONFIG_MTD_PARTITIONS=y -+# CONFIG_MTD_REDBOOT_PARTS is not set -+CONFIG_MTD_CMDLINE_PARTS=y -+# CONFIG_MTD_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 -+ -+# -+# 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 -+ -+# -+# Mapping drivers for chip access -+# -+# CONFIG_MTD_COMPLEX_MAPPINGS is not set -+# CONFIG_MTD_PLATRAM is not set -+ -+# -+# Self-contained MTD device drivers -+# -+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 -+ -+# -+# Disk-On-Chip Device Drivers -+# -+# CONFIG_MTD_DOC2000 is not set -+# CONFIG_MTD_DOC2001 is not set -+# CONFIG_MTD_DOC2001PLUS is not set -+ -+# -+# 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 -+ -+# -+# OneNAND Flash Device Drivers -+# -+# CONFIG_MTD_ONENAND is not set -+ -+# -+# Parallel port support -+# -+# CONFIG_PARPORT is not set -+ -+# -+# Plug and Play support -+# -+ -+# -+# Block devices -+# -+# CONFIG_BLK_DEV_COW_COMMON is not set -+CONFIG_BLK_DEV_LOOP=y -+# CONFIG_BLK_DEV_CRYPTOLOOP is not set -+# 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=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 -+ -+# -+# 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 -+ -+# -+# SCSI support type (disk, tape, CD-ROM) -+# -+CONFIG_BLK_DEV_SD=y -+# CONFIG_CHR_DEV_ST is not set -+# CONFIG_CHR_DEV_OSST is not set -+# CONFIG_BLK_DEV_SR is not set -+# CONFIG_CHR_DEV_SG is not set -+# CONFIG_CHR_DEV_SCH is not set -+ -+# -+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -+# -+CONFIG_SCSI_MULTI_LUN=y -+# CONFIG_SCSI_CONSTANTS is not set -+# CONFIG_SCSI_LOGGING is not set -+# CONFIG_SCSI_SCAN_ASYNC is not set -+ -+# -+# SCSI Transports -+# -+# CONFIG_SCSI_SPI_ATTRS is not set -+# CONFIG_SCSI_FC_ATTRS is not set -+# CONFIG_SCSI_ISCSI_ATTRS is not set -+# CONFIG_SCSI_SAS_ATTRS is not set -+# CONFIG_SCSI_SAS_LIBSAS is not set -+ -+# -+# SCSI low-level drivers -+# -+# CONFIG_ISCSI_TCP is not set -+# CONFIG_SCSI_DEBUG is not set -+ -+# -+# Serial ATA (prod) and Parallel ATA (experimental) drivers -+# -+# CONFIG_ATA is not set -+ -+# -+# Multi-device support (RAID and LVM) -+# -+# CONFIG_MD is not set -+ -+# -+# Fusion MPT device support -+# -+# CONFIG_FUSION is not set -+ -+# -+# IEEE 1394 (FireWire) support -+# -+ -+# -+# I2O device support -+# -+ -+# -+# 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 -+ -+# -+# PHY device support -+# -+# CONFIG_PHYLIB is not set -+ -+# -+# Ethernet (10 or 100Mbit) -+# -+CONFIG_NET_ETHERNET=y -+CONFIG_MII=y -+# CONFIG_SMC91X is not set -+# CONFIG_DM9000 is not set -+ -+# -+# Ethernet (1000 Mbit) -+# -+ -+# -+# Ethernet (10000 Mbit) -+# -+ -+# -+# Token Ring devices -+# -+ -+# -+# Wireless LAN (non-hamradio) -+# -+# CONFIG_NET_RADIO is not set -+ -+# -+# 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 -+# -+# CONFIG_ISDN is not set -+ -+# -+# Input device support -+# -+CONFIG_INPUT=y -+# CONFIG_INPUT_FF_MEMLESS is not set -+ -+# -+# 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=y -+CONFIG_INPUT_TSDEV_SCREEN_X=240 -+CONFIG_INPUT_TSDEV_SCREEN_Y=320 -+CONFIG_INPUT_EVDEV=y -+# CONFIG_INPUT_EVBUG is not set -+ -+# -+# Input Device Drivers -+# -+# CONFIG_INPUT_KEYBOARD is not set -+# CONFIG_INPUT_MOUSE is not set -+# CONFIG_INPUT_JOYSTICK 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 -+ -+# -+# Hardware I/O ports -+# -+# CONFIG_SERIO is not set -+# CONFIG_GAMEPORT is not set -+ -+# -+# 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 -+ -+# -+# Serial drivers -+# -+# CONFIG_SERIAL_8250 is not set -+ -+# -+# Non-8250 serial port support -+# -+CONFIG_SERIAL_ATMEL=y -+CONFIG_SERIAL_ATMEL_CONSOLE=y -+# CONFIG_SERIAL_ATMEL_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 -+ -+# -+# IPMI -+# -+# CONFIG_IPMI_HANDLER is not set -+ -+# -+# Watchdog Cards -+# -+CONFIG_WATCHDOG=y -+CONFIG_WATCHDOG_NOWAYOUT=y -+ -+# -+# Watchdog Device Drivers -+# -+# CONFIG_SOFT_WATCHDOG is not set -+ -+# -+# USB-based Watchdog Cards -+# -+# CONFIG_USBPCWATCHDOG is not set -+CONFIG_HW_RANDOM=y -+# CONFIG_NVRAM is not set -+# CONFIG_DTLK is not set -+# CONFIG_R3964 is not set -+# CONFIG_RAW_DRIVER is not set -+ -+# -+# TPM devices -+# -+# CONFIG_TCG_TPM is not set -+ -+# -+# I2C support -+# -+CONFIG_I2C=y -+CONFIG_I2C_CHARDEV=y -+ -+# -+# I2C Algorithms -+# -+# CONFIG_I2C_ALGOBIT is not set -+# CONFIG_I2C_ALGOPCF is not set -+# CONFIG_I2C_ALGOPCA is not set -+ -+# -+# I2C Hardware Bus support -+# -+CONFIG_I2C_AT91=y -+# CONFIG_I2C_OCORES is not set -+# CONFIG_I2C_PARPORT_LIGHT is not set -+# CONFIG_I2C_STUB is not set -+# CONFIG_I2C_PCA is not set -+# CONFIG_I2C_PCA_ISA 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 -+# 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 -+# -+ -+# -+# Dallas's 1-wire bus -+# -+# CONFIG_W1 is not set -+ -+# -+# Hardware Monitoring support -+# -+# CONFIG_HWMON is not set -+# CONFIG_HWMON_VID is not set -+ -+# -+# Misc devices -+# -+# CONFIG_TIFM_CORE is not set -+ -+# -+# LED devices -+# -+# CONFIG_NEW_LEDS is not set -+ -+# -+# LED drivers -+# -+ -+# -+# LED Triggers -+# -+ -+# -+# Multimedia devices -+# -+# CONFIG_VIDEO_DEV is not set -+ -+# -+# Digital Video Broadcasting Devices -+# -+# CONFIG_DVB is not set -+# CONFIG_USB_DABUSB is not set -+ -+# -+# Graphics support -+# -+# CONFIG_FIRMWARE_EDID is not set -+CONFIG_FB=y -+# CONFIG_FB_CFB_FILLRECT is not set -+# CONFIG_FB_CFB_COPYAREA is not set -+# CONFIG_FB_CFB_IMAGEBLIT 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_FB_S1D13XXX is not set -+# CONFIG_FB_VIRTUAL is not set -+ -+# -+# Console display driver support -+# -+# CONFIG_VGA_CONSOLE is not set -+CONFIG_DUMMY_CONSOLE=y -+# CONFIG_FRAMEBUFFER_CONSOLE is not set -+ -+# -+# Logo configuration -+# -+# CONFIG_LOGO is not set -+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set -+ -+# -+# Sound -+# -+# CONFIG_SOUND is not set -+ -+# -+# HID Devices -+# -+CONFIG_HID=y -+ -+# -+# 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 is not set -+ -+# -+# 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 -+ -+# -+# 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_LITTLE_ENDIAN=y -+# CONFIG_USB_SL811_HCD is not set -+ -+# -+# USB Device Class drivers -+# -+# 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 -+# -+CONFIG_USB_STORAGE=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_ONETOUCH is not set -+# CONFIG_USB_STORAGE_KARMA is not set -+# CONFIG_USB_LIBUSUAL is not set -+ -+# -+# 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_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_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 -+ -+# -+# USB Imaging devices -+# -+# CONFIG_USB_MDC800 is not set -+# CONFIG_USB_MICROTEK is not set -+ -+# -+# 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=y -+ -+# -+# USB port drivers -+# -+ -+# -+# USB Serial Converter support -+# -+# CONFIG_USB_SERIAL is not set -+ -+# -+# USB Miscellaneous drivers -+# -+# CONFIG_USB_EMI62 is not set -+# CONFIG_USB_EMI26 is not set -+# CONFIG_USB_ADUTUX is not set -+# CONFIG_USB_AUERSWALD is not set -+# CONFIG_USB_RIO500 is not set -+# CONFIG_USB_LEGOTOWER is not set -+# CONFIG_USB_LCD is not set -+# CONFIG_USB_LED is not set -+# CONFIG_USB_CYPRESS_CY7C63 is not set -+# CONFIG_USB_CYTHERM is not set -+# CONFIG_USB_PHIDGET is not set -+# CONFIG_USB_IDMOUSE is not set -+# CONFIG_USB_FTDI_ELAN is not set -+# CONFIG_USB_APPLEDISPLAY is not set -+# CONFIG_USB_LD is not set -+# CONFIG_USB_TRANCEVIBRATOR is not set -+# CONFIG_USB_TEST is not set -+ -+# -+# USB DSL modem support -+# -+ -+# -+# USB Gadget Support -+# -+CONFIG_USB_GADGET=y -+# CONFIG_USB_GADGET_DEBUG_FILES is not set -+CONFIG_USB_GADGET_SELECTED=y -+# 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_OMAP is not set -+CONFIG_USB_GADGET_AT91=y -+CONFIG_USB_AT91=y -+# CONFIG_USB_GADGET_DUMMY_HCD is not set -+# CONFIG_USB_GADGET_DUALSPEED is not set -+CONFIG_USB_ZERO=m -+# CONFIG_USB_ETH is not set -+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 -+ -+# -+# MMC/SD Card support -+# -+CONFIG_MMC=y -+# CONFIG_MMC_DEBUG is not set -+CONFIG_MMC_BLOCK=y -+CONFIG_MMC_AT91=m -+# CONFIG_MMC_TIFM_SD is not set -+ -+# -+# Real Time Clock -+# -+CONFIG_RTC_LIB=y -+# CONFIG_RTC_CLASS is not set -+ -+# -+# File systems -+# -+CONFIG_EXT2_FS=y -+# CONFIG_EXT2_FS_XATTR is not set -+# CONFIG_EXT2_FS_XIP is not set -+# CONFIG_EXT3_FS is not set -+# CONFIG_EXT4DEV_FS is not set -+# CONFIG_REISERFS_FS is not set -+# CONFIG_JFS_FS is not set -+# CONFIG_FS_POSIX_ACL is not set -+# CONFIG_XFS_FS is not set -+# CONFIG_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 is not set -+# CONFIG_FUSE_FS is not set -+ -+# -+# CD-ROM/DVD Filesystems -+# -+# CONFIG_ISO9660_FS is not set -+# CONFIG_UDF_FS is not set -+ -+# -+# 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 -+ -+# -+# 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 -+ -+# -+# 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 -+ -+# -+# Network File Systems -+# -+CONFIG_NFS_FS=y -+# CONFIG_NFS_V3 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_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 -+ -+# -+# Partition Types -+# -+# CONFIG_PARTITION_ADVANCED is not set -+CONFIG_MSDOS_PARTITION=y -+ -+# -+# 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 -+ -+# -+# Distributed Lock Manager -+# -+# CONFIG_DLM is not set -+ -+# -+# Profiling support -+# -+# CONFIG_PROFILING is not set -+ -+# -+# 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 -+ -+# -+# Security options -+# -+# CONFIG_KEYS is not set -+# CONFIG_SECURITY is not set -+ -+# -+# Cryptographic options -+# -+# CONFIG_CRYPTO is not set -+ -+# -+# 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_IOMAP_COPY=y -diff -urN linux-2.6.20.4-0rig/arch/arm/configs/csb337_defconfig linux-2.6.20.4-atmel/arch/arm/configs/csb337_defconfig ---- linux-2.6.20.4-0rig/arch/arm/configs/csb337_defconfig 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/arm/configs/csb337_defconfig 2007-03-24 16:39:15.000000000 +0100 -@@ -355,10 +355,12 @@ - # Mapping drivers for chip access - # - # CONFIG_MTD_COMPLEX_MAPPINGS is not set --# CONFIG_MTD_PHYSMAP is not set -+CONFIG_MTD_PHYSMAP=y -+CONFIG_MTD_PHYSMAP_START=0 -+CONFIG_MTD_PHYSMAP_LEN=0 -+CONFIG_MTD_PHYSMAP_BANKWIDTH=0 - # CONFIG_MTD_ARM_INTEGRATOR is not set - # CONFIG_MTD_PLATRAM is not set --CONFIG_MTD_CSB337=y - - # - # Self-contained MTD device drivers -diff -urN linux-2.6.20.4-0rig/arch/arm/configs/csb637_defconfig linux-2.6.20.4-atmel/arch/arm/configs/csb637_defconfig ---- linux-2.6.20.4-0rig/arch/arm/configs/csb637_defconfig 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/arm/configs/csb637_defconfig 2007-03-24 16:39:15.000000000 +0100 -@@ -355,10 +355,12 @@ - # Mapping drivers for chip access - # - # CONFIG_MTD_COMPLEX_MAPPINGS is not set --# CONFIG_MTD_PHYSMAP is not set -+CONFIG_MTD_PHYSMAP=y -+CONFIG_MTD_PHYSMAP_START=0 -+CONFIG_MTD_PHYSMAP_LEN=0 -+CONFIG_MTD_PHYSMAP_BANKWIDTH=0 - # CONFIG_MTD_ARM_INTEGRATOR is not set - # CONFIG_MTD_PLATRAM is not set --CONFIG_MTD_CSB637=y - - # - # Self-contained MTD device drivers -diff -urN linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/at91rm9200.c linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/at91rm9200.c ---- linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/at91rm9200.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/at91rm9200.c 2007-03-24 16:39:15.000000000 +0100 -@@ -117,6 +117,36 @@ - .pmc_mask = 1 << AT91RM9200_ID_PIOD, - .type = CLK_TYPE_PERIPHERAL, - }; -+static struct clk tc0_clk = { -+ .name = "tc0_clk", -+ .pmc_mask = 1 << AT91RM9200_ID_TC0, -+ .type = CLK_TYPE_PERIPHERAL, -+}; -+static struct clk tc1_clk = { -+ .name = "tc1_clk", -+ .pmc_mask = 1 << AT91RM9200_ID_TC1, -+ .type = CLK_TYPE_PERIPHERAL, -+}; -+static struct clk tc2_clk = { -+ .name = "tc2_clk", -+ .pmc_mask = 1 << AT91RM9200_ID_TC2, -+ .type = CLK_TYPE_PERIPHERAL, -+}; -+static struct clk tc3_clk = { -+ .name = "tc3_clk", -+ .pmc_mask = 1 << AT91RM9200_ID_TC3, -+ .type = CLK_TYPE_PERIPHERAL, -+}; -+static struct clk tc4_clk = { -+ .name = "tc4_clk", -+ .pmc_mask = 1 << AT91RM9200_ID_TC4, -+ .type = CLK_TYPE_PERIPHERAL, -+}; -+static struct clk tc5_clk = { -+ .name = "tc5_clk", -+ .pmc_mask = 1 << AT91RM9200_ID_TC5, -+ .type = CLK_TYPE_PERIPHERAL, -+}; - - static struct clk *periph_clocks[] __initdata = { - &pioA_clk, -@@ -132,7 +162,12 @@ - &twi_clk, - &spi_clk, - // ssc 0 .. ssc2 -- // tc0 .. tc5 -+ &tc0_clk, -+ &tc1_clk, -+ &tc2_clk, -+ &tc3_clk, -+ &tc4_clk, -+ &tc5_clk, - &ohci_clk, - ðer_clk, - // irq0 .. irq6 -diff -urN linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/at91rm9200_devices.c linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/at91rm9200_devices.c ---- linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/at91rm9200_devices.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/at91rm9200_devices.c 2007-03-24 16:39:15.000000000 +0100 -@@ -315,7 +315,7 @@ - .num_resources = ARRAY_SIZE(mmc_resources), - }; - --void __init at91_add_device_mmc(struct at91_mmc_data *data) -+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) - { - if (!data) - return; -@@ -361,7 +361,7 @@ - platform_device_register(&at91rm9200_mmc_device); - } - #else --void __init at91_add_device_mmc(struct at91_mmc_data *data) {} -+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {} - #endif - - -@@ -480,7 +480,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[] = { -@@ -497,7 +508,7 @@ - }; - - static struct platform_device at91rm9200_spi_device = { -- .name = "at91_spi", -+ .name = SPI_DEVNAME, - .id = 0, - .dev = { - .dma_mask = &spi_dmamask, -@@ -594,6 +605,10 @@ - - void __init at91_init_leds(u8 cpu_led, u8 timer_led) - { -+ /* Enable GPIO to access the LEDs */ -+ at91_set_gpio_output(cpu_led, 1); -+ at91_set_gpio_output(timer_led, 1); -+ - at91_leds_cpu = cpu_led; - at91_leds_timer = timer_led; - } -@@ -602,6 +617,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 - * -------------------------------------------------------------------- */ -diff -urN linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/at91rm9200_time.c linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/at91rm9200_time.c ---- linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/at91rm9200_time.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/at91rm9200_time.c 2007-03-24 16:39:15.000000000 +0100 -@@ -38,7 +38,8 @@ - * The ST_CRTR is updated asynchronously to the master clock. It is therefore - * necessary to read it twice (with the same value) to ensure accuracy. - */ --static inline unsigned long read_CRTR(void) { -+static inline unsigned long read_CRTR(void) -+{ - unsigned long x1, x2; - - do { -diff -urN linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/at91sam9260.c linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/at91sam9260.c ---- linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/at91sam9260.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/at91sam9260.c 2007-03-24 16:39:15.000000000 +0100 -@@ -14,6 +14,7 @@ - - #include <asm/mach/arch.h> - #include <asm/mach/map.h> -+#include <asm/arch/cpu.h> - #include <asm/arch/at91sam9260.h> - #include <asm/arch/at91_pmc.h> - #include <asm/arch/at91_rstc.h> -@@ -27,7 +28,11 @@ - .pfn = __phys_to_pfn(AT91_BASE_SYS), - .length = SZ_16K, - .type = MT_DEVICE, -- }, { -+ } -+}; -+ -+static struct map_desc at91sam9260_sram_desc[] __initdata = { -+ { - .virtual = AT91_IO_VIRT_BASE - AT91SAM9260_SRAM0_SIZE, - .pfn = __phys_to_pfn(AT91SAM9260_SRAM0_BASE), - .length = AT91SAM9260_SRAM0_SIZE, -@@ -37,7 +42,14 @@ - .pfn = __phys_to_pfn(AT91SAM9260_SRAM1_BASE), - .length = AT91SAM9260_SRAM1_SIZE, - .type = MT_DEVICE, -- }, -+ } -+}; -+ -+static struct map_desc at91sam9xe_sram_desc[] __initdata = { -+ { -+ .pfn = __phys_to_pfn(AT91SAM9XE_SRAM_BASE), -+ .type = MT_DEVICE, -+ } - }; - - /* -------------------------------------------------------------------- -@@ -107,13 +119,28 @@ - .pmc_mask = 1 << AT91SAM9260_ID_SPI1, - .type = CLK_TYPE_PERIPHERAL, - }; -+static struct clk tc0_clk = { -+ .name = "tc0_clk", -+ .pmc_mask = 1 << AT91SAM9260_ID_TC0, -+ .type = CLK_TYPE_PERIPHERAL, -+}; -+static struct clk tc1_clk = { -+ .name = "tc1_clk", -+ .pmc_mask = 1 << AT91SAM9260_ID_TC1, -+ .type = CLK_TYPE_PERIPHERAL, -+}; -+static struct clk tc2_clk = { -+ .name = "tc2_clk", -+ .pmc_mask = 1 << AT91SAM9260_ID_TC2, -+ .type = CLK_TYPE_PERIPHERAL, -+}; - static struct clk ohci_clk = { - .name = "ohci_clk", - .pmc_mask = 1 << AT91SAM9260_ID_UHP, - .type = CLK_TYPE_PERIPHERAL, - }; --static struct clk ether_clk = { -- .name = "ether_clk", -+static struct clk macb_clk = { -+ .name = "macb_clk", - .pmc_mask = 1 << AT91SAM9260_ID_EMAC, - .type = CLK_TYPE_PERIPHERAL, - }; -@@ -137,6 +164,21 @@ - .pmc_mask = 1 << AT91SAM9260_ID_US5, - .type = CLK_TYPE_PERIPHERAL, - }; -+static struct clk tc3_clk = { -+ .name = "tc3_clk", -+ .pmc_mask = 1 << AT91SAM9260_ID_TC3, -+ .type = CLK_TYPE_PERIPHERAL, -+}; -+static struct clk tc4_clk = { -+ .name = "tc4_clk", -+ .pmc_mask = 1 << AT91SAM9260_ID_TC4, -+ .type = CLK_TYPE_PERIPHERAL, -+}; -+static struct clk tc5_clk = { -+ .name = "tc5_clk", -+ .pmc_mask = 1 << AT91SAM9260_ID_TC5, -+ .type = CLK_TYPE_PERIPHERAL, -+}; - - static struct clk *periph_clocks[] __initdata = { - &pioA_clk, -@@ -152,14 +194,18 @@ - &spi0_clk, - &spi1_clk, - // ssc -- // tc0 .. tc2 -+ &tc0_clk, -+ &tc1_clk, -+ &tc2_clk, - &ohci_clk, -- ðer_clk, -+ &macb_clk, - &isi_clk, - &usart3_clk, - &usart4_clk, - &usart5_clk, -- // tc3 .. tc5 -+ &tc3_clk, -+ &tc4_clk, -+ &tc5_clk, - // irq0 .. irq2 - }; - -@@ -213,7 +259,7 @@ - - static void at91sam9260_reset(void) - { -- at91_sys_write(AT91_RSTC_CR, (0xA5 << 24) | AT91_RSTC_PROCRST | AT91_RSTC_PERRST); -+ at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST); - } - - -@@ -221,10 +267,36 @@ - * AT91SAM9260 processor initialization - * -------------------------------------------------------------------- */ - -+static void __init at91sam9xe_initialize(void) -+{ -+ unsigned long cidr, sram_size; -+ -+ cidr = at91_sys_read(AT91_DBGU_CIDR); -+ -+ switch (cidr & AT91_CIDR_SRAMSIZ) { -+ case AT91_CIDR_SRAMSIZ_32K: -+ sram_size = 2 * SZ_16K; -+ break; -+ case AT91_CIDR_SRAMSIZ_16K: -+ default: -+ sram_size = SZ_16K; -+ } -+ -+ at91sam9xe_sram_desc->virtual = AT91_IO_VIRT_BASE - sram_size; -+ at91sam9xe_sram_desc->length = sram_size; -+ -+ iotable_init(at91sam9xe_sram_desc, ARRAY_SIZE(at91sam9xe_sram_desc)); -+} -+ - void __init at91sam9260_initialize(unsigned long main_clock) - { - /* Map peripherals */ - iotable_init(at91sam9260_io_desc, ARRAY_SIZE(at91sam9260_io_desc)); -+ -+ if (cpu_is_at91sam9xe()) -+ at91sam9xe_initialize(); -+ else -+ iotable_init(at91sam9260_sram_desc, ARRAY_SIZE(at91sam9260_sram_desc)); - - at91_arch_reset = at91sam9260_reset; - at91_extern_irq = (1 << AT91SAM9260_ID_IRQ0) | (1 << AT91SAM9260_ID_IRQ1) -diff -urN linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/at91sam9260_devices.c linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/at91sam9260_devices.c ---- linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/at91sam9260_devices.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/at91sam9260_devices.c 2007-03-24 16:39:15.000000000 +0100 -@@ -128,7 +128,7 @@ - - #if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE) - static u64 eth_dmamask = 0xffffffffUL; --static struct eth_platform_data eth_data; -+static struct at91_eth_data eth_data; - - static struct resource eth_resources[] = { - [0] = { -@@ -155,7 +155,7 @@ - .num_resources = ARRAY_SIZE(eth_resources), - }; - --void __init at91_add_device_eth(struct eth_platform_data *data) -+void __init at91_add_device_eth(struct at91_eth_data *data) - { - if (!data) - return; -@@ -192,7 +192,7 @@ - platform_device_register(&at91sam9260_eth_device); - } - #else --void __init at91_add_device_eth(struct eth_platform_data *data) {} -+void __init at91_add_device_eth(struct at91_eth_data *data) {} - #endif - - -@@ -229,7 +229,7 @@ - .num_resources = ARRAY_SIZE(mmc_resources), - }; - --void __init at91_add_device_mmc(struct at91_mmc_data *data) -+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) - { - if (!data) - return; -@@ -275,7 +275,7 @@ - platform_device_register(&at91sam9260_mmc_device); - } - #else --void __init at91_add_device_mmc(struct at91_mmc_data *data) {} -+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {} - #endif - - -@@ -515,6 +515,10 @@ - - void __init at91_init_leds(u8 cpu_led, u8 timer_led) - { -+ /* Enable GPIO to access the LEDs */ -+ at91_set_gpio_output(cpu_led, 1); -+ at91_set_gpio_output(timer_led, 1); -+ - at91_leds_cpu = cpu_led; - at91_leds_timer = timer_led; - } -@@ -523,6 +527,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 - * -------------------------------------------------------------------- */ -diff -urN linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/at91sam9261.c linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/at91sam9261.c ---- linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/at91sam9261.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/at91sam9261.c 2007-03-24 16:39:15.000000000 +0100 -@@ -97,6 +97,21 @@ - .pmc_mask = 1 << AT91SAM9261_ID_SPI1, - .type = CLK_TYPE_PERIPHERAL, - }; -+static struct clk tc0_clk = { -+ .name = "tc0_clk", -+ .pmc_mask = 1 << AT91SAM9261_ID_TC0, -+ .type = CLK_TYPE_PERIPHERAL, -+}; -+static struct clk tc1_clk = { -+ .name = "tc1_clk", -+ .pmc_mask = 1 << AT91SAM9261_ID_TC1, -+ .type = CLK_TYPE_PERIPHERAL, -+}; -+static struct clk tc2_clk = { -+ .name = "tc2_clk", -+ .pmc_mask = 1 << AT91SAM9261_ID_TC2, -+ .type = CLK_TYPE_PERIPHERAL, -+}; - static struct clk ohci_clk = { - .name = "ohci_clk", - .pmc_mask = 1 << AT91SAM9261_ID_UHP, -@@ -121,7 +136,9 @@ - &spi0_clk, - &spi1_clk, - // ssc 0 .. ssc2 -- // tc0 .. tc2 -+ &tc0_clk, -+ &tc1_clk, -+ &tc2_clk, - &ohci_clk, - &lcdc_clk, - // irq0 .. irq2 -@@ -208,7 +225,7 @@ - - static void at91sam9261_reset(void) - { -- at91_sys_write(AT91_RSTC_CR, (0xA5 << 24) | AT91_RSTC_PROCRST | AT91_RSTC_PERRST); -+ at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST); - } - - -diff -urN linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/at91sam9261_devices.c linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/at91sam9261_devices.c ---- linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/at91sam9261_devices.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/at91sam9261_devices.c 2007-03-24 16:39:15.000000000 +0100 -@@ -14,6 +14,9 @@ - #include <asm/mach/map.h> - - #include <linux/platform_device.h> -+#include <linux/fb.h> -+ -+#include <video/atmel_lcdc.h> - - #include <asm/arch/board.h> - #include <asm/arch/gpio.h> -@@ -159,7 +162,7 @@ - .num_resources = ARRAY_SIZE(mmc_resources), - }; - --void __init at91_add_device_mmc(struct at91_mmc_data *data) -+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) - { - if (!data) - return; -@@ -192,7 +195,7 @@ - platform_device_register(&at91sam9261_mmc_device); - } - #else --void __init at91_add_device_mmc(struct at91_mmc_data *data) {} -+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {} - #endif - - -@@ -345,7 +348,7 @@ - .num_resources = ARRAY_SIZE(spi0_resources), - }; - --static const unsigned spi0_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PA5, AT91_PIN_PA6 }; -+static const unsigned spi0_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PA28, AT91_PIN_PA6 }; - - static struct resource spi1_resources[] = { - [0] = { -@@ -430,9 +433,9 @@ - * LCD Controller - * -------------------------------------------------------------------- */ - --#if defined(CONFIG_FB_AT91) || defined(CONFIG_FB_AT91_MODULE) -+#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE) - static u64 lcdc_dmamask = 0xffffffffUL; --static struct at91fb_info lcdc_data; -+static struct atmel_lcdfb_info lcdc_data; - - static struct resource lcdc_resources[] = { - [0] = { -@@ -455,18 +458,18 @@ - }; - - static struct platform_device at91_lcdc_device = { -- .name = "at91-fb", -- .id = 0, -- .dev = { -- .dma_mask = &lcdc_dmamask, -- .coherent_dma_mask = 0xffffffff, -- .platform_data = &lcdc_data, -+ .name = "atmel_lcdfb", -+ .id = 0, -+ .dev = { -+ .dma_mask = &lcdc_dmamask, -+ .coherent_dma_mask = 0xffffffff, -+ .platform_data = &lcdc_data, - }, - .resource = lcdc_resources, - .num_resources = ARRAY_SIZE(lcdc_resources), - }; - --void __init at91_add_device_lcdc(struct at91fb_info *data) -+void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) - { - if (!data) { - return; -@@ -499,7 +502,7 @@ - platform_device_register(&at91_lcdc_device); - } - #else --void __init at91_add_device_lcdc(struct at91fb_info *data) {} -+void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {} - #endif - - -@@ -513,6 +516,10 @@ - - void __init at91_init_leds(u8 cpu_led, u8 timer_led) - { -+ /* Enable GPIO to access the LEDs */ -+ at91_set_gpio_output(cpu_led, 1); -+ at91_set_gpio_output(timer_led, 1); -+ - at91_leds_cpu = cpu_led; - at91_leds_timer = timer_led; - } -@@ -521,6 +528,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 - * -------------------------------------------------------------------- */ -diff -urN linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/at91sam9263.c linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/at91sam9263.c ---- linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/at91sam9263.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/at91sam9263.c 2007-03-24 16:39:15.000000000 +0100 -@@ -0,0 +1,313 @@ -+/* -+ * arch/arm/mach-at91rm9200/at91sam9263.c -+ * -+ * Copyright (C) 2007 Atmel Corporation. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ */ -+ -+#include <linux/module.h> -+ -+#include <asm/mach/arch.h> -+#include <asm/mach/map.h> -+#include <asm/arch/at91sam9263.h> -+#include <asm/arch/at91_pmc.h> -+#include <asm/arch/at91_rstc.h> -+ -+#include "generic.h" -+#include "clock.h" -+ -+static struct map_desc at91sam9263_io_desc[] __initdata = { -+ { -+ .virtual = AT91_VA_BASE_SYS, -+ .pfn = __phys_to_pfn(AT91_BASE_SYS), -+ .length = SZ_16K, -+ .type = MT_DEVICE, -+ }, { -+ .virtual = AT91_IO_VIRT_BASE - AT91SAM9263_SRAM0_SIZE, -+ .pfn = __phys_to_pfn(AT91SAM9263_SRAM0_BASE), -+ .length = AT91SAM9263_SRAM0_SIZE, -+ .type = MT_DEVICE, -+ }, { -+ .virtual = AT91_IO_VIRT_BASE - AT91SAM9263_SRAM0_SIZE - AT91SAM9263_SRAM1_SIZE, -+ .pfn = __phys_to_pfn(AT91SAM9263_SRAM1_BASE), -+ .length = AT91SAM9263_SRAM1_SIZE, -+ .type = MT_DEVICE, -+ }, -+}; -+ -+/* -------------------------------------------------------------------- -+ * Clocks -+ * -------------------------------------------------------------------- */ -+ -+/* -+ * The peripheral clocks. -+ */ -+static struct clk pioA_clk = { -+ .name = "pioA_clk", -+ .pmc_mask = 1 << AT91SAM9263_ID_PIOA, -+ .type = CLK_TYPE_PERIPHERAL, -+}; -+static struct clk pioB_clk = { -+ .name = "pioB_clk", -+ .pmc_mask = 1 << AT91SAM9263_ID_PIOB, -+ .type = CLK_TYPE_PERIPHERAL, -+}; -+static struct clk pioCDE_clk = { -+ .name = "pioCDE_clk", -+ .pmc_mask = 1 << AT91SAM9263_ID_PIOCDE, -+ .type = CLK_TYPE_PERIPHERAL, -+}; -+static struct clk usart0_clk = { -+ .name = "usart0_clk", -+ .pmc_mask = 1 << AT91SAM9263_ID_US0, -+ .type = CLK_TYPE_PERIPHERAL, -+}; -+static struct clk usart1_clk = { -+ .name = "usart1_clk", -+ .pmc_mask = 1 << AT91SAM9263_ID_US1, -+ .type = CLK_TYPE_PERIPHERAL, -+}; -+static struct clk usart2_clk = { -+ .name = "usart2_clk", -+ .pmc_mask = 1 << AT91SAM9263_ID_US2, -+ .type = CLK_TYPE_PERIPHERAL, -+}; -+static struct clk mmc0_clk = { -+ .name = "mci0_clk", -+ .pmc_mask = 1 << AT91SAM9263_ID_MCI0, -+ .type = CLK_TYPE_PERIPHERAL, -+}; -+static struct clk mmc1_clk = { -+ .name = "mci1_clk", -+ .pmc_mask = 1 << AT91SAM9263_ID_MCI1, -+ .type = CLK_TYPE_PERIPHERAL, -+}; -+static struct clk twi_clk = { -+ .name = "twi_clk", -+ .pmc_mask = 1 << AT91SAM9263_ID_TWI, -+ .type = CLK_TYPE_PERIPHERAL, -+}; -+static struct clk spi0_clk = { -+ .name = "spi0_clk", -+ .pmc_mask = 1 << AT91SAM9263_ID_SPI0, -+ .type = CLK_TYPE_PERIPHERAL, -+}; -+static struct clk spi1_clk = { -+ .name = "spi1_clk", -+ .pmc_mask = 1 << AT91SAM9263_ID_SPI1, -+ .type = CLK_TYPE_PERIPHERAL, -+}; -+static struct clk tcb_clk = { -+ .name = "tcb_clk", -+ .pmc_mask = 1 << AT91SAM9263_ID_TCB, -+ .type = CLK_TYPE_PERIPHERAL, -+}; -+static struct clk macb_clk = { -+ .name = "macb_clk", -+ .pmc_mask = 1 << AT91SAM9263_ID_EMAC, -+ .type = CLK_TYPE_PERIPHERAL, -+}; -+static struct clk udc_clk = { -+ .name = "udc_clk", -+ .pmc_mask = 1 << AT91SAM9263_ID_UDP, -+ .type = CLK_TYPE_PERIPHERAL, -+}; -+static struct clk isi_clk = { -+ .name = "isi_clk", -+ .pmc_mask = 1 << AT91SAM9263_ID_ISI, -+ .type = CLK_TYPE_PERIPHERAL, -+}; -+static struct clk lcdc_clk = { -+ .name = "lcdc_clk", -+ .pmc_mask = 1 << AT91SAM9263_ID_LCDC, -+ .type = CLK_TYPE_PERIPHERAL, -+}; -+static struct clk ohci_clk = { -+ .name = "ohci_clk", -+ .pmc_mask = 1 << AT91SAM9263_ID_UHP, -+ .type = CLK_TYPE_PERIPHERAL, -+}; -+ -+static struct clk *periph_clocks[] __initdata = { -+ &pioA_clk, -+ &pioB_clk, -+ &pioCDE_clk, -+ &usart0_clk, -+ &usart1_clk, -+ &usart2_clk, -+ &mmc0_clk, -+ &mmc1_clk, -+ // can -+ &twi_clk, -+ &spi0_clk, -+ &spi1_clk, -+ // ssc0 .. ssc1 -+ // ac97 -+ &tcb_clk, -+ // pwmc -+ &macb_clk, -+ // 2dge -+ &udc_clk, -+ &isi_clk, -+ &lcdc_clk, -+ // dma -+ &ohci_clk, -+ // irq0 .. irq1 -+}; -+ -+/* -+ * The four programmable clocks. -+ * You must configure pin multiplexing to bring these signals out. -+ */ -+static struct clk pck0 = { -+ .name = "pck0", -+ .pmc_mask = AT91_PMC_PCK0, -+ .type = CLK_TYPE_PROGRAMMABLE, -+ .id = 0, -+}; -+static struct clk pck1 = { -+ .name = "pck1", -+ .pmc_mask = AT91_PMC_PCK1, -+ .type = CLK_TYPE_PROGRAMMABLE, -+ .id = 1, -+}; -+static struct clk pck2 = { -+ .name = "pck2", -+ .pmc_mask = AT91_PMC_PCK2, -+ .type = CLK_TYPE_PROGRAMMABLE, -+ .id = 2, -+}; -+static struct clk pck3 = { -+ .name = "pck3", -+ .pmc_mask = AT91_PMC_PCK3, -+ .type = CLK_TYPE_PROGRAMMABLE, -+ .id = 3, -+}; -+ -+static void __init at91sam9263_register_clocks(void) -+{ -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(periph_clocks); i++) -+ clk_register(periph_clocks[i]); -+ -+ clk_register(&pck0); -+ clk_register(&pck1); -+ clk_register(&pck2); -+ clk_register(&pck3); -+} -+ -+/* -------------------------------------------------------------------- -+ * GPIO -+ * -------------------------------------------------------------------- */ -+ -+static struct at91_gpio_bank at91sam9263_gpio[] = { -+ { -+ .id = AT91SAM9263_ID_PIOA, -+ .offset = AT91_PIOA, -+ .clock = &pioA_clk, -+ }, { -+ .id = AT91SAM9263_ID_PIOB, -+ .offset = AT91_PIOB, -+ .clock = &pioB_clk, -+ }, { -+ .id = AT91SAM9263_ID_PIOCDE, -+ .offset = AT91_PIOC, -+ .clock = &pioCDE_clk, -+ }, { -+ .id = AT91SAM9263_ID_PIOCDE, -+ .offset = AT91_PIOD, -+ .clock = &pioCDE_clk, -+ }, { -+ .id = AT91SAM9263_ID_PIOCDE, -+ .offset = AT91_PIOE, -+ .clock = &pioCDE_clk, -+ } -+}; -+ -+static void at91sam9263_reset(void) -+{ -+ at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST); -+} -+ -+ -+/* -------------------------------------------------------------------- -+ * AT91SAM9263 processor initialization -+ * -------------------------------------------------------------------- */ -+ -+void __init at91sam9263_initialize(unsigned long main_clock) -+{ -+ /* Map peripherals */ -+ iotable_init(at91sam9263_io_desc, ARRAY_SIZE(at91sam9263_io_desc)); -+ -+ at91_arch_reset = at91sam9263_reset; -+ at91_extern_irq = (1 << AT91SAM9263_ID_IRQ0) | (1 << AT91SAM9263_ID_IRQ1); -+ -+ /* Init clock subsystem */ -+ at91_clock_init(main_clock); -+ -+ /* Register the processor-specific clocks */ -+ at91sam9263_register_clocks(); -+ -+ /* Register GPIO subsystem */ -+ at91_gpio_init(at91sam9263_gpio, 5); -+} -+ -+/* -------------------------------------------------------------------- -+ * Interrupt initialization -+ * -------------------------------------------------------------------- */ -+ -+/* -+ * The default interrupt priority levels (0 = lowest, 7 = highest). -+ */ -+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 */ -+ 0, -+ 0, -+ 6, /* USART 0 */ -+ 6, /* USART 1 */ -+ 6, /* 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 */ -+ 0, /* Timer Counter 0, 1 and 2 */ -+ 0, /* Pulse Width Modulation Controller */ -+ 3, /* Ethernet */ -+ 0, -+ 0, /* 2D Graphic Engine */ -+ 3, /* USB Device Port */ -+ 0, /* Image Sensor Interface */ -+ 3, /* LDC Controller */ -+ 0, /* DMA Controller */ -+ 0, -+ 3, /* USB Host port */ -+ 0, /* Advanced Interrupt Controller (IRQ0) */ -+ 0, /* Advanced Interrupt Controller (IRQ1) */ -+}; -+ -+void __init at91sam9263_init_interrupts(unsigned int priority[NR_AIC_IRQS]) -+{ -+ if (!priority) -+ priority = at91sam9263_default_irq_priority; -+ -+ /* Initialize the AIC interrupt controller */ -+ at91_aic_init(priority); -+ -+ /* Enable GPIO interrupts */ -+ at91_gpio_irq_setup(); -+} -diff -urN linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/at91sam9263_devices.c linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/at91sam9263_devices.c ---- linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/at91sam9263_devices.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/at91sam9263_devices.c 2007-03-24 16:39:15.000000000 +0100 -@@ -0,0 +1,918 @@ -+/* -+ * arch/arm/mach-at91rm9200/at91sam9263_devices.c -+ * -+ * Copyright (C) 2007 Atmel Corporation. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ */ -+#include <asm/mach/arch.h> -+#include <asm/mach/map.h> -+ -+#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> -+#include <asm/arch/at91sam926x_mc.h> -+#include <asm/arch/at91sam9263_matrix.h> -+ -+#include "generic.h" -+ -+#define SZ_512 0x00000200 -+#define SZ_256 0x00000100 -+#define SZ_16 0x00000010 -+ -+/* -------------------------------------------------------------------- -+ * USB Host -+ * -------------------------------------------------------------------- */ -+ -+#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) -+static u64 ohci_dmamask = 0xffffffffUL; -+static struct at91_usbh_data usbh_data; -+ -+static struct resource usbh_resources[] = { -+ [0] = { -+ .start = AT91SAM9263_UHP_BASE, -+ .end = AT91SAM9263_UHP_BASE + SZ_1M - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = AT91SAM9263_ID_UHP, -+ .end = AT91SAM9263_ID_UHP, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static struct platform_device at91_usbh_device = { -+ .name = "at91_ohci", -+ .id = -1, -+ .dev = { -+ .dma_mask = &ohci_dmamask, -+ .coherent_dma_mask = 0xffffffff, -+ .platform_data = &usbh_data, -+ }, -+ .resource = usbh_resources, -+ .num_resources = ARRAY_SIZE(usbh_resources), -+}; -+ -+void __init at91_add_device_usbh(struct at91_usbh_data *data) -+{ -+ int i; -+ -+ if (!data) -+ return; -+ -+ /* Enable VBus control for UHP ports */ -+ for (i = 0; i < data->ports; i++) { -+ if (data->vbus_pin[i]) -+ at91_set_gpio_output(data->vbus_pin[i], 0); -+ } -+ -+ usbh_data = *data; -+ platform_device_register(&at91_usbh_device); -+} -+#else -+void __init at91_add_device_usbh(struct at91_usbh_data *data) {} -+#endif -+ -+ -+/* -------------------------------------------------------------------- -+ * USB Device (Gadget) -+ * -------------------------------------------------------------------- */ -+ -+#ifdef CONFIG_USB_GADGET_AT91 -+static struct at91_udc_data udc_data; -+ -+static struct resource udc_resources[] = { -+ [0] = { -+ .start = AT91SAM9263_BASE_UDP, -+ .end = AT91SAM9263_BASE_UDP + SZ_16K - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = AT91SAM9263_ID_UDP, -+ .end = AT91SAM9263_ID_UDP, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static struct platform_device at91_udc_device = { -+ .name = "at91_udc", -+ .id = -1, -+ .dev = { -+ .platform_data = &udc_data, -+ }, -+ .resource = udc_resources, -+ .num_resources = ARRAY_SIZE(udc_resources), -+}; -+ -+void __init at91_add_device_udc(struct at91_udc_data *data) -+{ -+ if (!data) -+ return; -+ -+ if (data->vbus_pin) { -+ at91_set_gpio_input(data->vbus_pin, 0); -+ at91_set_deglitch(data->vbus_pin, 1); -+ } -+ -+ /* Pullup pin is handled internally by USB device peripheral */ -+ -+ udc_data = *data; -+ platform_device_register(&at91_udc_device); -+} -+#else -+void __init at91_add_device_udc(struct at91_udc_data *data) {} -+#endif -+ -+ -+/* -------------------------------------------------------------------- -+ * Ethernet -+ * -------------------------------------------------------------------- */ -+ -+#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE) -+static u64 eth_dmamask = 0xffffffffUL; -+static struct at91_eth_data eth_data; -+ -+static struct resource eth_resources[] = { -+ [0] = { -+ .start = AT91SAM9263_BASE_EMAC, -+ .end = AT91SAM9263_BASE_EMAC + SZ_16K - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = AT91SAM9263_ID_EMAC, -+ .end = AT91SAM9263_ID_EMAC, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static struct platform_device at91sam9263_eth_device = { -+ .name = "macb", -+ .id = -1, -+ .dev = { -+ .dma_mask = ð_dmamask, -+ .coherent_dma_mask = 0xffffffff, -+ .platform_data = ð_data, -+ }, -+ .resource = eth_resources, -+ .num_resources = ARRAY_SIZE(eth_resources), -+}; -+ -+void __init at91_add_device_eth(struct at91_eth_data *data) -+{ -+ if (!data) -+ return; -+ -+ if (data->phy_irq_pin) { -+ at91_set_gpio_input(data->phy_irq_pin, 0); -+ at91_set_deglitch(data->phy_irq_pin, 1); -+ } -+ -+ /* Pins used for MII and RMII */ -+ at91_set_A_periph(AT91_PIN_PE21, 0); /* ETXCK_EREFCK */ -+ at91_set_B_periph(AT91_PIN_PC25, 0); /* ERXDV */ -+ at91_set_A_periph(AT91_PIN_PE25, 0); /* ERX0 */ -+ at91_set_A_periph(AT91_PIN_PE26, 0); /* ERX1 */ -+ at91_set_A_periph(AT91_PIN_PE27, 0); /* ERXER */ -+ at91_set_A_periph(AT91_PIN_PE28, 0); /* ETXEN */ -+ at91_set_A_periph(AT91_PIN_PE23, 0); /* ETX0 */ -+ at91_set_A_periph(AT91_PIN_PE24, 0); /* ETX1 */ -+ at91_set_A_periph(AT91_PIN_PE30, 0); /* EMDIO */ -+ at91_set_A_periph(AT91_PIN_PE29, 0); /* EMDC */ -+ -+ if (!data->is_rmii) { -+ at91_set_A_periph(AT91_PIN_PE22, 0); /* ECRS */ -+ at91_set_B_periph(AT91_PIN_PC26, 0); /* ECOL */ -+ at91_set_B_periph(AT91_PIN_PC22, 0); /* ERX2 */ -+ at91_set_B_periph(AT91_PIN_PC23, 0); /* ERX3 */ -+ at91_set_B_periph(AT91_PIN_PC27, 0); /* ERXCK */ -+ at91_set_B_periph(AT91_PIN_PC20, 0); /* ETX2 */ -+ at91_set_B_periph(AT91_PIN_PC21, 0); /* ETX3 */ -+ at91_set_B_periph(AT91_PIN_PC24, 0); /* ETXER */ -+ } -+ -+ eth_data = *data; -+ platform_device_register(&at91sam9263_eth_device); -+} -+#else -+void __init at91_add_device_eth(struct at91_eth_data *data) {} -+#endif -+ -+ -+/* -------------------------------------------------------------------- -+ * MMC / SD -+ * -------------------------------------------------------------------- */ -+ -+#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE) -+static u64 mmc_dmamask = 0xffffffffUL; -+static struct at91_mmc_data mmc0_data, mmc1_data; -+ -+static struct resource mmc0_resources[] = { -+ [0] = { -+ .start = AT91SAM9263_BASE_MCI0, -+ .end = AT91SAM9263_BASE_MCI0 + SZ_16K - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = AT91SAM9263_ID_MCI0, -+ .end = AT91SAM9263_ID_MCI0, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static struct platform_device at91sam9263_mmc0_device = { -+ .name = "at91_mci", -+ .id = 0, -+ .dev = { -+ .dma_mask = &mmc_dmamask, -+ .coherent_dma_mask = 0xffffffff, -+ .platform_data = &mmc0_data, -+ }, -+ .resource = mmc0_resources, -+ .num_resources = ARRAY_SIZE(mmc0_resources), -+}; -+ -+static struct resource mmc1_resources[] = { -+ [0] = { -+ .start = AT91SAM9263_BASE_MCI1, -+ .end = AT91SAM9263_BASE_MCI1 + SZ_16K - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = AT91SAM9263_ID_MCI1, -+ .end = AT91SAM9263_ID_MCI1, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static struct platform_device at91sam9263_mmc1_device = { -+ .name = "at91_mci", -+ .id = 1, -+ .dev = { -+ .dma_mask = &mmc_dmamask, -+ .coherent_dma_mask = 0xffffffff, -+ .platform_data = &mmc1_data, -+ }, -+ .resource = mmc1_resources, -+ .num_resources = ARRAY_SIZE(mmc1_resources), -+}; -+ -+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) -+{ -+ if (!data) -+ return; -+ -+ /* input/irq */ -+ if (data->det_pin) { -+ at91_set_gpio_input(data->det_pin, 1); -+ at91_set_deglitch(data->det_pin, 1); -+ } -+ if (data->wp_pin) -+ at91_set_gpio_input(data->wp_pin, 1); -+ if (data->vcc_pin) -+ at91_set_gpio_output(data->vcc_pin, 0); -+ -+ if (mmc_id == 0) { /* MCI0 */ -+ /* CLK */ -+ at91_set_A_periph(AT91_PIN_PA12, 0); -+ -+ if (data->slot_b) { -+ /* CMD */ -+ at91_set_A_periph(AT91_PIN_PA16, 1); -+ -+ /* DAT0, maybe DAT1..DAT3 */ -+ at91_set_A_periph(AT91_PIN_PA17, 1); -+ if (data->wire4) { -+ at91_set_A_periph(AT91_PIN_PA18, 1); -+ at91_set_A_periph(AT91_PIN_PA19, 1); -+ at91_set_A_periph(AT91_PIN_PA20, 1); -+ } -+ } else { -+ /* CMD */ -+ at91_set_A_periph(AT91_PIN_PA1, 1); -+ -+ /* DAT0, maybe DAT1..DAT3 */ -+ at91_set_A_periph(AT91_PIN_PA0, 1); -+ if (data->wire4) { -+ at91_set_A_periph(AT91_PIN_PA3, 1); -+ at91_set_A_periph(AT91_PIN_PA4, 1); -+ at91_set_A_periph(AT91_PIN_PA5, 1); -+ } -+ } -+ -+ mmc0_data = *data; -+ at91_clock_associate("mci0_clk", &at91sam9263_mmc1_device.dev, "mci_clk"); -+ platform_device_register(&at91sam9263_mmc0_device); -+ } else { /* MCI1 */ -+ /* CLK */ -+ at91_set_A_periph(AT91_PIN_PA6, 0); -+ -+ if (data->slot_b) { -+ /* CMD */ -+ at91_set_A_periph(AT91_PIN_PA21, 1); -+ -+ /* DAT0, maybe DAT1..DAT3 */ -+ at91_set_A_periph(AT91_PIN_PA22, 1); -+ if (data->wire4) { -+ at91_set_A_periph(AT91_PIN_PA23, 1); -+ at91_set_A_periph(AT91_PIN_PA24, 1); -+ at91_set_A_periph(AT91_PIN_PA25, 1); -+ } -+ } else { -+ /* CMD */ -+ at91_set_A_periph(AT91_PIN_PA7, 1); -+ -+ /* DAT0, maybe DAT1..DAT3 */ -+ at91_set_A_periph(AT91_PIN_PA8, 1); -+ if (data->wire4) { -+ at91_set_A_periph(AT91_PIN_PA9, 1); -+ at91_set_A_periph(AT91_PIN_PA10, 1); -+ at91_set_A_periph(AT91_PIN_PA11, 1); -+ } -+ } -+ -+ mmc1_data = *data; -+ at91_clock_associate("mci1_clk", &at91sam9263_mmc1_device.dev, "mci_clk"); -+ platform_device_register(&at91sam9263_mmc1_device); -+ } -+} -+#else -+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {} -+#endif -+ -+ -+/* -------------------------------------------------------------------- -+ * NAND / SmartMedia -+ * -------------------------------------------------------------------- */ -+ -+#if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE) -+static struct at91_nand_data nand_data; -+ -+#define NAND_BASE AT91_CHIPSELECT_3 -+ -+static struct resource nand_resources[] = { -+ { -+ .start = NAND_BASE, -+ .end = NAND_BASE + SZ_256M - 1, -+ .flags = IORESOURCE_MEM, -+ } -+}; -+ -+static struct platform_device at91sam9263_nand_device = { -+ .name = "at91_nand", -+ .id = -1, -+ .dev = { -+ .platform_data = &nand_data, -+ }, -+ .resource = nand_resources, -+ .num_resources = ARRAY_SIZE(nand_resources), -+}; -+ -+void __init at91_add_device_nand(struct at91_nand_data *data) -+{ -+ unsigned long csa, mode; -+ -+ if (!data) -+ return; -+ -+ csa = at91_sys_read(AT91_MATRIX_EBI0CSA); -+ at91_sys_write(AT91_MATRIX_EBI0CSA, csa | AT91_MATRIX_EBI0_CS3A_SMC); -+ -+ /* set the bus interface characteristics */ -+ at91_sys_write(AT91_SMC_SETUP(3), AT91_SMC_NWESETUP_(0) | AT91_SMC_NCS_WRSETUP_(0) -+ | AT91_SMC_NRDSETUP_(0) | AT91_SMC_NCS_RDSETUP_(0)); -+ -+ at91_sys_write(AT91_SMC_PULSE(3), AT91_SMC_NWEPULSE_(3) | AT91_SMC_NCS_WRPULSE_(3) -+ | AT91_SMC_NRDPULSE_(3) | AT91_SMC_NCS_RDPULSE_(3)); -+ -+ at91_sys_write(AT91_SMC_CYCLE(3), AT91_SMC_NWECYCLE_(5) | AT91_SMC_NRDCYCLE_(5)); -+ -+ if (data->bus_width_16) -+ mode = AT91_SMC_DBW_16; -+ else -+ mode = AT91_SMC_DBW_8; -+ at91_sys_write(AT91_SMC_MODE(3), mode | AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_TDF_(2)); -+ -+ /* enable pin */ -+ if (data->enable_pin) -+ at91_set_gpio_output(data->enable_pin, 1); -+ -+ /* ready/busy pin */ -+ if (data->rdy_pin) -+ at91_set_gpio_input(data->rdy_pin, 1); -+ -+ /* card detect pin */ -+ if (data->det_pin) -+ at91_set_gpio_input(data->det_pin, 1); -+ -+ nand_data = *data; -+ platform_device_register(&at91sam9263_nand_device); -+} -+#else -+void __init at91_add_device_nand(struct at91_nand_data *data) {} -+#endif -+ -+ -+/* -------------------------------------------------------------------- -+ * TWI (i2c) -+ * -------------------------------------------------------------------- */ -+ -+#if defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE) -+ -+static struct resource twi_resources[] = { -+ [0] = { -+ .start = AT91SAM9263_BASE_TWI, -+ .end = AT91SAM9263_BASE_TWI + SZ_16K - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = AT91SAM9263_ID_TWI, -+ .end = AT91SAM9263_ID_TWI, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static struct platform_device at91sam9263_twi_device = { -+ .name = "at91_i2c", -+ .id = -1, -+ .resource = twi_resources, -+ .num_resources = ARRAY_SIZE(twi_resources), -+}; -+ -+void __init at91_add_device_i2c(void) -+{ -+ /* pins used for TWI interface */ -+ at91_set_A_periph(AT91_PIN_PB4, 0); /* TWD */ -+ at91_set_multi_drive(AT91_PIN_PB4, 1); -+ -+ at91_set_A_periph(AT91_PIN_PB5, 0); /* TWCK */ -+ at91_set_multi_drive(AT91_PIN_PB5, 1); -+ -+ platform_device_register(&at91sam9263_twi_device); -+} -+#else -+void __init at91_add_device_i2c(void) {} -+#endif -+ -+ -+/* -------------------------------------------------------------------- -+ * SPI -+ * -------------------------------------------------------------------- */ -+ -+#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE) -+static u64 spi_dmamask = 0xffffffffUL; -+ -+static struct resource spi0_resources[] = { -+ [0] = { -+ .start = AT91SAM9263_BASE_SPI0, -+ .end = AT91SAM9263_BASE_SPI0 + SZ_16K - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = AT91SAM9263_ID_SPI0, -+ .end = AT91SAM9263_ID_SPI0, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static struct platform_device at91sam9263_spi0_device = { -+ .name = "atmel_spi", -+ .id = 0, -+ .dev = { -+ .dma_mask = &spi_dmamask, -+ .coherent_dma_mask = 0xffffffff, -+ }, -+ .resource = spi0_resources, -+ .num_resources = ARRAY_SIZE(spi0_resources), -+}; -+ -+static const unsigned spi0_standard_cs[4] = { AT91_PIN_PA5, AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PB11 }; -+ -+static struct resource spi1_resources[] = { -+ [0] = { -+ .start = AT91SAM9263_BASE_SPI1, -+ .end = AT91SAM9263_BASE_SPI1 + SZ_16K - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = AT91SAM9263_ID_SPI1, -+ .end = AT91SAM9263_ID_SPI1, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static struct platform_device at91sam9263_spi1_device = { -+ .name = "atmel_spi", -+ .id = 1, -+ .dev = { -+ .dma_mask = &spi_dmamask, -+ .coherent_dma_mask = 0xffffffff, -+ }, -+ .resource = spi1_resources, -+ .num_resources = ARRAY_SIZE(spi1_resources), -+}; -+ -+static const unsigned spi1_standard_cs[4] = { AT91_PIN_PB15, AT91_PIN_PB16, AT91_PIN_PB17, AT91_PIN_PB18 }; -+ -+void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) -+{ -+ int i; -+ unsigned long cs_pin; -+ short enable_spi0 = 0; -+ short enable_spi1 = 0; -+ -+ /* Choose SPI chip-selects */ -+ for (i = 0; i < nr_devices; i++) { -+ if (devices[i].controller_data) -+ cs_pin = (unsigned long) devices[i].controller_data; -+ else if (devices[i].bus_num == 0) -+ cs_pin = spi0_standard_cs[devices[i].chip_select]; -+ else -+ cs_pin = spi1_standard_cs[devices[i].chip_select]; -+ -+ if (devices[i].bus_num == 0) -+ enable_spi0 = 1; -+ else -+ enable_spi1 = 1; -+ -+ /* enable chip-select pin */ -+ at91_set_gpio_output(cs_pin, 1); -+ -+ /* pass chip-select pin to driver */ -+ devices[i].controller_data = (void *) cs_pin; -+ } -+ -+ spi_register_board_info(devices, nr_devices); -+ -+ /* Configure SPI bus(es) */ -+ if (enable_spi0) { -+ at91_set_B_periph(AT91_PIN_PA0, 0); /* SPI0_MISO */ -+ at91_set_B_periph(AT91_PIN_PA1, 0); /* SPI0_MOSI */ -+ at91_set_B_periph(AT91_PIN_PA2, 0); /* SPI0_SPCK */ -+ -+ at91_clock_associate("spi0_clk", &at91sam9263_spi0_device.dev, "spi_clk"); -+ platform_device_register(&at91sam9263_spi0_device); -+ } -+ if (enable_spi1) { -+ at91_set_A_periph(AT91_PIN_PB12, 0); /* SPI1_MISO */ -+ at91_set_A_periph(AT91_PIN_PB13, 0); /* SPI1_MOSI */ -+ at91_set_A_periph(AT91_PIN_PB14, 0); /* SPI1_SPCK */ -+ -+ at91_clock_associate("spi1_clk", &at91sam9263_spi1_device.dev, "spi_clk"); -+ platform_device_register(&at91sam9263_spi1_device); -+ } -+} -+#else -+void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {} -+#endif -+ -+ -+/* -------------------------------------------------------------------- -+ * LCD Controller -+ * -------------------------------------------------------------------- */ -+ -+#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE) -+static u64 lcdc_dmamask = 0xffffffffUL; -+static struct atmel_lcdfb_info lcdc_data; -+ -+static struct resource lcdc_resources[] = { -+ [0] = { -+ .start = AT91SAM9263_LCDC_BASE, -+ .end = AT91SAM9263_LCDC_BASE + SZ_4K - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = AT91SAM9263_ID_LCDC, -+ .end = AT91SAM9263_ID_LCDC, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static struct platform_device at91_lcdc_device = { -+ .name = "atmel_lcdfb", -+ .id = 0, -+ .dev = { -+ .dma_mask = &lcdc_dmamask, -+ .coherent_dma_mask = 0xffffffff, -+ .platform_data = &lcdc_data, -+ }, -+ .resource = lcdc_resources, -+ .num_resources = ARRAY_SIZE(lcdc_resources), -+}; -+ -+void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) -+{ -+ if (!data) { -+ return; -+ } -+ -+ /* configure PIO for LCDC */ -+ at91_set_A_periph(AT91_PIN_PC1, 0); /* LCDHSYNC */ -+ at91_set_A_periph(AT91_PIN_PC2, 0); /* LCDDOTCK */ -+ at91_set_A_periph(AT91_PIN_PC3, 0); /* LCDDEN */ -+ at91_set_B_periph(AT91_PIN_PB9, 0); /* LCDCC */ -+ at91_set_A_periph(AT91_PIN_PC6, 0); /* LCDD2 */ -+ at91_set_A_periph(AT91_PIN_PC7, 0); /* LCDD3 */ -+ at91_set_A_periph(AT91_PIN_PC8, 0); /* LCDD4 */ -+ at91_set_A_periph(AT91_PIN_PC9, 0); /* LCDD5 */ -+ at91_set_A_periph(AT91_PIN_PC10, 0); /* LCDD6 */ -+ at91_set_A_periph(AT91_PIN_PC11, 0); /* LCDD7 */ -+ at91_set_A_periph(AT91_PIN_PC14, 0); /* LCDD10 */ -+ at91_set_A_periph(AT91_PIN_PC15, 0); /* LCDD11 */ -+ at91_set_A_periph(AT91_PIN_PC16, 0); /* LCDD12 */ -+ at91_set_B_periph(AT91_PIN_PC12, 0); /* LCDD13 */ -+ at91_set_A_periph(AT91_PIN_PC18, 0); /* LCDD14 */ -+ at91_set_A_periph(AT91_PIN_PC19, 0); /* LCDD15 */ -+ at91_set_A_periph(AT91_PIN_PC22, 0); /* LCDD18 */ -+ at91_set_A_periph(AT91_PIN_PC23, 0); /* LCDD19 */ -+ at91_set_A_periph(AT91_PIN_PC24, 0); /* LCDD20 */ -+ at91_set_B_periph(AT91_PIN_PC17, 0); /* LCDD21 */ -+ at91_set_A_periph(AT91_PIN_PC26, 0); /* LCDD22 */ -+ at91_set_A_periph(AT91_PIN_PC27, 0); /* LCDD23 */ -+ -+ lcdc_data = *data; -+ platform_device_register(&at91_lcdc_device); -+} -+#else -+void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {} -+#endif -+ -+ -+/* -------------------------------------------------------------------- -+ * LEDs -+ * -------------------------------------------------------------------- */ -+ -+#if defined(CONFIG_LEDS) -+u8 at91_leds_cpu; -+u8 at91_leds_timer; -+ -+void __init at91_init_leds(u8 cpu_led, u8 timer_led) -+{ -+ /* Enable GPIO to access the LEDs */ -+ at91_set_gpio_output(cpu_led, 1); -+ at91_set_gpio_output(timer_led, 1); -+ -+ at91_leds_cpu = cpu_led; -+ at91_leds_timer = timer_led; -+} -+#else -+void __init at91_init_leds(u8 cpu_led, u8 timer_led) {} -+#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 -+ * -------------------------------------------------------------------- */ -+ -+#if defined(CONFIG_SERIAL_ATMEL) -+ -+static struct resource dbgu_resources[] = { -+ [0] = { -+ .start = AT91_VA_BASE_SYS + AT91_DBGU, -+ .end = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = AT91_ID_SYS, -+ .end = AT91_ID_SYS, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static struct atmel_uart_data dbgu_data = { -+ .use_dma_tx = 0, -+ .use_dma_rx = 0, /* DBGU not capable of receive DMA */ -+ .regs = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU), -+}; -+ -+static struct platform_device at91sam9263_dbgu_device = { -+ .name = "atmel_usart", -+ .id = 0, -+ .dev = { -+ .platform_data = &dbgu_data, -+ .coherent_dma_mask = 0xffffffff, -+ }, -+ .resource = dbgu_resources, -+ .num_resources = ARRAY_SIZE(dbgu_resources), -+}; -+ -+static inline void configure_dbgu_pins(void) -+{ -+ at91_set_A_periph(AT91_PIN_PC30, 0); /* DRXD */ -+ at91_set_A_periph(AT91_PIN_PC31, 1); /* DTXD */ -+} -+ -+static struct resource uart0_resources[] = { -+ [0] = { -+ .start = AT91SAM9263_BASE_US0, -+ .end = AT91SAM9263_BASE_US0 + SZ_16K - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = AT91SAM9263_ID_US0, -+ .end = AT91SAM9263_ID_US0, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static struct atmel_uart_data uart0_data = { -+ .use_dma_tx = 1, -+ .use_dma_rx = 1, -+}; -+ -+static struct platform_device at91sam9263_uart0_device = { -+ .name = "atmel_usart", -+ .id = 1, -+ .dev = { -+ .platform_data = &uart0_data, -+ .coherent_dma_mask = 0xffffffff, -+ }, -+ .resource = uart0_resources, -+ .num_resources = ARRAY_SIZE(uart0_resources), -+}; -+ -+static inline void configure_usart0_pins(void) -+{ -+ at91_set_A_periph(AT91_PIN_PA26, 1); /* TXD0 */ -+ at91_set_A_periph(AT91_PIN_PA27, 0); /* RXD0 */ -+ at91_set_A_periph(AT91_PIN_PA28, 0); /* RTS0 */ -+ at91_set_A_periph(AT91_PIN_PA29, 0); /* CTS0 */ -+} -+ -+static struct resource uart1_resources[] = { -+ [0] = { -+ .start = AT91SAM9263_BASE_US1, -+ .end = AT91SAM9263_BASE_US1 + SZ_16K - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = AT91SAM9263_ID_US1, -+ .end = AT91SAM9263_ID_US1, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static struct atmel_uart_data uart1_data = { -+ .use_dma_tx = 1, -+ .use_dma_rx = 1, -+}; -+ -+static struct platform_device at91sam9263_uart1_device = { -+ .name = "atmel_usart", -+ .id = 2, -+ .dev = { -+ .platform_data = &uart1_data, -+ .coherent_dma_mask = 0xffffffff, -+ }, -+ .resource = uart1_resources, -+ .num_resources = ARRAY_SIZE(uart1_resources), -+}; -+ -+static inline void configure_usart1_pins(void) -+{ -+ at91_set_A_periph(AT91_PIN_PD0, 1); /* TXD1 */ -+ at91_set_A_periph(AT91_PIN_PD1, 0); /* RXD1 */ -+ at91_set_B_periph(AT91_PIN_PD7, 0); /* RTS1 */ -+ at91_set_B_periph(AT91_PIN_PD8, 0); /* CTS1 */ -+} -+ -+static struct resource uart2_resources[] = { -+ [0] = { -+ .start = AT91SAM9263_BASE_US2, -+ .end = AT91SAM9263_BASE_US2 + SZ_16K - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = AT91SAM9263_ID_US2, -+ .end = AT91SAM9263_ID_US2, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static struct atmel_uart_data uart2_data = { -+ .use_dma_tx = 1, -+ .use_dma_rx = 1, -+}; -+ -+static struct platform_device at91sam9263_uart2_device = { -+ .name = "atmel_usart", -+ .id = 3, -+ .dev = { -+ .platform_data = &uart2_data, -+ .coherent_dma_mask = 0xffffffff, -+ }, -+ .resource = uart2_resources, -+ .num_resources = ARRAY_SIZE(uart2_resources), -+}; -+ -+static inline void configure_usart2_pins(void) -+{ -+ at91_set_A_periph(AT91_PIN_PD2, 1); /* TXD2 */ -+ at91_set_A_periph(AT91_PIN_PD3, 0); /* RXD2 */ -+ at91_set_B_periph(AT91_PIN_PD5, 0); /* RTS2 */ -+ at91_set_B_periph(AT91_PIN_PD6, 0); /* CTS2 */ -+} -+ -+struct platform_device *at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */ -+struct platform_device *atmel_default_console_device; /* the serial console device */ -+ -+void __init at91_init_serial(struct at91_uart_config *config) -+{ -+ int i; -+ -+ /* Fill in list of supported UARTs */ -+ for (i = 0; i < config->nr_tty; i++) { -+ switch (config->tty_map[i]) { -+ case 0: -+ configure_usart0_pins(); -+ at91_uarts[i] = &at91sam9263_uart0_device; -+ at91_clock_associate("usart0_clk", &at91sam9263_uart0_device.dev, "usart"); -+ break; -+ case 1: -+ configure_usart1_pins(); -+ at91_uarts[i] = &at91sam9263_uart1_device; -+ at91_clock_associate("usart1_clk", &at91sam9263_uart1_device.dev, "usart"); -+ break; -+ case 2: -+ configure_usart2_pins(); -+ at91_uarts[i] = &at91sam9263_uart2_device; -+ at91_clock_associate("usart2_clk", &at91sam9263_uart2_device.dev, "usart"); -+ break; -+ case 3: -+ configure_dbgu_pins(); -+ at91_uarts[i] = &at91sam9263_dbgu_device; -+ at91_clock_associate("mck", &at91sam9263_dbgu_device.dev, "usart"); -+ break; -+ default: -+ continue; -+ } -+ at91_uarts[i]->id = i; /* update ID number to mapped ID */ -+ } -+ -+ /* Set serial console device */ -+ if (config->console_tty < ATMEL_MAX_UART) -+ atmel_default_console_device = at91_uarts[config->console_tty]; -+ if (!atmel_default_console_device) -+ printk(KERN_INFO "AT91: No default serial console defined.\n"); -+} -+ -+void __init at91_add_device_serial(void) -+{ -+ int i; -+ -+ for (i = 0; i < ATMEL_MAX_UART; i++) { -+ if (at91_uarts[i]) -+ platform_device_register(at91_uarts[i]); -+ } -+} -+#else -+void __init at91_init_serial(struct at91_uart_config *config) {} -+void __init at91_add_device_serial(void) {} -+#endif -+ -+ -+/* -------------------------------------------------------------------- */ -+/* -+ * These devices are always present and don't need any board-specific -+ * setup. -+ */ -+static int __init at91_add_standard_devices(void) -+{ -+ return 0; -+} -+ -+arch_initcall(at91_add_standard_devices); -diff -urN linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/at91sam926x_time.c linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/at91sam926x_time.c ---- linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/at91sam926x_time.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/at91sam926x_time.c 2007-03-24 16:39:15.000000000 +0100 -@@ -30,7 +30,6 @@ - * Returns number of microseconds since last timer interrupt. Note that interrupts - * will have been disabled by do_gettimeofday() - * 'LATCH' is hwclock ticks (see CLOCK_TICK_RATE in timex.h) per jiffy. -- * 'tick' is usecs per jiffy (linux/timex.h). - */ - static unsigned long at91sam926x_gettimeoffset(void) - { -@@ -39,7 +38,7 @@ - - elapsed = (PIT_PICNT(t) * LATCH) + PIT_CPIV(t); /* hardware clock cycles */ - -- return (unsigned long)(elapsed * 1000000) / LATCH; -+ return (unsigned long)(elapsed * jiffies_to_usecs(1)) / LATCH; - } - - /* -diff -urN linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/board-carmeva.c linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/board-carmeva.c ---- linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/board-carmeva.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/board-carmeva.c 2007-03-24 16:39:15.000000000 +0100 -@@ -134,7 +134,7 @@ - /* Compact Flash */ - // at91_add_device_cf(&carmeva_cf_data); - /* MMC */ -- at91_add_device_mmc(&carmeva_mmc_data); -+ at91_add_device_mmc(0, &carmeva_mmc_data); - } - - MACHINE_START(CARMEVA, "Carmeva") -diff -urN linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/board-csb337.c linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/board-csb337.c ---- linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/board-csb337.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/board-csb337.c 2007-03-24 16:39:15.000000000 +0100 -@@ -24,6 +24,8 @@ - #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> - #include <asm/setup.h> -@@ -58,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); -@@ -112,6 +115,91 @@ - }, - }; - -+#define CSB_FLASH_BASE AT91_CHIPSELECT_0 -+#define CSB_FLASH_SIZE 0x800000 -+ -+static struct mtd_partition csb_flash_partitions[] = { -+ { -+ .name = "uMON flash", -+ .offset = 0, -+ .size = MTDPART_SIZ_FULL, -+ .mask_flags = MTD_WRITEABLE, /* read only */ -+ } -+}; -+ -+static struct physmap_flash_data csb_flash_data = { -+ .width = 2, -+ .parts = csb_flash_partitions, -+ .nr_parts = ARRAY_SIZE(csb_flash_partitions), -+}; -+ -+static struct resource csb_flash_resources[] = { -+ { -+ .start = CSB_FLASH_BASE, -+ .end = CSB_FLASH_BASE + CSB_FLASH_SIZE - 1, -+ .flags = IORESOURCE_MEM, -+ } -+}; -+ -+static struct platform_device csb_flash = { -+ .name = "physmap-flash", -+ .id = 0, -+ .dev = { -+ .platform_data = &csb_flash_data, -+ }, -+ .resource = csb_flash_resources, -+ .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 -+#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 -+ /* there's also SW2 at PA21, GPIO or TIOA2 */ -+} -+#else -+static void __init csb300_switches(void) {} -+#endif -+ - static void __init csb337_board_init(void) - { - /* Serial */ -@@ -130,7 +218,13 @@ - /* SPI */ - at91_add_device_spi(csb337_spi_devices, ARRAY_SIZE(csb337_spi_devices)); - /* MMC */ -- at91_add_device_mmc(&csb337_mmc_data); -+ 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") -diff -urN linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/board-csb637.c linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/board-csb637.c ---- linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/board-csb637.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/board-csb637.c 2007-03-24 16:39:15.000000000 +0100 -@@ -23,6 +23,7 @@ - #include <linux/mm.h> - #include <linux/module.h> - #include <linux/platform_device.h> -+#include <linux/mtd/physmap.h> - - #include <asm/hardware.h> - #include <asm/setup.h> -@@ -81,6 +82,42 @@ - .pullup_pin = AT91_PIN_PB1, - }; - -+#define CSB_FLASH_BASE AT91_CHIPSELECT_0 -+#define CSB_FLASH_SIZE 0x1000000 -+ -+static struct mtd_partition csb_flash_partitions[] = { -+ { -+ .name = "uMON flash", -+ .offset = 0, -+ .size = MTDPART_SIZ_FULL, -+ .mask_flags = MTD_WRITEABLE, /* read only */ -+ } -+}; -+ -+static struct physmap_flash_data csb_flash_data = { -+ .width = 2, -+ .parts = csb_flash_partitions, -+ .nr_parts = ARRAY_SIZE(csb_flash_partitions), -+}; -+ -+static struct resource csb_flash_resources[] = { -+ { -+ .start = CSB_FLASH_BASE, -+ .end = CSB_FLASH_BASE + CSB_FLASH_SIZE - 1, -+ .flags = IORESOURCE_MEM, -+ } -+}; -+ -+static struct platform_device csb_flash = { -+ .name = "physmap-flash", -+ .id = 0, -+ .dev = { -+ .platform_data = &csb_flash_data, -+ }, -+ .resource = csb_flash_resources, -+ .num_resources = ARRAY_SIZE(csb_flash_resources), -+}; -+ - static void __init csb637_board_init(void) - { - /* Serial */ -@@ -95,6 +132,8 @@ - at91_add_device_i2c(); - /* SPI */ - at91_add_device_spi(NULL, 0); -+ /* NOR flash */ -+ platform_device_register(&csb_flash); - } - - MACHINE_START(CSB637, "Cogent CSB637") -diff -urN linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/board-dk.c linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/board-dk.c ---- linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/board-dk.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/board-dk.c 2007-03-24 16:39:15.000000000 +0100 -@@ -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 -+ - 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) - { -@@ -194,14 +380,16 @@ - #else - /* MMC */ - at91_set_gpio_output(AT91_PIN_PB7, 1); /* this MMC card slot can optionally use SPI signaling (CS3). */ -- at91_add_device_mmc(&dk_mmc_data); -+ at91_add_device_mmc(0, &dk_mmc_data); - #endif - /* NAND */ - 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") -diff -urN linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/board-eb9200.c linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/board-eb9200.c ---- linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/board-eb9200.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/board-eb9200.c 2007-03-24 16:39:15.000000000 +0100 -@@ -109,7 +109,7 @@ - at91_add_device_spi(NULL, 0); - /* MMC */ - /* only supports 1 or 4 bit interface, not wired through to SPI */ -- at91_add_device_mmc(&eb9200_mmc_data); -+ at91_add_device_mmc(0, &eb9200_mmc_data); - } - - MACHINE_START(ATEB9200, "Embest ATEB9200") -diff -urN linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/board-ek.c linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/board-ek.c ---- linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/board-ek.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/board-ek.c 2007-03-24 16:39:15.000000000 +0100 -@@ -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 s1d13xxxfb_pdata ek_s1dfb_pdata = { -+ .initregs = ek_s1dfb_initregs, -+ .initregssize = ARRAY_SIZE(ek_s1dfb_initregs), -+ .platform_init_video = ek_init_video, -+}; -+ -+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 = { -+ .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 __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) - { -@@ -154,12 +347,14 @@ - #else - /* MMC */ - at91_set_gpio_output(AT91_PIN_PB22, 1); /* this MMC card slot can optionally use SPI signaling (CS3). */ -- at91_add_device_mmc(&ek_mmc_data); -+ at91_add_device_mmc(0, &ek_mmc_data); - #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") -diff -urN linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/board-kb9202.c linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/board-kb9202.c ---- linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/board-kb9202.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/board-kb9202.c 2007-03-24 16:39:15.000000000 +0100 -@@ -122,7 +122,7 @@ - /* USB Device */ - at91_add_device_udc(&kb9202_udc_data); - /* MMC */ -- at91_add_device_mmc(&kb9202_mmc_data); -+ at91_add_device_mmc(0, &kb9202_mmc_data); - /* I2C */ - at91_add_device_i2c(); - /* SPI */ -diff -urN linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/board-sam9260ek.c linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/board-sam9260ek.c ---- linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/board-sam9260ek.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/board-sam9260ek.c 2007-03-24 16:39:15.000000000 +0100 -@@ -1,5 +1,5 @@ - /* -- * linux/arch/arm/mach-at91rm9200/board-ek.c -+ * linux/arch/arm/mach-at91rm9200/board-sam9260ek.c - * - * Copyright (C) 2005 SAN People - * Copyright (C) 2006 Atmel -@@ -118,7 +118,7 @@ - /* - * MACB Ethernet device - */ --static struct __initdata eth_platform_data ek_macb_data = { -+static struct __initdata at91_eth_data ek_macb_data = { - .phy_irq_pin = AT91_PIN_PA7, - .is_rmii = 1, - }; -@@ -187,7 +187,7 @@ - /* Ethernet */ - at91_add_device_eth(&ek_macb_data); - /* MMC */ -- at91_add_device_mmc(&ek_mmc_data); -+ at91_add_device_mmc(0, &ek_mmc_data); - } - - MACHINE_START(AT91SAM9260EK, "Atmel AT91SAM9260-EK") -diff -urN linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/board-sam9261ek.c linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/board-sam9261ek.c ---- linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/board-sam9261ek.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/board-sam9261ek.c 2007-03-24 16:39:15.000000000 +0100 -@@ -1,5 +1,5 @@ - /* -- * linux/arch/arm/mach-at91rm9200/board-ek.c -+ * linux/arch/arm/mach-at91rm9200/board-sam9261ek.c - * - * Copyright (C) 2005 SAN People - * Copyright (C) 2006 Atmel -@@ -26,6 +26,11 @@ - #include <linux/platform_device.h> - #include <linux/spi/spi.h> - #include <linux/dm9000.h> -+#include <linux/spi/ads7846.h> -+#include <linux/fb.h> -+#include <linux/clk.h> -+ -+#include <video/atmel_lcdc.h> - - #include <asm/hardware.h> - #include <asm/setup.h> -@@ -148,6 +153,42 @@ - - - /* -+ * Touchscreen ads7843 -+ */ -+#if defined(CONFIG_TOUCHSCREEN_ADS7846) || defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE) -+ -+int ads7843_pendown_state(void) -+{ -+ return !at91_get_gpio_value(AT91_PIN_PC2); -+} -+ -+static struct ads7846_platform_data ads_info = { -+ .model = 7843, -+ .x_min = 150, .x_max = 3830, -+ .y_min = 190, .y_max = 3830, -+ .vref_delay_usecs = 100, -+ .x_plate_ohms = 450, -+ .y_plate_ohms = 250, -+ .pressure_max = 15000, -+ .debounce_max = 1, -+ .debounce_rep = 0, -+ .debounce_tol = (~0), -+ .get_pendown_state = ads7843_pendown_state, -+}; -+ -+void __init at91_add_device_ts(void) -+{ -+ /* Configure Interrupt 1 as external IRQ, with pullup */ -+ at91_set_B_periph(AT91_PIN_PC2, 1); /* IRQ0 */ -+ /* ts busy */ -+ at91_set_gpio_input(AT91_PIN_PA11, 1); -+} -+#else -+void __init at91_add_device_ts(void) {} -+#endif -+ -+ -+/* - * MCI (SD/MMC) - */ - static struct at91_mmc_data __initdata ek_mmc_data = { -@@ -204,6 +245,17 @@ - .max_speed_hz = 15 * 1000 * 1000, - .bus_num = 0, - }, -+#if defined(CONFIG_TOUCHSCREEN_ADS7846) || defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE) -+ { -+ .modalias = "ads7846", -+ .chip_select = 2, -+ .max_speed_hz = 125000 /* max sample rate at 3V */ -+ * 26, /* command + data + overhead */ -+ .bus_num = 0, -+ .platform_data = &ads_info, -+ .irq = AT91SAM9261_ID_IRQ0, -+ }, -+#endif - #if defined(CONFIG_MTD_AT91_DATAFLASH_CARD) - { /* DataFlash card - jumper (J12) configurable to CS3 or CS0 */ - .modalias = "mtd_dataflash", -@@ -222,6 +274,64 @@ - }; - - -+/* -+ * 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), -+ -+ .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 = "TX09D50VM1CCA", -+ -+ .modedb = at91_tft_vga_modes, -+ .modedb_len = ARRAY_SIZE(at91_tft_vga_modes), -+ .hfmin = 15000, -+ .hfmax = 64000, -+ .vfmin = 50, -+ .vfmax = 150, -+}; -+ -+/* Driver defaults */ -+#define AT91SAM9261_DEFAULT_LCDCON2 (ATMEL_LCDC_MEMOR_LITTLE \ -+ | ATMEL_LCDC_DISTYPE_TFT \ -+ | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE) -+ -+#define AT91SAM9261_DEFAULT_FB_FLAGS (FBINFO_DEFAULT \ -+ | FBINFO_PARTIAL_PAN_OK \ -+ | FBINFO_HWACCEL_XPAN \ -+ | FBINFO_HWACCEL_YPAN) -+ -+/* 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, -+ .default_flags = AT91SAM9261_DEFAULT_FB_FLAGS, -+ .power_control_pin = AT91_PIN_PA12, -+ .guard_time = 1, -+}; -+ -+#else -+static struct atmel_lcdfb_info __initdata ek_lcdc_data; -+#endif -+ -+ - static void __init ek_board_init(void) - { - /* Serial */ -@@ -243,8 +353,12 @@ - at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices)); - #else - /* MMC */ -- at91_add_device_mmc(&ek_mmc_data); -+ at91_add_device_mmc(0, &ek_mmc_data); - #endif -+ /* LCD Controller */ -+ at91_add_device_lcdc(&ek_lcdc_data); -+ /* Touchscreen */ -+ at91_add_device_ts(); - } - - MACHINE_START(AT91SAM9261EK, "Atmel AT91SAM9261-EK") -diff -urN linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/board-sam9263ek.c linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/board-sam9263ek.c ---- linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/board-sam9263ek.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/board-sam9263ek.c 2007-03-24 16:39:15.000000000 +0100 -@@ -0,0 +1,297 @@ -+/* -+ * linux/arch/arm/mach-at91rm9200/board-sam9263ek.c -+ * -+ * Copyright (C) 2005 SAN People -+ * Copyright (C) 2007 Atmel Corporation. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#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/ads7846.h> -+#include <linux/fb.h> -+#include <linux/clk.h> -+ -+#include <video/atmel_lcdc.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 .. 2 = USART0 .. USART2 -+ * 3 = DBGU -+ */ -+static struct at91_uart_config __initdata ek_uart_config = { -+ .console_tty = 0, /* ttyS0 */ -+ .nr_tty = 2, -+ .tty_map = { 3, 0, -1, -1, } /* ttyS0, ..., ttyS3 */ -+}; -+ -+static void __init ek_map_io(void) -+{ -+ /* Initialize processor: 16.367 MHz crystal */ -+ at91sam9263_initialize(16367660); -+ -+ /* Setup the serial ports and console */ -+ at91_init_serial(&ek_uart_config); -+} -+ -+static void __init ek_init_irq(void) -+{ -+ at91sam9263_init_interrupts(NULL); -+} -+ -+ -+/* -+ * USB Host port -+ */ -+static struct at91_usbh_data __initdata ek_usbh_data = { -+ .ports = 2, -+ .vbus_pin = { AT91_PIN_PA24, AT91_PIN_PA21 }, -+}; -+ -+/* -+ * USB Device port -+ */ -+static struct at91_udc_data __initdata ek_udc_data = { -+ .vbus_pin = AT91_PIN_PA25, -+ .pullup_pin = 0, /* pull-up driven by UDC */ -+}; -+ -+/* -+ * Touchscreen ads7843 -+ */ -+#if defined(CONFIG_TOUCHSCREEN_ADS7846) || defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE) -+ -+int ads7843_pendown_state(void) -+{ -+ return !at91_get_gpio_value(AT91_PIN_PA15); -+} -+ -+static struct ads7846_platform_data ads_info = { -+ .model = 7843, -+ .x_min = 150, .x_max = 3830, -+ .y_min = 190, .y_max = 3830, -+ .vref_delay_usecs = 100, -+ .x_plate_ohms = 450, -+ .y_plate_ohms = 250, -+ .pressure_max = 15000, -+ .debounce_max = 1, -+ .debounce_rep = 0, -+ .debounce_tol = (~0), -+ .get_pendown_state = ads7843_pendown_state, -+}; -+ -+void __init at91_add_device_ts(void) -+{ -+ /* Configure Interrupt 1 as external IRQ, with pullup */ -+ at91_set_B_periph(AT91_PIN_PA15, 1); /* IRQ1 */ -+ /* ts busy */ -+ at91_set_gpio_input(AT91_PIN_PA31, 1); -+} -+#else -+void __init at91_add_device_ts(void) {} -+#endif -+ -+/* -+ * SPI devices. -+ */ -+static struct spi_board_info ek_spi_devices[] = { -+#if defined(CONFIG_MTD_AT91_DATAFLASH_CARD) -+ { /* DataFlash card */ -+ .modalias = "mtd_dataflash", -+ .chip_select = 0, -+ .max_speed_hz = 15 * 1000 * 1000, -+ .bus_num = 0, -+ }, -+#endif -+#if defined(CONFIG_TOUCHSCREEN_ADS7846) || defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE) -+ { -+ .modalias = "ads7846", -+ .chip_select = 3, -+ .max_speed_hz = 125000 /* max sample rate at 3V */ -+ * 26, /* command + data + overhead */ -+ .bus_num = 0, -+ .platform_data = &ads_info, -+ .irq = AT91SAM9263_ID_IRQ1, -+ }, -+#endif -+}; -+ -+/* -+ * MACB device -+ */ -+static struct __initdata at91_eth_data ek_macb_data = { -+ .is_rmii = 1, -+}; -+ -+/* -+ * MCI (SD/MMC) -+ */ -+static struct at91_mmc_data __initdata ek_mmc_data = { -+ .wire4 = 1, -+ .det_pin = AT91_PIN_PE18, -+ .wp_pin = AT91_PIN_PE19, -+// .vcc_pin = ... not connected -+}; -+ -+ -+/* -+ * NAND flash -+ */ -+static struct mtd_partition __initdata ek_nand_partition[] = { -+ { -+ .name = "Partition 1", -+ .offset = 0, -+ .size = 64 * 1024 * 1024, -+ }, -+ { -+ .name = "Partition 2", -+ .offset = 64 * 1024 * 1024, -+ .size = MTDPART_SIZ_FULL, -+ }, -+}; -+ -+static struct mtd_partition *nand_partitions(int size, int *num_partitions) -+{ -+ *num_partitions = ARRAY_SIZE(ek_nand_partition); -+ return ek_nand_partition; -+} -+ -+static struct at91_nand_data __initdata ek_nand_data = { -+ .ale = 21, -+ .cle = 22, -+// .det_pin = ... not connected -+ .rdy_pin = AT91_PIN_PA22, -+ .enable_pin = AT91_PIN_PD15, -+ .partition_info = nand_partitions, -+#if defined(CONFIG_MTD_NAND_AT91_BUSWIDTH_16) -+ .bus_width_16 = 1, -+#else -+ .bus_width_16 = 0, -+#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), -+ -+ .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, -+}; -+ -+/* Driver defaults */ -+#define AT91SAM9261_DEFAULT_LCDCON2 (ATMEL_LCDC_MEMOR_LITTLE \ -+ | ATMEL_LCDC_DISTYPE_TFT \ -+ | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE) -+ -+#define AT91SAM9261_DEFAULT_FB_FLAGS (FBINFO_DEFAULT \ -+ | FBINFO_PARTIAL_PAN_OK \ -+ | FBINFO_HWACCEL_XPAN \ -+ | FBINFO_HWACCEL_YPAN) -+ -+/* 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, -+ .default_flags = AT91SAM9261_DEFAULT_FB_FLAGS, -+ .power_control_pin = AT91_PIN_PD12, -+ .guard_time = 1, -+}; -+ -+#else -+static struct atmel_lcdfb_info __initdata ek_lcdc_data; -+#endif -+ -+ -+static void __init ek_board_init(void) -+{ -+ /* Serial */ -+ at91_add_device_serial(); -+ /* USB Host */ -+ at91_add_device_usbh(&ek_usbh_data); -+ /* USB Device */ -+ at91_add_device_udc(&ek_udc_data); -+ /* select SPI clk for Dataflash card slot */ -+ at91_set_gpio_output(AT91_PIN_PE20, 1); -+ /* SPI */ -+ at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices)); -+ /* MMC */ -+ at91_add_device_mmc(1, &ek_mmc_data); -+ /* MACB */ -+ at91_add_device_eth(&ek_macb_data); -+ /* NAND */ -+ at91_add_device_nand(&ek_nand_data); -+ /* LCD Controller */ -+ at91_add_device_lcdc(&ek_lcdc_data); -+ /* Touchscreen */ -+ at91_add_device_ts(); -+} -+ -+MACHINE_START(AT91SAM9263EK, "Atmel AT91SAM9263-EK") -+ /* Maintainer: Atmel */ -+ .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 = ek_map_io, -+ .init_irq = ek_init_irq, -+ .init_machine = ek_board_init, -+MACHINE_END -diff -urN linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/clock.c linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/clock.c ---- linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/clock.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/clock.c 2007-03-24 16:39:15.000000000 +0100 -@@ -375,6 +375,7 @@ - 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)); -@@ -525,27 +526,6 @@ - return 0; - } - --/* -- * Several unused clocks may be active. Turn them off. -- */ --static void __init at91_periphclk_reset(void) --{ -- unsigned long reg; -- struct clk *clk; -- -- reg = at91_sys_read(AT91_PMC_PCSR); -- -- list_for_each_entry(clk, &clocks, node) { -- if (clk->mode != pmc_periph_mode) -- continue; -- -- if (clk->users > 0) -- reg &= ~clk->pmc_mask; -- } -- -- at91_sys_write(AT91_PMC_PCDR, reg); --} -- - static struct clk *const standard_pmc_clocks[] __initdata = { - /* four primary clocks */ - &clk32k, -@@ -586,7 +566,7 @@ - pr_info("Clocks: PLLA overclocked, %ld MHz\n", plla.rate_hz / 1000000); - - /* -- * USB clock init: choose 48 MHz PLLB value, turn all clocks off, -+ * USB clock init: choose 48 MHz PLLB value, - * disable 48MHz clock during usb peripheral suspend. - * - * REVISIT: assumes MCK doesn't derive from PLLB! -@@ -596,16 +576,10 @@ - if (cpu_is_at91rm9200()) { - uhpck.pmc_mask = AT91RM9200_PMC_UHP; - udpck.pmc_mask = AT91RM9200_PMC_UDP; -- at91_sys_write(AT91_PMC_SCDR, AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP); - at91_sys_write(AT91_PMC_SCER, AT91RM9200_PMC_MCKUDP); -- } else if (cpu_is_at91sam9260()) { -+ } else if (cpu_is_at91sam9260() || cpu_is_at91sam9261() || cpu_is_at91sam9263()) { - uhpck.pmc_mask = AT91SAM926x_PMC_UHP; - udpck.pmc_mask = AT91SAM926x_PMC_UDP; -- at91_sys_write(AT91_PMC_SCDR, AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP); -- } else if (cpu_is_at91sam9261()) { -- uhpck.pmc_mask = (AT91SAM926x_PMC_UHP | AT91_PMC_HCK0); -- udpck.pmc_mask = AT91SAM926x_PMC_UDP; -- at91_sys_write(AT91_PMC_SCDR, AT91SAM926x_PMC_UHP | AT91_PMC_HCK0 | AT91SAM926x_PMC_UDP); - } - at91_sys_write(AT91_CKGR_PLLBR, 0); - -@@ -634,11 +608,34 @@ - (unsigned) main_clock / 1000000, - ((unsigned) main_clock % 1000000) / 1000); - -- /* disable all programmable clocks */ -- at91_sys_write(AT91_PMC_SCDR, AT91_PMC_PCK0 | AT91_PMC_PCK1 | AT91_PMC_PCK2 | AT91_PMC_PCK3); -+ return 0; -+} -+ -+/* -+ * Several unused clocks may be active. Turn them off. -+ */ -+static int __init at91_clock_reset(void) -+{ -+ unsigned long pcdr = 0; -+ unsigned long scdr = 0; -+ struct clk *clk; -+ -+ list_for_each_entry(clk, &clocks, node) { -+ if (clk->users > 0) -+ continue; -+ -+ if (clk->mode == pmc_periph_mode) -+ pcdr |= clk->pmc_mask; -+ -+ if (clk->mode == pmc_sys_mode) -+ scdr |= clk->pmc_mask; -+ -+ pr_debug("Clocks: disable unused %s\n", clk->name); -+ } - -- /* disable all other unused peripheral clocks */ -- at91_periphclk_reset(); -+ at91_sys_write(AT91_PMC_PCDR, pcdr); -+ at91_sys_write(AT91_PMC_SCDR, scdr); - - return 0; - } -+late_initcall(at91_clock_reset); -diff -urN linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/generic.h linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/generic.h ---- linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/generic.h 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/generic.h 2007-03-24 16:39:15.000000000 +0100 -@@ -12,11 +12,13 @@ - extern void __init at91rm9200_initialize(unsigned long main_clock, unsigned short banks); - extern void __init at91sam9260_initialize(unsigned long main_clock); - extern void __init at91sam9261_initialize(unsigned long main_clock); -+extern void __init at91sam9263_initialize(unsigned long main_clock); - - /* Interrupts */ - extern void __init at91rm9200_init_interrupts(unsigned int priority[]); - extern void __init at91sam9260_init_interrupts(unsigned int priority[]); - extern void __init at91sam9261_init_interrupts(unsigned int priority[]); -+extern void __init at91sam9263_init_interrupts(unsigned int priority[]); - extern void __init at91_aic_init(unsigned int priority[]); - - /* Timer */ -diff -urN linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/ics1523.c linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/ics1523.c ---- linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/ics1523.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/ics1523.c 2007-03-24 16:39:15.000000000 +0100 -@@ -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)); -+} -+ -+/* ----------------------------------------------------------------------------- -+ * Read a byte with TWI Interface from the Clock Generator ICS1523 -+ * ----------------------------------------------------------------------------- */ -+ -+static int at91_ics1523_ReadByte(unsigned char reg_address, unsigned char *data_in) -+{ -+ int Status, nb_trial; -+ -+ 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); -+ -+ /* 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); -+ } -+ -+ if (Status & AT91_TWI_TXCOMP) { -+ *data_in = (unsigned char) at91_twi_read(AT91_TWI_RHR); -+ return ICS1523_ACCESS_OK; -+ } -+ else -+ return ICS1523_ACCESS_ERROR; -+} -+ -+/* ----------------------------------------------------------------------------- -+ * 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; -+} -diff -urN linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/Kconfig linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/Kconfig ---- linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/Kconfig 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/Kconfig 2007-03-24 16:39:15.000000000 +0100 -@@ -9,11 +9,14 @@ - bool "AT91RM9200" - - config ARCH_AT91SAM9260 -- bool "AT91SAM9260" -+ bool "AT91SAM9260 or AT91SAM9XE" - - config ARCH_AT91SAM9261 - bool "AT91SAM9261" - -+config ARCH_AT91SAM9263 -+ bool "AT91SAM9263" -+ - endchoice - - # ---------------------------------------------------------- -@@ -90,13 +93,22 @@ - - if ARCH_AT91SAM9260 - --comment "AT91SAM9260 Board Type" -+comment "AT91SAM9260 Variants" -+ -+config ARCH_AT91SAM9260_SAM9XE -+ bool "AT91SAM9XE" -+ depends on ARCH_AT91SAM9260 -+ help -+ Select this if you are using Atmel's AT91SAM9XE System-on-Chip. -+ They are basicaly AT91SAM9260s with various sizes of embedded Flash. -+ -+comment "AT91SAM9260 / AT91SAM9XE Board Type" - - config MACH_AT91SAM9260EK -- bool "Atmel AT91SAM9260-EK Evaluation Kit" -+ bool "Atmel AT91SAM9260-EK / AT91SAM9XE Evaluation Kit" - depends on ARCH_AT91SAM9260 - help -- Select this if you are using Atmel's AT91SAM9260-EK Evaluation Kit. -+ 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> - - endif -@@ -118,21 +130,50 @@ - - # ---------------------------------------------------------- - -+if ARCH_AT91SAM9263 -+ -+comment "AT91SAM9263 Board Type" -+ -+config MACH_AT91SAM9263EK -+ bool "Atmel AT91SAM9263-EK Evaluation Kit" -+ depends on ARCH_AT91SAM9263 -+ help -+ Select this if you are using Atmel's AT91SAM9263-EK Evaluation Kit. -+ <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=4057> -+ -+endif -+ -+# ---------------------------------------------------------- -+ - comment "AT91 Board Options" - - config MTD_AT91_DATAFLASH_CARD - bool "Enable DataFlash Card support" -- depends on (ARCH_AT91RM9200DK || MACH_AT91RM9200EK || MACH_AT91SAM9260EK || MACH_AT91SAM9261EK) -+ depends on (ARCH_AT91RM9200DK || MACH_AT91RM9200EK || MACH_AT91SAM9260EK || MACH_AT91SAM9261EK || MACH_AT91SAM9263EK) - help - Enable support for the DataFlash card. - - config MTD_NAND_AT91_BUSWIDTH_16 - bool "Enable 16-bit data bus interface to NAND flash" -- depends on (MACH_AT91SAM9261EK || MACH_AT91SAM9260EK) -+ depends on (MACH_AT91SAM9261EK || MACH_AT91SAM9260EK || MACH_AT91SAM9263EK) - help - 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 -+ If you have a CSB300 connected to your CSB337, this lets -+ SW0 serve as a wakeup button. It uses IRQ0. -+ -+config CSB300_WAKE_SW1 -+ bool "CSB300 SW1 gpio wakeup" -+ depends on MACH_CSB337 && PM -+ help -+ If you have a CSB300 connected to your CSB337, this lets -+ SW1 serve as a wakeup button. It uses GPIO. -+ - # ---------------------------------------------------------- - - comment "AT91 Feature Selections" -@@ -143,6 +184,13 @@ - Select this if you need to program one or more of the PCK0..PCK3 - programmable clock outputs. - -+config AT91_SLOW_CLOCK -+ bool "Suspend-to-RAM uses slow clock mode (EXPERIMENTAL)" -+ depends on PM && EXPERIMENTAL -+ help -+ Select this if you wish to put the CPU into slow clock mode -+ while in the "Suspend to RAM" state, to save more power. -+ - endmenu - - endif -diff -urN linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/leds.c linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/leds.c ---- linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/leds.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/leds.c 2007-03-24 16:39:15.000000000 +0100 -@@ -86,10 +86,6 @@ - if (!at91_leds_timer || !at91_leds_cpu) - return -ENODEV; - -- /* Enable PIO to access the LEDs */ -- at91_set_gpio_output(at91_leds_timer, 1); -- at91_set_gpio_output(at91_leds_cpu, 1); -- - leds_event = at91_leds_event; - - leds_event(led_start); -diff -urN linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/Makefile linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/Makefile ---- linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/Makefile 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/Makefile 2007-03-24 16:39:15.000000000 +0100 -@@ -8,11 +8,13 @@ - obj- := - - obj-$(CONFIG_PM) += pm.o -+obj-$(CONFIG_AT91_SLOW_CLOCK) += pm_slowclock.o - - # CPU-specific support - obj-$(CONFIG_ARCH_AT91RM9200) += at91rm9200.o at91rm9200_time.o at91rm9200_devices.o - obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o - obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o -+obj-$(CONFIG_ARCH_AT91SAM9263) += at91sam9263.o at91sam926x_time.o at91sam9263_devices.o - - # AT91RM9200 board-specific support - obj-$(CONFIG_MACH_ONEARM) += board-1arm.o -@@ -31,6 +33,9 @@ - # AT91SAM9261 board-specific support - obj-$(CONFIG_MACH_AT91SAM9261EK) += board-sam9261ek.o - -+# AT91SAM9263 board-specific support -+obj-$(CONFIG_MACH_AT91SAM9263EK) += board-sam9263ek.o -+ - # LEDs support - led-$(CONFIG_ARCH_AT91RM9200DK) += leds.o - led-$(CONFIG_MACH_AT91RM9200EK) += leds.o -@@ -41,7 +46,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) -diff -urN linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/pm.c linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/pm.c ---- linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/pm.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/pm.c 2007-03-24 16:39:15.000000000 +0100 -@@ -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; -@@ -80,6 +81,8 @@ - #warning "Check SAM9260 USB clocks" - } else if (cpu_is_at91sam9261()) { - #warning "Check SAM9261 USB clocks" -+ } else if (cpu_is_at91sam9263()) { -+#warning "Check SAM9263 USB clocks" - } - - #ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS -@@ -205,16 +208,23 @@ - .enter = at91_pm_enter, - }; - -+#ifdef CONFIG_AT91_SLOW_CLOCK -+extern void at91rm9200_slow_clock(void); -+extern u32 at91rm9200_slow_clock_sz; -+#endif -+ - 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 -+ printk("AT91: Power Management\n"); - #endif - - /* Disable SDRAM low-power mode. Cannot be used with self-refresh. */ -diff -urN linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/pm_slowclock.S linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/pm_slowclock.S ---- linux-2.6.20.4-0rig/arch/arm/mach-at91rm9200/pm_slowclock.S 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/arm/mach-at91rm9200/pm_slowclock.S 2007-03-24 16:39:15.000000000 +0100 -@@ -0,0 +1,172 @@ -+/* -+ * arch/arm/mach-at91rm9200/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. -+ * -+ */ -+ -+#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 -diff -urN linux-2.6.20.4-0rig/arch/arm/mm/Kconfig linux-2.6.20.4-atmel/arch/arm/mm/Kconfig ---- linux-2.6.20.4-0rig/arch/arm/mm/Kconfig 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/arm/mm/Kconfig 2007-03-24 16:39:15.000000000 +0100 -@@ -171,8 +171,8 @@ - # ARM926T - config CPU_ARM926T - bool "Support ARM926T processor" -- depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 -- default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 -+ depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 || ARCH_AT91SAM9263 -+ default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 || ARCH_AT91SAM9263 - select CPU_32v5 - select CPU_ABRT_EV5TJ - select CPU_CACHE_VIVT -diff -urN linux-2.6.20.4-0rig/arch/avr32/boards/atstk1000/atstk1002.c linux-2.6.20.4-atmel/arch/avr32/boards/atstk1000/atstk1002.c ---- linux-2.6.20.4-0rig/arch/avr32/boards/atstk1000/atstk1002.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/avr32/boards/atstk1000/atstk1002.c 2007-03-24 16:42:29.000000000 +0100 -@@ -14,11 +14,17 @@ - #include <linux/platform_device.h> - #include <linux/string.h> - #include <linux/types.h> -+#include <linux/spi/spi.h> - - #include <asm/io.h> - #include <asm/setup.h> -+#include <asm/arch/at32ap7000.h> - #include <asm/arch/board.h> - #include <asm/arch/init.h> -+#include <asm/arch/portmux.h> -+ -+ -+#define SW2_DEFAULT /* MMCI and UART_A available */ - - struct eth_addr { - u8 addr[6]; -@@ -29,6 +35,20 @@ - static struct eth_platform_data __initdata eth_data[2]; - extern struct lcdc_platform_data atstk1000_fb0_data; - -+static struct spi_board_info spi0_board_info[] __initdata = { -+ { -+ /* QVGA display */ -+ .modalias = "ltv350qv", -+ .max_speed_hz = 16000000, -+ .chip_select = 1, -+ }, -+}; -+ -+static struct mci_platform_data __initdata mci0_data = { -+ .detect_pin = GPIO_PIN_NONE, -+ .wp_pin = GPIO_PIN_NONE, -+}; -+ - /* - * The next two functions should go away as the boot loader is - * supposed to initialize the macb address registers with a valid -@@ -86,25 +106,58 @@ - - void __init setup_board(void) - { -- at32_map_usart(1, 0); /* /dev/ttyS0 */ -- at32_map_usart(2, 1); /* /dev/ttyS1 */ -- at32_map_usart(3, 2); /* /dev/ttyS2 */ -+#ifdef SW2_DEFAULT -+ 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 */ - - at32_setup_serial_console(0); - } - - static int __init atstk1002_init(void) - { -+ /* -+ * ATSTK1000 uses 32-bit SDRAM interface. Reserve the -+ * SDRAM-specific pins so that nobody messes with them. -+ */ -+ at32_reserve_pin(GPIO_PIN_PE(0)); /* DATA[16] */ -+ at32_reserve_pin(GPIO_PIN_PE(1)); /* DATA[17] */ -+ at32_reserve_pin(GPIO_PIN_PE(2)); /* DATA[18] */ -+ at32_reserve_pin(GPIO_PIN_PE(3)); /* DATA[19] */ -+ at32_reserve_pin(GPIO_PIN_PE(4)); /* DATA[20] */ -+ at32_reserve_pin(GPIO_PIN_PE(5)); /* DATA[21] */ -+ at32_reserve_pin(GPIO_PIN_PE(6)); /* DATA[22] */ -+ at32_reserve_pin(GPIO_PIN_PE(7)); /* DATA[23] */ -+ at32_reserve_pin(GPIO_PIN_PE(8)); /* DATA[24] */ -+ at32_reserve_pin(GPIO_PIN_PE(9)); /* DATA[25] */ -+ at32_reserve_pin(GPIO_PIN_PE(10)); /* DATA[26] */ -+ at32_reserve_pin(GPIO_PIN_PE(11)); /* DATA[27] */ -+ at32_reserve_pin(GPIO_PIN_PE(12)); /* DATA[28] */ -+ at32_reserve_pin(GPIO_PIN_PE(13)); /* DATA[29] */ -+ at32_reserve_pin(GPIO_PIN_PE(14)); /* DATA[30] */ -+ at32_reserve_pin(GPIO_PIN_PE(15)); /* DATA[31] */ -+ at32_reserve_pin(GPIO_PIN_PE(26)); /* SDCS */ -+ - at32_add_system_devices(); - -+#ifdef SW2_DEFAULT - at32_add_device_usart(0); -+#else - at32_add_device_usart(1); -+#endif - at32_add_device_usart(2); - - set_hw_addr(at32_add_device_eth(0, ð_data[0])); - -- at32_add_device_spi(0); -+ at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info)); -+ at32_add_device_twi(0); -+ at32_add_device_mci(0, &mci0_data); - at32_add_device_lcdc(0, &atstk1000_fb0_data); -+ at32_add_device_usba(0); -+ at32_add_device_abdac(0); - - return 0; - } -diff -urN linux-2.6.20.4-0rig/arch/avr32/boards/atstk1000/Makefile linux-2.6.20.4-atmel/arch/avr32/boards/atstk1000/Makefile ---- linux-2.6.20.4-0rig/arch/avr32/boards/atstk1000/Makefile 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/avr32/boards/atstk1000/Makefile 2007-03-24 16:42:28.000000000 +0100 -@@ -1,2 +1,2 @@ --obj-y += setup.o spi.o flash.o -+obj-y += setup.o flash.o - obj-$(CONFIG_BOARD_ATSTK1002) += atstk1002.o -diff -urN linux-2.6.20.4-0rig/arch/avr32/boards/atstk1000/spi.c linux-2.6.20.4-atmel/arch/avr32/boards/atstk1000/spi.c ---- linux-2.6.20.4-0rig/arch/avr32/boards/atstk1000/spi.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/avr32/boards/atstk1000/spi.c 1970-01-01 01:00:00.000000000 +0100 -@@ -1,27 +0,0 @@ --/* -- * ATSTK1000 SPI devices -- * -- * Copyright (C) 2005 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. -- */ --#include <linux/device.h> --#include <linux/spi/spi.h> -- --static struct spi_board_info spi_board_info[] __initdata = { -- { -- .modalias = "ltv350qv", -- .max_speed_hz = 16000000, -- .bus_num = 0, -- .chip_select = 1, -- }, --}; -- --static int board_init_spi(void) --{ -- spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info)); -- return 0; --} --arch_initcall(board_init_spi); -diff -urN linux-2.6.20.4-0rig/arch/avr32/drivers/dw-dmac.c linux-2.6.20.4-atmel/arch/avr32/drivers/dw-dmac.c ---- linux-2.6.20.4-0rig/arch/avr32/drivers/dw-dmac.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/avr32/drivers/dw-dmac.c 2007-03-24 16:42:29.000000000 +0100 -@@ -0,0 +1,761 @@ -+/* -+ * Driver for the Synopsys DesignWare DMA Controller -+ * -+ * Copyright (C) 2005-2006 Atmel Corporation -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+#include <linux/clk.h> -+#include <linux/device.h> -+#include <linux/dma-mapping.h> -+#include <linux/dmapool.h> -+#include <linux/init.h> -+#include <linux/interrupt.h> -+#include <linux/module.h> -+#include <linux/platform_device.h> -+ -+#include <asm/dma-controller.h> -+#include <asm/io.h> -+ -+#include "dw-dmac.h" -+ -+#define DMAC_NR_CHANNELS 3 -+#define DMAC_MAX_BLOCKSIZE 4095 -+ -+enum { -+ CH_STATE_FREE = 0, -+ CH_STATE_ALLOCATED, -+ CH_STATE_BUSY, -+}; -+ -+struct dw_dma_lli { -+ dma_addr_t sar; -+ dma_addr_t dar; -+ dma_addr_t llp; -+ u32 ctllo; -+ u32 ctlhi; -+ u32 sstat; -+ u32 dstat; -+}; -+ -+struct dw_dma_block { -+ struct dw_dma_lli *lli_vaddr; -+ dma_addr_t lli_dma_addr; -+}; -+ -+struct dw_dma_channel { -+ unsigned int state; -+ int is_cyclic; -+ struct dma_request_sg *req_sg; -+ struct dma_request_cyclic *req_cyclic; -+ unsigned int nr_blocks; -+ int direction; -+ struct dw_dma_block *block; -+}; -+ -+struct dw_dma_controller { -+ spinlock_t lock; -+ void * __iomem regs; -+ struct dma_pool *lli_pool; -+ struct clk *hclk; -+ struct dma_controller dma; -+ struct dw_dma_channel channel[DMAC_NR_CHANNELS]; -+}; -+#define to_dw_dmac(dmac) container_of(dmac, struct dw_dma_controller, dma) -+ -+#define dmac_writel_hi(dmac, reg, value) \ -+ __raw_writel((value), (dmac)->regs + DW_DMAC_##reg + 4) -+#define dmac_readl_hi(dmac, reg) \ -+ __raw_readl((dmac)->regs + DW_DMAC_##reg + 4) -+#define dmac_writel_lo(dmac, reg, value) \ -+ __raw_writel((value), (dmac)->regs + DW_DMAC_##reg) -+#define dmac_readl_lo(dmac, reg) \ -+ __raw_readl((dmac)->regs + DW_DMAC_##reg) -+#define dmac_chan_writel_hi(dmac, chan, reg, value) \ -+ __raw_writel((value), ((dmac)->regs + 0x58 * (chan) \ -+ + DW_DMAC_CHAN_##reg + 4)) -+#define dmac_chan_readl_hi(dmac, chan, reg) \ -+ __raw_readl((dmac)->regs + 0x58 * (chan) + DW_DMAC_CHAN_##reg + 4) -+#define dmac_chan_writel_lo(dmac, chan, reg, value) \ -+ __raw_writel((value), (dmac)->regs + 0x58 * (chan) + DW_DMAC_CHAN_##reg) -+#define dmac_chan_readl_lo(dmac, chan, reg) \ -+ __raw_readl((dmac)->regs + 0x58 * (chan) + DW_DMAC_CHAN_##reg) -+#define set_channel_bit(dmac, reg, chan) \ -+ dmac_writel_lo(dmac, reg, (1 << (chan)) | (1 << ((chan) + 8))) -+#define clear_channel_bit(dmac, reg, chan) \ -+ dmac_writel_lo(dmac, reg, (0 << (chan)) | (1 << ((chan) + 8))) -+ -+static int dmac_alloc_channel(struct dma_controller *_dmac) -+{ -+ struct dw_dma_controller *dmac = to_dw_dmac(_dmac); -+ struct dw_dma_channel *chan; -+ unsigned long flags; -+ int i; -+ -+ spin_lock_irqsave(&dmac->lock, flags); -+ for (i = 0; i < DMAC_NR_CHANNELS; i++) -+ if (dmac->channel[i].state == CH_STATE_FREE) -+ break; -+ -+ if (i < DMAC_NR_CHANNELS) { -+ chan = &dmac->channel[i]; -+ chan->state = CH_STATE_ALLOCATED; -+ } else { -+ i = -EBUSY; -+ } -+ -+ spin_unlock_irqrestore(&dmac->lock, flags); -+ -+ return i; -+} -+ -+static void dmac_release_channel(struct dma_controller *_dmac, int channel) -+{ -+ struct dw_dma_controller *dmac = to_dw_dmac(_dmac); -+ -+ BUG_ON(channel >= DMAC_NR_CHANNELS -+ || dmac->channel[channel].state != CH_STATE_ALLOCATED); -+ -+ dmac->channel[channel].state = CH_STATE_FREE; -+} -+ -+static struct dw_dma_block *allocate_blocks(struct dw_dma_controller *dmac, -+ unsigned int nr_blocks) -+{ -+ struct dw_dma_block *block; -+ void *p; -+ unsigned int i; -+ -+ block = kmalloc(nr_blocks * sizeof(*block), -+ GFP_KERNEL); -+ if (unlikely(!block)) -+ return NULL; -+ -+ for (i = 0; i < nr_blocks; i++) { -+ p = dma_pool_alloc(dmac->lli_pool, GFP_KERNEL, -+ &block[i].lli_dma_addr); -+ block[i].lli_vaddr = p; -+ if (unlikely(!p)) -+ goto fail; -+ } -+ -+ return block; -+ -+fail: -+ for (i = 0; i < nr_blocks; i++) { -+ if (!block[i].lli_vaddr) -+ break; -+ dma_pool_free(dmac->lli_pool, block[i].lli_vaddr, -+ block[i].lli_dma_addr); -+ } -+ kfree(block); -+ return NULL; -+} -+ -+static void cleanup_channel(struct dw_dma_controller *dmac, -+ struct dw_dma_channel *chan) -+{ -+ unsigned int i; -+ -+ if (chan->nr_blocks > 1) { -+ for (i = 0; i < chan->nr_blocks; i++) -+ dma_pool_free(dmac->lli_pool, chan->block[i].lli_vaddr, -+ chan->block[i].lli_dma_addr); -+ kfree(chan->block); -+ } -+ -+ chan->state = CH_STATE_ALLOCATED; -+} -+ -+static int dmac_prepare_request_sg(struct dma_controller *_dmac, -+ struct dma_request_sg *req) -+{ -+ struct dw_dma_controller *dmac = to_dw_dmac(_dmac); -+ struct dw_dma_channel *chan; -+ unsigned long ctlhi, ctllo, cfghi, cfglo; -+ unsigned long block_size; -+ unsigned int nr_blocks; -+ int ret, i, direction; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&dmac->lock, flags); -+ -+ ret = -EINVAL; -+ if (req->req.channel >= DMAC_NR_CHANNELS -+ || dmac->channel[req->req.channel].state != CH_STATE_ALLOCATED -+ || req->block_size > DMAC_MAX_BLOCKSIZE) { -+ spin_unlock_irqrestore(&dmac->lock, flags); -+ return -EINVAL; -+ } -+ -+ chan = &dmac->channel[req->req.channel]; -+ chan->state = CH_STATE_BUSY; -+ chan->req_sg = req; -+ chan->is_cyclic = 0; -+ -+ /* -+ * We have marked the channel as busy, so no need to keep the -+ * lock as long as we only touch the channel-specific -+ * registers -+ */ -+ spin_unlock_irqrestore(&dmac->lock, flags); -+ -+ /* -+ * There may be limitations in the driver and/or the DMA -+ * controller that prevents us from sending a whole -+ * scatterlist item in one go. Taking this into account, -+ * calculate the number of block transfers we need to set up. -+ * -+ * FIXME: Let the peripheral driver know about the maximum -+ * block size we support. We really don't want to use a -+ * different block size than what was suggested by the -+ * peripheral. -+ * -+ * Each block will get its own Linked List Item (LLI) below. -+ */ -+ block_size = req->block_size; -+ nr_blocks = req->nr_blocks; -+ pr_debug("block_size %lu, nr_blocks %u nr_sg = %u\n", -+ block_size, nr_blocks, req->nr_sg); -+ -+ BUG_ON(nr_blocks == 0); -+ chan->nr_blocks = nr_blocks; -+ -+ ret = -EINVAL; -+ cfglo = cfghi = 0; -+ switch (req->direction) { -+ case DMA_DIR_MEM_TO_PERIPH: -+ direction = DMA_TO_DEVICE; -+ cfghi = req->periph_id << (43 - 32); -+ break; -+ -+ case DMA_DIR_PERIPH_TO_MEM: -+ direction = DMA_FROM_DEVICE; -+ cfghi = req->periph_id << (39 - 32); -+ break; -+ default: -+ goto out_unclaim_channel; -+ } -+ -+ chan->direction = direction; -+ -+ dmac_chan_writel_hi(dmac, req->req.channel, CFG, cfghi); -+ dmac_chan_writel_lo(dmac, req->req.channel, CFG, cfglo); -+ -+ ctlhi = block_size >> req->width; -+ ctllo = ((req->direction << 20) -+ // | (1 << 14) | (1 << 11) // source/dest burst trans len -+ | (req->width << 4) | (req->width << 1) -+ | (1 << 0)); // interrupt enable -+ -+ if (nr_blocks == 1) { -+ /* Only one block: No need to use block chaining */ -+ if (direction == DMA_TO_DEVICE) { -+ dmac_chan_writel_lo(dmac, req->req.channel, SAR, -+ req->sg->dma_address); -+ dmac_chan_writel_lo(dmac, req->req.channel, DAR, -+ req->data_reg); -+ ctllo |= 2 << 7; // no dst increment -+ } else { -+ dmac_chan_writel_lo(dmac, req->req.channel, SAR, -+ req->data_reg); -+ dmac_chan_writel_lo(dmac, req->req.channel, DAR, -+ req->sg->dma_address); -+ ctllo |= 2 << 9; // no src increment -+ } -+ dmac_chan_writel_lo(dmac, req->req.channel, CTL, ctllo); -+ dmac_chan_writel_hi(dmac, req->req.channel, CTL, ctlhi); -+ pr_debug("ctl hi:lo 0x%lx:%lx\n", ctlhi, ctllo); -+ } else { -+ struct dw_dma_lli *lli, *lli_prev = NULL; -+ int j = 0, offset = 0; -+ -+ ret = -ENOMEM; -+ chan->block = allocate_blocks(dmac, nr_blocks); -+ if (!chan->block) -+ goto out_unclaim_channel; -+ -+ if (direction == DMA_TO_DEVICE) -+ ctllo |= 1 << 28 | 1 << 27 | 2 << 7; -+ else -+ ctllo |= 1 << 28 | 1 << 27 | 2 << 9; -+ -+ /* -+ * Map scatterlist items to blocks. One scatterlist -+ * item may need more than one block for the reasons -+ * mentioned above. -+ */ -+ for (i = 0; i < nr_blocks; i++) { -+ lli = chan->block[i].lli_vaddr; -+ if (lli_prev) { -+ lli_prev->llp = chan->block[i].lli_dma_addr; -+ pr_debug("lli[%d] (0x%p/0x%x): 0x%x 0x%x 0x%x 0x%x 0x%x\n", -+ i - 1, chan->block[i - 1].lli_vaddr, -+ chan->block[i - 1].lli_dma_addr, -+ lli_prev->sar, lli_prev->dar, lli_prev->llp, -+ lli_prev->ctllo, lli_prev->ctlhi); -+ } -+ lli->llp = 0; -+ lli->ctllo = ctllo; -+ lli->ctlhi = ctlhi; -+ if (direction == DMA_TO_DEVICE) { -+ lli->sar = req->sg[j].dma_address + offset; -+ lli->dar = req->data_reg; -+ } else { -+ lli->sar = req->data_reg; -+ lli->dar = req->sg[j].dma_address + offset; -+ } -+ lli_prev = lli; -+ -+ offset += block_size; -+ if (offset > req->sg[j].length) { -+ j++; -+ offset = 0; -+ } -+ } -+ -+ pr_debug("lli[%d] (0x%p/0x%x): 0x%x 0x%x 0x%x 0x%x 0x%x\n", -+ i - 1, chan->block[i - 1].lli_vaddr, -+ chan->block[i - 1].lli_dma_addr, lli_prev->sar, -+ lli_prev->dar, lli_prev->llp, -+ lli_prev->ctllo, lli_prev->ctlhi); -+ -+ /* -+ * SAR, DAR and CTL are initialized from the LLI. We -+ * only have to enable the LLI bits in CTL. -+ */ -+ dmac_chan_writel_hi(dmac, req->req.channel, CTL, 0); -+ dmac_chan_writel_lo(dmac, req->req.channel, LLP, -+ chan->block[0].lli_dma_addr); -+ dmac_chan_writel_lo(dmac, req->req.channel, CTL, 1 << 28 | 1 << 27); -+ } -+ -+ set_channel_bit(dmac, MASK_XFER, req->req.channel); -+ set_channel_bit(dmac, MASK_ERROR, req->req.channel); -+ if (req->req.block_complete) -+ set_channel_bit(dmac, MASK_BLOCK, req->req.channel); -+ else -+ clear_channel_bit(dmac, MASK_BLOCK, req->req.channel); -+ -+ return 0; -+ -+out_unclaim_channel: -+ chan->state = CH_STATE_ALLOCATED; -+ return ret; -+} -+ -+static int dmac_prepare_request_cyclic(struct dma_controller *_dmac, -+ struct dma_request_cyclic *req) -+{ -+ struct dw_dma_controller *dmac = to_dw_dmac(_dmac); -+ struct dw_dma_channel *chan; -+ unsigned long ctlhi, ctllo, cfghi, cfglo; -+ unsigned long block_size; -+ int ret, i, direction; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&dmac->lock, flags); -+ -+ block_size = (req->buffer_size/req->periods) >> req->width; -+ -+ ret = -EINVAL; -+ if (req->req.channel >= DMAC_NR_CHANNELS -+ || dmac->channel[req->req.channel].state != CH_STATE_ALLOCATED -+ || (req->periods == 0) -+ || block_size > DMAC_MAX_BLOCKSIZE) { -+ spin_unlock_irqrestore(&dmac->lock, flags); -+ return -EINVAL; -+ } -+ -+ chan = &dmac->channel[req->req.channel]; -+ chan->state = CH_STATE_BUSY; -+ chan->is_cyclic = 1; -+ chan->req_cyclic = req; -+ -+ /* -+ * We have marked the channel as busy, so no need to keep the -+ * lock as long as we only touch the channel-specific -+ * registers -+ */ -+ spin_unlock_irqrestore(&dmac->lock, flags); -+ -+ /* -+ Setup -+ */ -+ BUG_ON(req->buffer_size % req->periods); -+ /* printk(KERN_INFO "block_size = %lu, periods = %u\n", block_size, req->periods); */ -+ -+ chan->nr_blocks = req->periods; -+ -+ ret = -EINVAL; -+ cfglo = cfghi = 0; -+ switch (req->direction) { -+ case DMA_DIR_MEM_TO_PERIPH: -+ direction = DMA_TO_DEVICE; -+ cfghi = req->periph_id << (43 - 32); -+ break; -+ -+ case DMA_DIR_PERIPH_TO_MEM: -+ direction = DMA_FROM_DEVICE; -+ cfghi = req->periph_id << (39 - 32); -+ break; -+ default: -+ goto out_unclaim_channel; -+ } -+ -+ chan->direction = direction; -+ -+ dmac_chan_writel_hi(dmac, req->req.channel, CFG, cfghi); -+ dmac_chan_writel_lo(dmac, req->req.channel, CFG, cfglo); -+ -+ ctlhi = block_size; -+ ctllo = ((req->direction << 20) -+ | (req->width << 4) | (req->width << 1) -+ | (1 << 0)); // interrupt enable -+ -+ { -+ struct dw_dma_lli *lli = NULL, *lli_prev = NULL; -+ -+ ret = -ENOMEM; -+ chan->block = allocate_blocks(dmac, req->periods); -+ if (!chan->block) -+ goto out_unclaim_channel; -+ -+ if (direction == DMA_TO_DEVICE) -+ ctllo |= 1 << 28 | 1 << 27 | 2 << 7; -+ else -+ ctllo |= 1 << 28 | 1 << 27 | 2 << 9; -+ -+ /* -+ * Set up a linked list items where each period gets -+ * an item. The linked list item for the last period -+ * points back to the star of the buffer making a -+ * cyclic buffer. -+ */ -+ for (i = 0; i < req->periods; i++) { -+ lli = chan->block[i].lli_vaddr; -+ if (lli_prev) { -+ lli_prev->llp = chan->block[i].lli_dma_addr; -+ /* printk(KERN_INFO "lli[%d] (0x%p/0x%x): 0x%x 0x%x 0x%x 0x%x 0x%x\n", -+ i - 1, chan->block[i - 1].lli_vaddr, -+ chan->block[i - 1].lli_dma_addr, -+ lli_prev->sar, lli_prev->dar, lli_prev->llp, -+ lli_prev->ctllo, lli_prev->ctlhi);*/ -+ } -+ lli->llp = 0; -+ lli->ctllo = ctllo; -+ lli->ctlhi = ctlhi; -+ if (direction == DMA_TO_DEVICE) { -+ lli->sar = req->buffer_start + i*(block_size << req->width); -+ lli->dar = req->data_reg; -+ } else { -+ lli->sar = req->data_reg; -+ lli->dar = req->buffer_start + i*(block_size << req->width); -+ } -+ lli_prev = lli; -+ } -+ lli->llp = chan->block[0].lli_dma_addr; -+ -+ /*printk(KERN_INFO "lli[%d] (0x%p/0x%x): 0x%x 0x%x 0x%x 0x%x 0x%x\n", -+ i - 1, chan->block[i - 1].lli_vaddr, -+ chan->block[i - 1].lli_dma_addr, lli_prev->sar, -+ lli_prev->dar, lli_prev->llp, -+ lli_prev->ctllo, lli_prev->ctlhi); */ -+ -+ /* -+ * SAR, DAR and CTL are initialized from the LLI. We -+ * only have to enable the LLI bits in CTL. -+ */ -+ dmac_chan_writel_lo(dmac, req->req.channel, LLP, -+ chan->block[0].lli_dma_addr); -+ dmac_chan_writel_lo(dmac, req->req.channel, CTL, 1 << 28 | 1 << 27); -+ } -+ -+ clear_channel_bit(dmac, MASK_XFER, req->req.channel); -+ set_channel_bit(dmac, MASK_ERROR, req->req.channel); -+ if (req->req.block_complete) -+ set_channel_bit(dmac, MASK_BLOCK, req->req.channel); -+ else -+ clear_channel_bit(dmac, MASK_BLOCK, req->req.channel); -+ -+ return 0; -+ -+out_unclaim_channel: -+ chan->state = CH_STATE_ALLOCATED; -+ return ret; -+} -+ -+static int dmac_start_request(struct dma_controller *_dmac, -+ unsigned int channel) -+{ -+ struct dw_dma_controller *dmac = to_dw_dmac(_dmac); -+ -+ BUG_ON(channel >= DMAC_NR_CHANNELS); -+ -+ set_channel_bit(dmac, CH_EN, channel); -+ -+ return 0; -+} -+ -+static dma_addr_t dmac_get_current_pos(struct dma_controller *_dmac, -+ unsigned int channel) -+{ -+ struct dw_dma_controller *dmac = to_dw_dmac(_dmac); -+ struct dw_dma_channel *chan; -+ dma_addr_t current_pos; -+ -+ BUG_ON(channel >= DMAC_NR_CHANNELS); -+ -+ chan = &dmac->channel[channel]; -+ -+ switch (chan->direction) { -+ case DMA_TO_DEVICE: -+ current_pos = dmac_chan_readl_lo(dmac, channel, SAR); -+ break; -+ case DMA_FROM_DEVICE: -+ current_pos = dmac_chan_readl_lo(dmac, channel, DAR); -+ break; -+ default: -+ return 0; -+ } -+ -+ -+ if (!current_pos) { -+ if (chan->is_cyclic) { -+ current_pos = chan->req_cyclic->buffer_start; -+ } else { -+ current_pos = chan->req_sg->sg->dma_address; -+ } -+ } -+ -+ return current_pos; -+} -+ -+ -+static int dmac_stop_request(struct dma_controller *_dmac, -+ unsigned int channel) -+{ -+ struct dw_dma_controller *dmac = to_dw_dmac(_dmac); -+ struct dw_dma_channel *chan; -+ -+ BUG_ON(channel >= DMAC_NR_CHANNELS); -+ -+ chan = &dmac->channel[channel]; -+ pr_debug("stop: st%u s%08x d%08x l%08x ctl0x%08x:0x%08x\n", -+ chan->state, dmac_chan_readl_lo(dmac, channel, SAR), -+ dmac_chan_readl_lo(dmac, channel, DAR), -+ dmac_chan_readl_lo(dmac, channel, LLP), -+ dmac_chan_readl_hi(dmac, channel, CTL), -+ dmac_chan_readl_lo(dmac, channel, CTL)); -+ -+ if (chan->state == CH_STATE_BUSY) { -+ clear_channel_bit(dmac, CH_EN, channel); -+ cleanup_channel(dmac, &dmac->channel[channel]); -+ } -+ -+ return 0; -+} -+ -+ -+static void dmac_block_complete(struct dw_dma_controller *dmac) -+{ -+ struct dw_dma_channel *chan; -+ unsigned long status, chanid; -+ -+ status = dmac_readl_lo(dmac, STATUS_BLOCK); -+ -+ while (status) { -+ struct dma_request *req; -+ chanid = __ffs(status); -+ chan = &dmac->channel[chanid]; -+ -+ if (chan->is_cyclic) { -+ BUG_ON(!chan->req_cyclic -+ || !chan->req_cyclic->req.block_complete); -+ req = &chan->req_cyclic->req; -+ } else { -+ BUG_ON(!chan->req_sg || !chan->req_sg->req.block_complete); -+ req = &chan->req_sg->req; -+ } -+ dmac_writel_lo(dmac, CLEAR_BLOCK, 1 << chanid); -+ req->block_complete(req); -+ status = dmac_readl_lo(dmac, STATUS_BLOCK); -+ } -+} -+ -+static void dmac_xfer_complete(struct dw_dma_controller *dmac) -+{ -+ struct dw_dma_channel *chan; -+ struct dma_request *req; -+ unsigned long status, chanid; -+ -+ status = dmac_readl_lo(dmac, STATUS_XFER); -+ -+ while (status) { -+ chanid = __ffs(status); -+ chan = &dmac->channel[chanid]; -+ -+ dmac_writel_lo(dmac, CLEAR_XFER, 1 << chanid); -+ -+ req = &chan->req_sg->req; -+ BUG_ON(!req); -+ cleanup_channel(dmac, chan); -+ if (req->xfer_complete) -+ req->xfer_complete(req); -+ -+ status = dmac_readl_lo(dmac, STATUS_XFER); -+ } -+} -+ -+static void dmac_error(struct dw_dma_controller *dmac) -+{ -+ struct dw_dma_channel *chan; -+ unsigned long status, chanid; -+ -+ status = dmac_readl_lo(dmac, STATUS_ERROR); -+ -+ while (status) { -+ struct dma_request *req; -+ -+ chanid = __ffs(status); -+ chan = &dmac->channel[chanid]; -+ -+ dmac_writel_lo(dmac, CLEAR_ERROR, 1 << chanid); -+ clear_channel_bit(dmac, CH_EN, chanid); -+ -+ if (chan->is_cyclic) { -+ BUG_ON(!chan->req_cyclic); -+ req = &chan->req_cyclic->req; -+ } else { -+ BUG_ON(!chan->req_sg); -+ req = &chan->req_sg->req; -+ } -+ -+ cleanup_channel(dmac, chan); -+ if (req->error) -+ req->error(req); -+ -+ status = dmac_readl_lo(dmac, STATUS_XFER); -+ } -+} -+ -+static irqreturn_t dmac_interrupt(int irq, void *dev_id) -+{ -+ struct dw_dma_controller *dmac = dev_id; -+ unsigned long status; -+ int ret = IRQ_NONE; -+ -+ spin_lock(&dmac->lock); -+ -+ status = dmac_readl_lo(dmac, STATUS_INT); -+ -+ while (status) { -+ ret = IRQ_HANDLED; -+ if (status & 0x10) -+ dmac_error(dmac); -+ if (status & 0x02) -+ dmac_block_complete(dmac); -+ if (status & 0x01) -+ dmac_xfer_complete(dmac); -+ -+ status = dmac_readl_lo(dmac, STATUS_INT); -+ } -+ -+ spin_unlock(&dmac->lock); -+ return ret; -+} -+ -+static int __devinit dmac_probe(struct platform_device *pdev) -+{ -+ struct dw_dma_controller *dmac; -+ struct resource *regs; -+ int ret; -+ -+ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!regs) -+ return -ENXIO; -+ -+ dmac = kmalloc(sizeof(*dmac), GFP_KERNEL); -+ if (!dmac) -+ return -ENOMEM; -+ memset(dmac, 0, sizeof(*dmac)); -+ -+ dmac->hclk = clk_get(&pdev->dev, "hclk"); -+ if (IS_ERR(dmac->hclk)) { -+ ret = PTR_ERR(dmac->hclk); -+ goto out_free_dmac; -+ } -+ clk_enable(dmac->hclk); -+ -+ ret = -ENOMEM; -+ dmac->lli_pool = dma_pool_create("dmac", &pdev->dev, -+ sizeof(struct dw_dma_lli), 4, 0); -+ if (!dmac->lli_pool) -+ goto out_disable_clk; -+ -+ spin_lock_init(&dmac->lock); -+ dmac->dma.dev = &pdev->dev; -+ dmac->dma.alloc_channel = dmac_alloc_channel; -+ dmac->dma.release_channel = dmac_release_channel; -+ dmac->dma.prepare_request_sg = dmac_prepare_request_sg; -+ dmac->dma.prepare_request_cyclic = dmac_prepare_request_cyclic; -+ dmac->dma.start_request = dmac_start_request; -+ dmac->dma.stop_request = dmac_stop_request; -+ dmac->dma.get_current_pos = dmac_get_current_pos; -+ -+ dmac->regs = ioremap(regs->start, regs->end - regs->start + 1); -+ if (!dmac->regs) -+ goto out_free_pool; -+ -+ ret = request_irq(platform_get_irq(pdev, 0), dmac_interrupt, -+ SA_SAMPLE_RANDOM, pdev->name, dmac); -+ if (ret) -+ goto out_unmap_regs; -+ -+ /* Enable the DMA controller */ -+ dmac_writel_lo(dmac, CFG, 1); -+ -+ register_dma_controller(&dmac->dma); -+ -+ printk(KERN_INFO -+ "dmac%d: DesignWare DMA controller at 0x%p irq %d\n", -+ dmac->dma.id, dmac->regs, platform_get_irq(pdev, 0)); -+ -+ return 0; -+ -+out_unmap_regs: -+ iounmap(dmac->regs); -+out_free_pool: -+ dma_pool_destroy(dmac->lli_pool); -+out_disable_clk: -+ clk_disable(dmac->hclk); -+ clk_put(dmac->hclk); -+out_free_dmac: -+ kfree(dmac); -+ return ret; -+} -+ -+static struct platform_driver dmac_driver = { -+ .probe = dmac_probe, -+ .driver = { -+ .name = "dmaca", -+ }, -+}; -+ -+static int __init dmac_init(void) -+{ -+ return platform_driver_register(&dmac_driver); -+} -+subsys_initcall(dmac_init); -+ -+static void __exit dmac_exit(void) -+{ -+ platform_driver_unregister(&dmac_driver); -+} -+module_exit(dmac_exit); -+ -+MODULE_DESCRIPTION("Synopsys DesignWare DMA Controller driver"); -+MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>"); -+MODULE_LICENSE("GPL"); -diff -urN linux-2.6.20.4-0rig/arch/avr32/drivers/dw-dmac.h linux-2.6.20.4-atmel/arch/avr32/drivers/dw-dmac.h ---- linux-2.6.20.4-0rig/arch/avr32/drivers/dw-dmac.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/avr32/drivers/dw-dmac.h 2007-03-24 16:42:29.000000000 +0100 -@@ -0,0 +1,42 @@ -+/* -+ * Driver for the Synopsys DesignWare DMA Controller -+ * -+ * Copyright (C) 2005-2006 Atmel Corporation -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+#ifndef __AVR32_DW_DMAC_H__ -+#define __AVR32_DW_DMAC_H__ -+ -+#define DW_DMAC_CFG 0x398 -+#define DW_DMAC_CH_EN 0x3a0 -+ -+#define DW_DMAC_STATUS_XFER 0x2e8 -+#define DW_DMAC_STATUS_BLOCK 0x2f0 -+#define DW_DMAC_STATUS_ERROR 0x308 -+ -+#define DW_DMAC_MASK_XFER 0x310 -+#define DW_DMAC_MASK_BLOCK 0x318 -+#define DW_DMAC_MASK_ERROR 0x330 -+ -+#define DW_DMAC_CLEAR_XFER 0x338 -+#define DW_DMAC_CLEAR_BLOCK 0x340 -+#define DW_DMAC_CLEAR_ERROR 0x358 -+ -+#define DW_DMAC_STATUS_INT 0x360 -+ -+#define DW_DMAC_CHAN_SAR 0x000 -+#define DW_DMAC_CHAN_DAR 0x008 -+#define DW_DMAC_CHAN_LLP 0x010 -+#define DW_DMAC_CHAN_CTL 0x018 -+#define DW_DMAC_CHAN_SSTAT 0x020 -+#define DW_DMAC_CHAN_DSTAT 0x028 -+#define DW_DMAC_CHAN_SSTATAR 0x030 -+#define DW_DMAC_CHAN_DSTATAR 0x038 -+#define DW_DMAC_CHAN_CFG 0x040 -+#define DW_DMAC_CHAN_SGR 0x048 -+#define DW_DMAC_CHAN_DSR 0x050 -+ -+#endif /* __AVR32_DW_DMAC_H__ */ -diff -urN linux-2.6.20.4-0rig/arch/avr32/drivers/Makefile linux-2.6.20.4-atmel/arch/avr32/drivers/Makefile ---- linux-2.6.20.4-0rig/arch/avr32/drivers/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/avr32/drivers/Makefile 2007-03-24 16:42:29.000000000 +0100 -@@ -0,0 +1 @@ -+obj-$(CONFIG_DW_DMAC) += dw-dmac.o -diff -urN linux-2.6.20.4-0rig/arch/avr32/Kconfig linux-2.6.20.4-atmel/arch/avr32/Kconfig ---- linux-2.6.20.4-0rig/arch/avr32/Kconfig 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/avr32/Kconfig 2007-03-24 16:42:29.000000000 +0100 -@@ -112,6 +112,8 @@ - bool "U-Boot (or similar) bootloader" - endchoice - -+source "arch/avr32/mach-at32ap/Kconfig" -+ - config LOAD_ADDRESS - hex - default 0x10000000 if LOADER_U_BOOT=y && CPU_AT32AP7000=y -@@ -160,6 +162,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" -@@ -195,6 +201,8 @@ - - source "fs/Kconfig" - -+source "arch/avr32/oprofile/Kconfig" -+ - source "arch/avr32/Kconfig.debug" - - source "security/Kconfig" -diff -urN linux-2.6.20.4-0rig/arch/avr32/kernel/cpu.c linux-2.6.20.4-atmel/arch/avr32/kernel/cpu.c ---- linux-2.6.20.4-0rig/arch/avr32/kernel/cpu.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/avr32/kernel/cpu.c 2007-03-24 16:42:28.000000000 +0100 -@@ -9,6 +9,7 @@ - #include <linux/sysdev.h> - #include <linux/seq_file.h> - #include <linux/cpu.h> -+#include <linux/module.h> - #include <linux/percpu.h> - #include <linux/param.h> - #include <linux/errno.h> -diff -urN linux-2.6.20.4-0rig/arch/avr32/kernel/dma-controller.c linux-2.6.20.4-atmel/arch/avr32/kernel/dma-controller.c ---- linux-2.6.20.4-0rig/arch/avr32/kernel/dma-controller.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/avr32/kernel/dma-controller.c 2007-03-24 16:42:29.000000000 +0100 -@@ -0,0 +1,34 @@ -+/* -+ * Preliminary DMA controller framework for AVR32 -+ * -+ * Copyright (C) 2005-2006 Atmel Corporation -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+#include <asm/dma-controller.h> -+ -+static LIST_HEAD(controllers); -+ -+int register_dma_controller(struct dma_controller *dmac) -+{ -+ static int next_id; -+ -+ dmac->id = next_id++; -+ list_add_tail(&dmac->list, &controllers); -+ -+ return 0; -+} -+EXPORT_SYMBOL(register_dma_controller); -+ -+struct dma_controller *find_dma_controller(int id) -+{ -+ struct dma_controller *dmac; -+ -+ list_for_each_entry(dmac, &controllers, list) -+ if (dmac->id == id) -+ return dmac; -+ return NULL; -+} -+EXPORT_SYMBOL(find_dma_controller); -diff -urN linux-2.6.20.4-0rig/arch/avr32/kernel/irq.c linux-2.6.20.4-atmel/arch/avr32/kernel/irq.c ---- linux-2.6.20.4-0rig/arch/avr32/kernel/irq.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/avr32/kernel/irq.c 2007-03-24 16:42:28.000000000 +0100 -@@ -57,6 +57,7 @@ - seq_printf(p, "%3d: ", i); - for_each_online_cpu(cpu) - seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[i]); -+ seq_printf(p, " %8s", irq_desc[i].chip->name ? : "-"); - seq_printf(p, " %s", action->name); - for (action = action->next; action; action = action->next) - seq_printf(p, ", %s", action->name); -diff -urN linux-2.6.20.4-0rig/arch/avr32/kernel/Makefile linux-2.6.20.4-atmel/arch/avr32/kernel/Makefile ---- linux-2.6.20.4-0rig/arch/avr32/kernel/Makefile 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/avr32/kernel/Makefile 2007-03-24 16:42:29.000000000 +0100 -@@ -9,6 +9,7 @@ - obj-y += setup.o traps.o semaphore.o ptrace.o - obj-y += signal.o sys_avr32.o process.o time.o - obj-y += init_task.o switch_to.o cpu.o -+obj-y += dma-controller.o - obj-$(CONFIG_MODULES) += module.o avr32_ksyms.o - obj-$(CONFIG_KPROBES) += kprobes.o - -diff -urN linux-2.6.20.4-0rig/arch/avr32/kernel/setup.c linux-2.6.20.4-atmel/arch/avr32/kernel/setup.c ---- linux-2.6.20.4-0rig/arch/avr32/kernel/setup.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/avr32/kernel/setup.c 2007-03-24 16:42:28.000000000 +0100 -@@ -16,6 +16,7 @@ - #include <linux/module.h> - #include <linux/root_dev.h> - #include <linux/cpu.h> -+#include <linux/kernel.h> - - #include <asm/sections.h> - #include <asm/processor.h> -@@ -174,8 +175,7 @@ - * Copy the data so the bootmem init code doesn't need to care - * about it. - */ -- if (mem_range_next_free >= -- (sizeof(mem_range_cache) / sizeof(mem_range_cache[0]))) -+ if (mem_range_next_free >= ARRAY_SIZE(mem_range_cache)) - panic("Physical memory map too complex!\n"); - - new = &mem_range_cache[mem_range_next_free++]; -diff -urN linux-2.6.20.4-0rig/arch/avr32/kernel/syscall_table.S linux-2.6.20.4-atmel/arch/avr32/kernel/syscall_table.S ---- linux-2.6.20.4-0rig/arch/avr32/kernel/syscall_table.S 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/avr32/kernel/syscall_table.S 2007-03-24 16:42:28.000000000 +0100 -@@ -8,14 +8,6 @@ - * published by the Free Software Foundation. - */ - --#if !defined(CONFIG_NFSD) && !defined(CONFIG_NFSD_MODULE) --#define sys_nfsservctl sys_ni_syscall --#endif -- --#if !defined(CONFIG_SYSV_IPC) --# define sys_ipc sys_ni_syscall --#endif -- - .section .rodata,"a",@progbits - .type sys_call_table,@object - .global sys_call_table -@@ -129,7 +121,7 @@ - .long sys_getitimer /* 105 */ - .long sys_swapoff - .long sys_sysinfo -- .long sys_ipc -+ .long sys_ni_syscall /* was sys_ipc briefly */ - .long sys_sendfile - .long sys_setdomainname /* 110 */ - .long sys_newuname -@@ -287,4 +279,16 @@ - .long sys_tee - .long sys_vmsplice - .long __sys_epoll_pwait /* 265 */ -+ .long sys_msgget -+ .long sys_msgsnd -+ .long sys_msgrcv -+ .long sys_msgctl -+ .long sys_semget /* 270 */ -+ .long sys_semop -+ .long sys_semctl -+ .long sys_semtimedop -+ .long sys_shmat -+ .long sys_shmget /* 275 */ -+ .long sys_shmdt -+ .long sys_shmctl - .long sys_ni_syscall /* r8 is saturated at nr_syscalls */ -diff -urN linux-2.6.20.4-0rig/arch/avr32/kernel/time.c linux-2.6.20.4-atmel/arch/avr32/kernel/time.c ---- linux-2.6.20.4-0rig/arch/avr32/kernel/time.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/avr32/kernel/time.c 2007-03-24 16:42:29.000000000 +0100 -@@ -21,6 +21,7 @@ - #include <linux/profile.h> - #include <linux/sysdev.h> - -+#include <asm/intc.h> - #include <asm/div64.h> - #include <asm/sysreg.h> - #include <asm/io.h> -@@ -136,6 +137,10 @@ - { - unsigned int count; - -+ /* Check if interrupt is timer or performance counters */ -+ if (!(intc_get_pending(irq) & 1)) -+ return IRQ_NONE; -+ - /* ack timer interrupt and try to set next interrupt */ - count = avr32_hpt_read(); - avr32_timer_ack(); -@@ -164,7 +169,7 @@ - - static struct irqaction timer_irqaction = { - .handler = timer_interrupt, -- .flags = IRQF_DISABLED, -+ .flags = IRQF_DISABLED|IRQF_SHARED, - .name = "timer", - }; - -diff -urN linux-2.6.20.4-0rig/arch/avr32/kernel/traps.c linux-2.6.20.4-atmel/arch/avr32/kernel/traps.c ---- linux-2.6.20.4-0rig/arch/avr32/kernel/traps.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/avr32/kernel/traps.c 2007-03-24 16:42:28.000000000 +0100 -@@ -49,39 +49,45 @@ - return; - } - -+static inline int valid_stack_ptr(struct thread_info *tinfo, unsigned long p) -+{ -+ return (p > (unsigned long)tinfo) -+ && (p < (unsigned long)tinfo + THREAD_SIZE - 3); -+} -+ - #ifdef CONFIG_FRAME_POINTER - static inline void __show_trace(struct task_struct *tsk, unsigned long *sp, - struct pt_regs *regs) - { -- unsigned long __user *fp; -- unsigned long __user *last_fp = NULL; -+ unsigned long lr, fp; -+ struct thread_info *tinfo; - -- if (regs) { -- fp = (unsigned long __user *)regs->r7; -- } else if (tsk == current) { -- register unsigned long __user *real_fp __asm__("r7"); -- fp = real_fp; -- } else { -- fp = (unsigned long __user *)tsk->thread.cpu_context.r7; -- } -+ tinfo = (struct thread_info *) -+ ((unsigned long)sp & ~(THREAD_SIZE - 1)); -+ -+ if (regs) -+ fp = regs->r7; -+ else if (tsk == current) -+ asm("mov %0, r7" : "=r"(fp)); -+ else -+ fp = tsk->thread.cpu_context.r7; - - /* -- * Walk the stack until (a) we get an exception, (b) the frame -- * pointer becomes zero, or (c) the frame pointer gets stuck -- * at the same value. -+ * Walk the stack as long as the frame pointer (a) is within -+ * the kernel stack of the task, and (b) it doesn't move -+ * downwards. - */ -- while (fp && fp != last_fp) { -- unsigned long lr, new_fp = 0; -- -- last_fp = fp; -- if (__get_user(lr, fp)) -- break; -- if (fp && __get_user(new_fp, fp + 1)) -- break; -- fp = (unsigned long __user *)new_fp; -+ while (valid_stack_ptr(tinfo, fp)) { -+ unsigned long new_fp; - -+ lr = *(unsigned long *)fp; - printk(" [<%08lx>] ", lr); - print_symbol("%s\n", lr); -+ -+ new_fp = *(unsigned long *)(fp + 4); -+ if (new_fp <= fp) -+ break; -+ fp = new_fp; - } - printk("\n"); - } -diff -urN linux-2.6.20.4-0rig/arch/avr32/lib/libgcc.h linux-2.6.20.4-atmel/arch/avr32/lib/libgcc.h ---- linux-2.6.20.4-0rig/arch/avr32/lib/libgcc.h 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/avr32/lib/libgcc.h 1970-01-01 01:00:00.000000000 +0100 -@@ -1,33 +0,0 @@ --/* Definitions for various functions 'borrowed' from gcc-3.4.3 */ -- --#define BITS_PER_UNIT 8 -- --typedef int QItype __attribute__ ((mode (QI))); --typedef unsigned int UQItype __attribute__ ((mode (QI))); --typedef int HItype __attribute__ ((mode (HI))); --typedef unsigned int UHItype __attribute__ ((mode (HI))); --typedef int SItype __attribute__ ((mode (SI))); --typedef unsigned int USItype __attribute__ ((mode (SI))); --typedef int DItype __attribute__ ((mode (DI))); --typedef unsigned int UDItype __attribute__ ((mode (DI))); --typedef float SFtype __attribute__ ((mode (SF))); --typedef float DFtype __attribute__ ((mode (DF))); --typedef int word_type __attribute__ ((mode (__word__))); -- --#define W_TYPE_SIZE (4 * BITS_PER_UNIT) --#define Wtype SItype --#define UWtype USItype --#define HWtype SItype --#define UHWtype USItype --#define DWtype DItype --#define UDWtype UDItype --#define __NW(a,b) __ ## a ## si ## b --#define __NDW(a,b) __ ## a ## di ## b -- --struct DWstruct {Wtype high, low;}; -- --typedef union --{ -- struct DWstruct s; -- DWtype ll; --} DWunion; -diff -urN linux-2.6.20.4-0rig/arch/avr32/lib/longlong.h linux-2.6.20.4-atmel/arch/avr32/lib/longlong.h ---- linux-2.6.20.4-0rig/arch/avr32/lib/longlong.h 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/avr32/lib/longlong.h 1970-01-01 01:00:00.000000000 +0100 -@@ -1,98 +0,0 @@ --/* longlong.h -- definitions for mixed size 32/64 bit arithmetic. -- Copyright (C) 1991, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000 -- Free Software Foundation, Inc. -- -- This definition file 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, or (at your option) any later version. -- -- This definition file 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. */ -- --/* Borrowed from gcc-3.4.3 */ -- --#define __BITS4 (W_TYPE_SIZE / 4) --#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2)) --#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1)) --#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2)) -- --#define count_leading_zeros(count, x) ((count) = __builtin_clz(x)) -- --#define __udiv_qrnnd_c(q, r, n1, n0, d) \ -- do { \ -- UWtype __d1, __d0, __q1, __q0; \ -- UWtype __r1, __r0, __m; \ -- __d1 = __ll_highpart (d); \ -- __d0 = __ll_lowpart (d); \ -- \ -- __r1 = (n1) % __d1; \ -- __q1 = (n1) / __d1; \ -- __m = (UWtype) __q1 * __d0; \ -- __r1 = __r1 * __ll_B | __ll_highpart (n0); \ -- if (__r1 < __m) \ -- { \ -- __q1--, __r1 += (d); \ -- if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\ -- if (__r1 < __m) \ -- __q1--, __r1 += (d); \ -- } \ -- __r1 -= __m; \ -- \ -- __r0 = __r1 % __d1; \ -- __q0 = __r1 / __d1; \ -- __m = (UWtype) __q0 * __d0; \ -- __r0 = __r0 * __ll_B | __ll_lowpart (n0); \ -- if (__r0 < __m) \ -- { \ -- __q0--, __r0 += (d); \ -- if (__r0 >= (d)) \ -- if (__r0 < __m) \ -- __q0--, __r0 += (d); \ -- } \ -- __r0 -= __m; \ -- \ -- (q) = (UWtype) __q1 * __ll_B | __q0; \ -- (r) = __r0; \ -- } while (0) -- --#define udiv_qrnnd __udiv_qrnnd_c -- --#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ -- do { \ -- UWtype __x; \ -- __x = (al) - (bl); \ -- (sh) = (ah) - (bh) - (__x > (al)); \ -- (sl) = __x; \ -- } while (0) -- --#define umul_ppmm(w1, w0, u, v) \ -- do { \ -- UWtype __x0, __x1, __x2, __x3; \ -- UHWtype __ul, __vl, __uh, __vh; \ -- \ -- __ul = __ll_lowpart (u); \ -- __uh = __ll_highpart (u); \ -- __vl = __ll_lowpart (v); \ -- __vh = __ll_highpart (v); \ -- \ -- __x0 = (UWtype) __ul * __vl; \ -- __x1 = (UWtype) __ul * __vh; \ -- __x2 = (UWtype) __uh * __vl; \ -- __x3 = (UWtype) __uh * __vh; \ -- \ -- __x1 += __ll_highpart (__x0);/* this can't give carry */ \ -- __x1 += __x2; /* but this indeed can */ \ -- if (__x1 < __x2) /* did we get it? */ \ -- __x3 += __ll_B; /* yes, add it in the proper pos. */ \ -- \ -- (w1) = __x3 + __ll_highpart (__x1); \ -- (w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0); \ -- } while (0) -diff -urN linux-2.6.20.4-0rig/arch/avr32/mach-at32ap/at32ap7000.c linux-2.6.20.4-atmel/arch/avr32/mach-at32ap/at32ap7000.c ---- linux-2.6.20.4-0rig/arch/avr32/mach-at32ap/at32ap7000.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/avr32/mach-at32ap/at32ap7000.c 2007-03-24 16:42:29.000000000 +0100 -@@ -8,6 +8,7 @@ - #include <linux/clk.h> - #include <linux/init.h> - #include <linux/platform_device.h> -+#include <linux/spi/spi.h> - - #include <asm/io.h> - -@@ -310,8 +311,6 @@ - { - u32 control; - -- BUG_ON(clk->index > 7); -- - control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index); - if (enabled) - control |= SM_BIT(CEN); -@@ -325,11 +324,6 @@ - u32 control; - unsigned long div = 1; - -- BUG_ON(clk->index > 7); -- -- if (!clk->parent) -- return 0; -- - control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index); - if (control & SM_BIT(DIVEN)) - div = 2 * (SM_BFEXT(DIV, control) + 1); -@@ -342,11 +336,6 @@ - u32 control; - unsigned long parent_rate, actual_rate, div; - -- BUG_ON(clk->index > 7); -- -- if (!clk->parent) -- return 0; -- - parent_rate = clk->parent->get_rate(clk->parent); - control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index); - -@@ -373,11 +362,8 @@ - { - u32 control; - -- BUG_ON(clk->index > 7); -- - printk("clk %s: new parent %s (was %s)\n", -- clk->name, parent->name, -- clk->parent ? clk->parent->name : "(null)"); -+ clk->name, parent->name, clk->parent->name); - - control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index); - -@@ -399,6 +385,22 @@ - return 0; - } - -+static void __init genclk_init_parent(struct clk *clk) -+{ -+ u32 control; -+ struct clk *parent; -+ -+ BUG_ON(clk->index > 7); -+ -+ control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index); -+ if (control & SM_BIT(OSCSEL)) -+ parent = (control & SM_BIT(PLLSEL)) ? &pll1 : &osc1; -+ else -+ parent = (control & SM_BIT(PLLSEL)) ? &pll0 : &osc0; -+ -+ clk->parent = parent; -+} -+ - /* -------------------------------------------------------------------- - * System peripherals - * -------------------------------------------------------------------- */ -@@ -464,6 +466,17 @@ - .users = 1, - }; - -+static struct resource dmaca0_resource[] = { -+ { -+ .start = 0xff200000, -+ .end = 0xff20ffff, -+ .flags = IORESOURCE_MEM, -+ }, -+ IRQ(2), -+}; -+DEFINE_DEV(dmaca, 0); -+DEV_CLK(hclk, dmaca0, hsb, 10); -+ - /* -------------------------------------------------------------------- - * PIO - * -------------------------------------------------------------------- */ -@@ -496,19 +509,28 @@ - DEFINE_DEV(pio, 3); - DEV_CLK(mck, pio3, pba, 13); - -+static struct resource pio4_resource[] = { -+ PBMEM(0xffe03800), -+ IRQ(17), -+}; -+DEFINE_DEV(pio, 4); -+DEV_CLK(mck, pio4, pba, 14); -+ - void __init at32_add_system_devices(void) - { -- system_manager.eim_first_irq = NR_INTERNAL_IRQS; -+ system_manager.eim_first_irq = EIM_IRQ_BASE; - - platform_device_register(&at32_sm_device); - platform_device_register(&at32_intc0_device); - platform_device_register(&smc0_device); - platform_device_register(&pdc_device); -+ platform_device_register(&dmaca0_device); - - platform_device_register(&pio0_device); - platform_device_register(&pio1_device); - platform_device_register(&pio2_device); - platform_device_register(&pio3_device); -+ platform_device_register(&pio4_device); - } - - /* -------------------------------------------------------------------- -@@ -521,7 +543,7 @@ - }; - static struct resource atmel_usart0_resource[] = { - PBMEM(0xffe00c00), -- IRQ(7), -+ IRQ(6), - }; - DEFINE_DEV_DATA(atmel_usart, 0); - DEV_CLK(usart, atmel_usart0, pba, 4); -@@ -583,7 +605,7 @@ - select_peripheral(PB(17), PERIPH_B, 0); /* TXD */ - } - --static struct platform_device *at32_usarts[4]; -+static struct platform_device *__initdata at32_usarts[4]; - - void __init at32_map_usart(unsigned int hw_id, unsigned int line) - { -@@ -728,32 +750,156 @@ - /* -------------------------------------------------------------------- - * SPI - * -------------------------------------------------------------------- */ --static struct resource spi0_resource[] = { -+static struct resource atmel_spi0_resource[] = { - PBMEM(0xffe00000), - IRQ(3), - }; --DEFINE_DEV(spi, 0); --DEV_CLK(mck, spi0, pba, 0); -+DEFINE_DEV(atmel_spi, 0); -+DEV_CLK(spi_clk, atmel_spi0, pba, 0); -+ -+static struct resource atmel_spi1_resource[] = { -+ PBMEM(0xffe00400), -+ IRQ(4), -+}; -+DEFINE_DEV(atmel_spi, 1); -+DEV_CLK(spi_clk, atmel_spi1, pba, 1); -+ -+static void __init -+at32_spi_setup_slaves(unsigned int bus_num, struct spi_board_info *b, -+ unsigned int n, const u8 *pins) -+{ -+ unsigned int pin, mode; -+ -+ for (; n; n--, b++) { -+ b->bus_num = bus_num; -+ if (b->chip_select >= 4) -+ continue; -+ pin = (unsigned)b->controller_data; -+ if (!pin) { -+ pin = pins[b->chip_select]; -+ b->controller_data = (void *)pin; -+ } -+ mode = AT32_GPIOF_OUTPUT; -+ if (!(b->mode & SPI_CS_HIGH)) -+ mode |= AT32_GPIOF_HIGH; -+ at32_select_gpio(pin, mode); -+ } -+} - --struct platform_device *__init at32_add_device_spi(unsigned int id) -+struct platform_device *__init -+at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n) - { -+ /* -+ * Manage the chipselects as GPIOs, normally using the same pins -+ * the SPI controller expects; but boards can use other pins. -+ */ -+ static u8 __initdata spi0_pins[] = -+ { GPIO_PIN_PA(3), GPIO_PIN_PA(4), -+ GPIO_PIN_PA(5), GPIO_PIN_PA(20), }; -+ static u8 __initdata spi1_pins[] = -+ { GPIO_PIN_PB(2), GPIO_PIN_PB(3), -+ GPIO_PIN_PB(4), GPIO_PIN_PA(27), }; - struct platform_device *pdev; - - switch (id) { - case 0: -- pdev = &spi0_device; -+ pdev = &atmel_spi0_device; - select_peripheral(PA(0), PERIPH_A, 0); /* MISO */ - select_peripheral(PA(1), PERIPH_A, 0); /* MOSI */ - select_peripheral(PA(2), PERIPH_A, 0); /* SCK */ -- select_peripheral(PA(3), PERIPH_A, 0); /* NPCS0 */ -- select_peripheral(PA(4), PERIPH_A, 0); /* NPCS1 */ -- select_peripheral(PA(5), PERIPH_A, 0); /* NPCS2 */ -+ at32_spi_setup_slaves(0, b, n, spi0_pins); -+ break; -+ -+ case 1: -+ pdev = &atmel_spi1_device; -+ select_peripheral(PB(0), PERIPH_B, 0); /* MISO */ -+ select_peripheral(PB(1), PERIPH_B, 0); /* MOSI */ -+ select_peripheral(PB(5), PERIPH_B, 0); /* SCK */ -+ at32_spi_setup_slaves(1, b, n, spi1_pins); - break; - - default: - return NULL; - } - -+ spi_register_board_info(b, n); -+ platform_device_register(pdev); -+ return pdev; -+} -+ -+/* -------------------------------------------------------------------- -+ * TWI -+ * -------------------------------------------------------------------- */ -+ -+static struct resource atmel_twi0_resource[] = { -+ PBMEM(0xffe00800), -+ IRQ(5), -+}; -+DEFINE_DEV(atmel_twi, 0); -+DEV_CLK(pclk,atmel_twi0,pba,2); -+ -+struct platform_device *__init -+at32_add_device_twi(unsigned int id) -+{ -+ struct platform_device *pdev; -+ -+ switch (id) { -+ case 0: -+ pdev = &atmel_twi0_device; -+ select_peripheral(PA(6), PERIPH_A, 0); /* SDA */ -+ select_peripheral(PA(7), PERIPH_A, 0); /* SCL */ -+ break; -+ -+ default: -+ return NULL; -+ } -+ -+ platform_device_register(pdev); -+ return pdev; -+} -+ -+/* -------------------------------------------------------------------- -+ * MMC -+ * -------------------------------------------------------------------- */ -+static struct mci_platform_data atmel_mci0_data = { -+ .detect_pin = GPIO_PIN_NONE, -+ .wp_pin = GPIO_PIN_NONE, -+}; -+static struct resource atmel_mci0_resource[] = { -+ PBMEM(0xfff02400), -+ IRQ(28), -+}; -+DEFINE_DEV_DATA(atmel_mci, 0); -+DEV_CLK(mci_clk, atmel_mci0, pbb, 9); -+ -+struct platform_device *__init -+at32_add_device_mci(unsigned int id, struct mci_platform_data *data) -+{ -+ struct platform_device *pdev; -+ -+ switch (id) { -+ case 0: -+ pdev = &atmel_mci0_device; -+ select_peripheral(PA(10), PERIPH_A, 0); /* CLK */ -+ select_peripheral(PA(11), PERIPH_A, 0); /* CMD */ -+ select_peripheral(PA(12), PERIPH_A, 0); /* DATA0 */ -+ select_peripheral(PA(13), PERIPH_A, 0); /* DATA1 */ -+ select_peripheral(PA(14), PERIPH_A, 0); /* DATA2 */ -+ select_peripheral(PA(15), PERIPH_A, 0); /* DATA3 */ -+ break; -+ default: -+ return NULL; -+ } -+ -+ if (data) { -+ if (data->detect_pin != GPIO_PIN_NONE) -+ at32_select_gpio(data->detect_pin, 0); -+ if (data->wp_pin != GPIO_PIN_NONE) -+ at32_select_gpio(data->wp_pin, 0); -+ memcpy(pdev->dev.platform_data, data, -+ sizeof(struct mci_platform_data)); -+ } -+ - platform_device_register(pdev); - return pdev; - } -@@ -837,6 +983,199 @@ - return pdev; - } - -+/* -------------------------------------------------------------------- -+ * USB Device Controller -+ * -------------------------------------------------------------------- */ -+static struct resource usba0_resource[] = { -+ { -+ .start = 0xff300000, -+ .end = 0xff3fffff, -+ .flags = IORESOURCE_MEM, -+ }, -+ PBMEM(0xfff03000), -+ IRQ(31), -+}; -+DEFINE_DEV(usba, 0); -+DEV_CLK(pclk, usba0, pbb, 12); -+DEV_CLK(hclk, usba0, hsb, 6); -+ -+struct platform_device *__init at32_add_device_usba(unsigned int id) -+{ -+ struct platform_device *pdev; -+ -+ switch (id) { -+ case 0: -+ pdev = &usba0_device; -+ /* USB pads are not multiplexed */ -+ break; -+ default: -+ return NULL; -+ } -+ -+ platform_device_register(pdev); -+ return pdev; -+} -+ -+/* -------------------------------------------------------------------- -+ * AC97C -+ * -------------------------------------------------------------------- */ -+static struct resource atmel_ac97c0_resource[] = { -+ PBMEM(0xfff02800), -+ IRQ(29), -+}; -+DEFINE_DEV(atmel_ac97c, 0); -+DEV_CLK(pclk, atmel_ac97c0, pbb, 10); -+ -+struct platform_device *__init -+at32_add_device_ac97c(unsigned int id) -+{ -+ struct platform_device *pdev; -+ -+ switch (id) { -+ case 0: -+ pdev = &atmel_ac97c0_device; -+ select_peripheral(PB(20), PERIPH_B, 0); /* SYNC */ -+ select_peripheral(PB(21), PERIPH_B, 0); /* SDO */ -+ select_peripheral(PB(22), PERIPH_B, 0); /* SDI */ -+ select_peripheral(PB(23), PERIPH_B, 0); /* SCLK */ -+ break; -+ default: -+ return NULL; -+ } -+ -+ platform_device_register(pdev); -+ return pdev; -+} -+ -+/* -------------------------------------------------------------------- -+ * DAC -+ * -------------------------------------------------------------------- */ -+static struct resource abdac0_resource[] = { -+ PBMEM(0xfff02000), -+ IRQ(27), -+}; -+DEFINE_DEV(abdac, 0); -+DEV_CLK(pclk, abdac0, pbb, 8); -+static struct clk abdac0_sample_clk = { -+ .name = "sample_clk", -+ .dev = &abdac0_device.dev, -+ .mode = genclk_mode, -+ .get_rate = genclk_get_rate, -+ .set_rate = genclk_set_rate, -+ .set_parent = genclk_set_parent, -+ .index = 6, -+}; -+ -+struct platform_device *__init -+at32_add_device_abdac(unsigned int id) -+{ -+ struct platform_device *pdev; -+ -+ switch (id) { -+ case 0: -+ pdev = &abdac0_device; -+ select_peripheral(PB(20), PERIPH_A, 0); /* DATA1 */ -+ select_peripheral(PB(21), PERIPH_A, 0); /* DATA0 */ -+ select_peripheral(PB(22), PERIPH_A, 0); /* DATAN1 */ -+ select_peripheral(PB(23), PERIPH_A, 0); /* DATAN0 */ -+ break; -+ default: -+ return NULL; -+ } -+ -+ platform_device_register(pdev); -+ return pdev; -+} -+ -+/* -------------------------------------------------------------------- -+ * ISI -+ * -------------------------------------------------------------------- */ -+static struct resource atmel_isi0_resource[] = { -+ PBMEM(0xfff02c00), -+ IRQ(30), -+}; -+DEFINE_DEV(atmel_isi, 0); -+DEV_CLK(hclk, atmel_isi0, hsb, 5); -+DEV_CLK(pclk, atmel_isi0, pbb, 11); -+ -+struct platform_device *__init -+at32_add_device_isi(unsigned int id) -+{ -+ struct platform_device *pdev; -+ -+ switch (id) { -+ case 0: -+ pdev = &atmel_isi0_device; -+ select_peripheral(PB(0), PERIPH_A, 0); /* DATA0 */ -+ select_peripheral(PB(1), PERIPH_A, 0); /* DATA1 */ -+ select_peripheral(PB(2), PERIPH_A, 0); /* DATA2 */ -+ select_peripheral(PB(3), PERIPH_A, 0); /* DATA3 */ -+ select_peripheral(PB(4), PERIPH_A, 0); /* DATA4 */ -+ select_peripheral(PB(5), PERIPH_A, 0); /* DATA5 */ -+ select_peripheral(PB(6), PERIPH_A, 0); /* DATA6 */ -+ select_peripheral(PB(7), PERIPH_A, 0); /* DATA7 */ -+ select_peripheral(PB(11), PERIPH_B, 0); /* DATA8 */ -+ select_peripheral(PB(12), PERIPH_B, 0); /* DATA9 */ -+ select_peripheral(PB(13), PERIPH_B, 0); /* DATA10 */ -+ select_peripheral(PB(14), PERIPH_B, 0); /* DATA11 */ -+ select_peripheral(PB(8), PERIPH_A, 0); /* HSYNC */ -+ select_peripheral(PB(9), PERIPH_A, 0); /* VSYNC */ -+ select_peripheral(PB(10), PERIPH_A, 0); /* PCLK */ -+ break; -+ -+ default: -+ return NULL; -+ } -+ -+ platform_device_register(pdev); -+ -+ return pdev; -+} -+ -+/* -------------------------------------------------------------------- -+ * GCLK -+ * -------------------------------------------------------------------- */ -+static struct clk gclk0 = { -+ .name = "gclk0", -+ .mode = genclk_mode, -+ .get_rate = genclk_get_rate, -+ .set_rate = genclk_set_rate, -+ .set_parent = genclk_set_parent, -+ .index = 0, -+}; -+static struct clk gclk1 = { -+ .name = "gclk1", -+ .mode = genclk_mode, -+ .get_rate = genclk_get_rate, -+ .set_rate = genclk_set_rate, -+ .set_parent = genclk_set_parent, -+ .index = 1, -+}; -+static struct clk gclk2 = { -+ .name = "gclk2", -+ .mode = genclk_mode, -+ .get_rate = genclk_get_rate, -+ .set_rate = genclk_set_rate, -+ .set_parent = genclk_set_parent, -+ .index = 2, -+}; -+static struct clk gclk3 = { -+ .name = "gclk3", -+ .mode = genclk_mode, -+ .get_rate = genclk_get_rate, -+ .set_rate = genclk_set_rate, -+ .set_parent = genclk_set_parent, -+ .index = 3, -+}; -+static struct clk gclk4 = { -+ .name = "gclk4", -+ .mode = genclk_mode, -+ .get_rate = genclk_get_rate, -+ .set_rate = genclk_set_rate, -+ .set_parent = genclk_set_parent, -+ .index = 4, -+}; -+ - struct clk *at32_clock_list[] = { - &osc32k, - &osc0, -@@ -855,11 +1194,13 @@ - &smc0_mck, - &pdc_hclk, - &pdc_pclk, -+ &dmaca0_hclk, - &pico_clk, - &pio0_mck, - &pio1_mck, - &pio2_mck, - &pio3_mck, -+ &pio4_mck, - &atmel_usart0_usart, - &atmel_usart1_usart, - &atmel_usart2_usart, -@@ -868,9 +1209,24 @@ - &macb0_pclk, - &macb1_hclk, - &macb1_pclk, -- &spi0_mck, -+ &atmel_spi0_spi_clk, -+ &atmel_spi1_spi_clk, -+ &atmel_twi0_pclk, -+ &atmel_mci0_mci_clk, - &lcdc0_hclk, - &lcdc0_pixclk, -+ &usba0_pclk, -+ &usba0_hclk, -+ &atmel_ac97c0_pclk, -+ &abdac0_pclk, -+ &abdac0_sample_clk, -+ &gclk0, -+ &gclk1, -+ &gclk2, -+ &gclk3, -+ &gclk4, -+ &atmel_isi0_hclk, -+ &atmel_isi0_pclk, - }; - unsigned int at32_nr_clocks = ARRAY_SIZE(at32_clock_list); - -@@ -880,6 +1236,7 @@ - at32_init_pio(&pio1_device); - at32_init_pio(&pio2_device); - at32_init_pio(&pio3_device); -+ at32_init_pio(&pio4_device); - } - - void __init at32_clock_init(void) -@@ -898,6 +1255,14 @@ - if (sm_readl(sm, PM_PLL1) & SM_BIT(PLLOSC)) - pll1.parent = &osc1; - -+ genclk_init_parent(&gclk0); -+ genclk_init_parent(&gclk1); -+ genclk_init_parent(&gclk2); -+ genclk_init_parent(&gclk3); -+ genclk_init_parent(&gclk4); -+ genclk_init_parent(&lcdc0_pixclk); -+ genclk_init_parent(&abdac0_sample_clk); -+ - /* - * Turn on all clocks that have at least one user already, and - * turn off everything else. We only do this for module -diff -urN linux-2.6.20.4-0rig/arch/avr32/mach-at32ap/clock.c linux-2.6.20.4-atmel/arch/avr32/mach-at32ap/clock.c ---- linux-2.6.20.4-0rig/arch/avr32/mach-at32ap/clock.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/avr32/mach-at32ap/clock.c 2007-03-24 16:42:28.000000000 +0100 -@@ -63,7 +63,11 @@ - - static void __clk_disable(struct clk *clk) - { -- BUG_ON(clk->users == 0); -+ if (clk->users == 0) { -+ printk(KERN_ERR "%s: mismatched disable\n", clk->name); -+ WARN_ON(1); -+ return; -+ } - - if (--clk->users == 0 && clk->mode) - clk->mode(clk, 0); -diff -urN linux-2.6.20.4-0rig/arch/avr32/mach-at32ap/extint.c linux-2.6.20.4-atmel/arch/avr32/mach-at32ap/extint.c ---- linux-2.6.20.4-0rig/arch/avr32/mach-at32ap/extint.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/avr32/mach-at32ap/extint.c 2007-03-24 16:42:28.000000000 +0100 -@@ -55,20 +55,11 @@ - unsigned long flags; - int ret = 0; - -+ flow_type &= IRQ_TYPE_SENSE_MASK; - if (flow_type == IRQ_TYPE_NONE) - flow_type = IRQ_TYPE_LEVEL_LOW; - - desc = &irq_desc[irq]; -- desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL); -- desc->status |= flow_type & IRQ_TYPE_SENSE_MASK; -- -- if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) { -- desc->status |= IRQ_LEVEL; -- set_irq_handler(irq, handle_level_irq); -- } else { -- set_irq_handler(irq, handle_edge_irq); -- } -- - spin_lock_irqsave(&sm->lock, flags); - - mode = sm_readl(sm, EIM_MODE); -@@ -97,9 +88,16 @@ - break; - } - -- sm_writel(sm, EIM_MODE, mode); -- sm_writel(sm, EIM_EDGE, edge); -- sm_writel(sm, EIM_LEVEL, level); -+ if (ret == 0) { -+ sm_writel(sm, EIM_MODE, mode); -+ sm_writel(sm, EIM_EDGE, edge); -+ sm_writel(sm, EIM_LEVEL, level); -+ -+ if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) -+ flow_type |= IRQ_LEVEL; -+ desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL); -+ desc->status |= flow_type; -+ } - - spin_unlock_irqrestore(&sm->lock, flags); - -@@ -122,8 +120,6 @@ - unsigned long status, pending; - unsigned int i, ext_irq; - -- spin_lock(&sm->lock); -- - status = sm_readl(sm, EIM_ISR); - pending = status & sm_readl(sm, EIM_IMR); - -@@ -133,10 +129,11 @@ - - ext_irq = i + sm->eim_first_irq; - ext_desc = irq_desc + ext_irq; -- ext_desc->handle_irq(ext_irq, ext_desc); -+ if (ext_desc->status & IRQ_LEVEL) -+ handle_level_irq(ext_irq, ext_desc); -+ else -+ handle_edge_irq(ext_irq, ext_desc); - } -- -- spin_unlock(&sm->lock); - } - - static int __init eim_init(void) -@@ -168,8 +165,9 @@ - sm->eim_chip = &eim_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, -- handle_edge_irq); -+ handle_level_irq); - set_irq_chip_data(sm->eim_first_irq + i, sm); - } - -diff -urN linux-2.6.20.4-0rig/arch/avr32/mach-at32ap/hsmc.c linux-2.6.20.4-atmel/arch/avr32/mach-at32ap/hsmc.c ---- linux-2.6.20.4-0rig/arch/avr32/mach-at32ap/hsmc.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/avr32/mach-at32ap/hsmc.c 2007-03-24 16:42:29.000000000 +0100 -@@ -75,12 +75,35 @@ - return -EINVAL; - } - -+ switch (config->nwait_mode) { -+ case 0: -+ mode |= HSMC_BF(EXNW_MODE, HSMC_EXNW_MODE_DISABLED); -+ break; -+ case 1: -+ mode |= HSMC_BF(EXNW_MODE, HSMC_EXNW_MODE_RESERVED); -+ break; -+ case 2: -+ mode |= HSMC_BF(EXNW_MODE, HSMC_EXNW_MODE_FROZEN); -+ break; -+ case 3: -+ mode |= HSMC_BF(EXNW_MODE, HSMC_EXNW_MODE_READY); -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ if (config->tdf_cycles) { -+ mode |= HSMC_BF(TDF_CYCLES, config->tdf_cycles); -+ } -+ - if (config->nrd_controlled) - mode |= HSMC_BIT(READ_MODE); - if (config->nwe_controlled) - mode |= HSMC_BIT(WRITE_MODE); - if (config->byte_write) - mode |= HSMC_BIT(BAT); -+ if (config->tdf_mode) -+ mode |= HSMC_BIT(TDF_MODE); - - pr_debug("smc cs%d: setup/%08x pulse/%08x cycle/%08x mode/%08x\n", - cs, setup, pulse, cycle, mode); -diff -urN linux-2.6.20.4-0rig/arch/avr32/mach-at32ap/Kconfig linux-2.6.20.4-atmel/arch/avr32/mach-at32ap/Kconfig ---- linux-2.6.20.4-0rig/arch/avr32/mach-at32ap/Kconfig 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/avr32/mach-at32ap/Kconfig 2007-03-24 16:42:29.000000000 +0100 -@@ -0,0 +1,15 @@ -+if PLATFORM_AT32AP -+ -+menu "Atmel AVR32 AP options" -+ -+config PIO_DEV -+ bool "PIO /dev interface" -+ select CONFIGFS_FS -+ default y -+ help -+ Say `Y' to enable a /dev interface to the Parallel I/O -+ Controller. -+ -+endmenu -+ -+endif -diff -urN linux-2.6.20.4-0rig/arch/avr32/mach-at32ap/Makefile linux-2.6.20.4-atmel/arch/avr32/mach-at32ap/Makefile ---- linux-2.6.20.4-0rig/arch/avr32/mach-at32ap/Makefile 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/avr32/mach-at32ap/Makefile 2007-03-24 16:42:28.000000000 +0100 -@@ -1,2 +1,2 @@ --obj-y += at32ap.o clock.o pio.o intc.o extint.o hsmc.o -+obj-y += at32ap.o clock.o intc.o extint.o pio.o hsmc.o - obj-$(CONFIG_CPU_AT32AP7000) += at32ap7000.o -diff -urN linux-2.6.20.4-0rig/arch/avr32/mach-at32ap/pio.c linux-2.6.20.4-atmel/arch/avr32/mach-at32ap/pio.c ---- linux-2.6.20.4-0rig/arch/avr32/mach-at32ap/pio.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/avr32/mach-at32ap/pio.c 2007-03-24 16:42:29.000000000 +0100 -@@ -12,7 +12,9 @@ - #include <linux/debugfs.h> - #include <linux/fs.h> - #include <linux/platform_device.h> -+#include <linux/irq.h> - -+#include <asm/gpio.h> - #include <asm/io.h> - - #include <asm/arch/portmux.h> -@@ -23,10 +25,11 @@ - - struct pio_device { - void __iomem *regs; -- const struct platform_device *pdev; -+ struct platform_device *pdev; - struct clk *clk; - u32 pinmux_mask; -- char name[32]; -+ u32 gpio_mask; -+ char name[8]; - }; - - static struct pio_device pio_dev[MAX_NR_PIO_DEVICES]; -@@ -76,6 +79,9 @@ - if (!(flags & AT32_GPIOF_PULLUP)) - pio_writel(pio, PUDR, mask); - -+ /* gpio_request NOT allowed */ -+ set_bit(pin_index, &pio->gpio_mask); -+ - return; - - fail: -@@ -99,19 +105,52 @@ - goto fail; - } - -- pio_writel(pio, PUER, mask); -- if (flags & AT32_GPIOF_HIGH) -- pio_writel(pio, SODR, mask); -- else -- pio_writel(pio, CODR, mask); -- if (flags & AT32_GPIOF_OUTPUT) -+ if (flags & AT32_GPIOF_OUTPUT) { -+ if (flags & AT32_GPIOF_HIGH) -+ pio_writel(pio, SODR, mask); -+ else -+ pio_writel(pio, CODR, mask); -+ pio_writel(pio, PUDR, mask); - pio_writel(pio, OER, mask); -- else -+ } else { -+ if (flags & AT32_GPIOF_PULLUP) -+ pio_writel(pio, PUER, mask); -+ else -+ pio_writel(pio, PUDR, mask); -+ if (flags & AT32_GPIOF_DEGLITCH) -+ pio_writel(pio, IFER, mask); -+ else -+ pio_writel(pio, IFDR, mask); - pio_writel(pio, ODR, mask); -+ } - - pio_writel(pio, PER, mask); -- if (!(flags & AT32_GPIOF_PULLUP)) -- pio_writel(pio, PUDR, mask); -+ -+ /* gpio_request now allowed */ -+ clear_bit(pin_index, &pio->gpio_mask); -+ -+ return; -+ -+fail: -+ dump_stack(); -+} -+ -+/* Reserve a pin, preventing anyone else from changing its configuration. */ -+void __init at32_reserve_pin(unsigned int pin) -+{ -+ struct pio_device *pio; -+ unsigned int pin_index = pin & 0x1f; -+ -+ pio = gpio_to_pio(pin); -+ if (unlikely(!pio)) { -+ printk("pio: invalid pin %u\n", pin); -+ goto fail; -+ } -+ -+ if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask))) { -+ printk("%s: pin %u is busy\n", pio->name, pin_index); -+ goto fail; -+ } - - return; - -@@ -119,20 +158,793 @@ - dump_stack(); - } - -+/*--------------------------------------------------------------------------*/ -+ -+static unsigned int pio_id(struct pio_device *pio) -+{ -+ return pio - pio_dev; -+} -+ -+static void __disable_gpio(struct pio_device *pio, u32 mask) -+{ -+ pio_writel(pio, PUER, mask); -+ pio_writel(pio, ODR, mask); -+} -+ -+static void pio_dealloc_mask(struct pio_device *pio, u32 mask) -+{ -+ u32 old, new; -+ -+ do { -+ old = pio->pinmux_mask; -+ new = old & ~mask; -+ } while (cmpxchg(&pio->pinmux_mask, old, new) != old); -+} -+ -+/* GPIO API */ -+ -+int gpio_request(unsigned int gpio, const char *label) -+{ -+ struct pio_device *pio; -+ unsigned int pin; -+ -+ pio = gpio_to_pio(gpio); -+ if (!pio) -+ return -ENODEV; -+ -+ pin = gpio & 0x1f; -+ if (test_and_set_bit(pin, &pio->gpio_mask)) -+ return -EBUSY; -+ -+ return 0; -+} -+EXPORT_SYMBOL(gpio_request); -+ -+void gpio_free(unsigned int gpio) -+{ -+ struct pio_device *pio; -+ unsigned int pin; -+ -+ pio = gpio_to_pio(gpio); -+ if (!pio) { -+ printk(KERN_ERR -+ "gpio: attempted to free invalid pin %u\n", gpio); -+ return; -+ } -+ -+ pin = gpio & 0x1f; -+ if (!test_and_clear_bit(pin, &pio->gpio_mask)) -+ printk(KERN_ERR "gpio: freeing free or non-gpio pin %s-%u\n", -+ pio->name, pin); -+} -+EXPORT_SYMBOL(gpio_free); -+ -+int gpio_direction_input(unsigned int gpio) -+{ -+ struct pio_device *pio; -+ unsigned int pin; -+ -+ pio = gpio_to_pio(gpio); -+ if (!pio) -+ return -ENODEV; -+ -+ pin = gpio & 0x1f; -+ pio_writel(pio, ODR, 1 << pin); -+ -+ return 0; -+} -+EXPORT_SYMBOL(gpio_direction_input); -+ -+int gpio_direction_output(unsigned int gpio) -+{ -+ struct pio_device *pio; -+ unsigned int pin; -+ -+ pio = gpio_to_pio(gpio); -+ if (!pio) -+ return -ENODEV; -+ -+ pin = gpio & 0x1f; -+ pio_writel(pio, OER, 1 << pin); -+ -+ return 0; -+} -+EXPORT_SYMBOL(gpio_direction_output); -+ -+int gpio_get_value(unsigned int gpio) -+{ -+ struct pio_device *pio = &pio_dev[gpio >> 5]; -+ -+ return (pio_readl(pio, PDSR) >> (gpio & 0x1f)) & 1; -+} -+EXPORT_SYMBOL(gpio_get_value); -+ -+void gpio_set_value(unsigned int gpio, int value) -+{ -+ struct pio_device *pio = &pio_dev[gpio >> 5]; -+ u32 mask; -+ -+ mask = 1 << (gpio & 0x1f); -+ if (value) -+ pio_writel(pio, SODR, mask); -+ else -+ pio_writel(pio, CODR, mask); -+} -+EXPORT_SYMBOL(gpio_set_value); -+ -+/*--------------------------------------------------------------------------*/ -+ -+/* GPIO IRQ support */ -+ -+static void gpio_irq_mask(unsigned irq) -+{ -+ unsigned gpio = irq_to_gpio(irq); -+ struct pio_device *pio = &pio_dev[gpio >> 5]; -+ -+ pio_writel(pio, IDR, 1 << (gpio & 0x1f)); -+} -+ -+static void gpio_irq_unmask(unsigned irq) -+{ -+ unsigned gpio = irq_to_gpio(irq); -+ struct pio_device *pio = &pio_dev[gpio >> 5]; -+ -+ pio_writel(pio, IER, 1 << (gpio & 0x1f)); -+} -+ -+static int gpio_irq_type(unsigned irq, unsigned type) -+{ -+ if (type != IRQ_TYPE_EDGE_BOTH && type != IRQ_TYPE_NONE) -+ return -EINVAL; -+ -+ return 0; -+} -+ -+static struct irq_chip gpio_irqchip = { -+ .name = "gpio", -+ .mask = gpio_irq_mask, -+ .unmask = gpio_irq_unmask, -+ .set_type = gpio_irq_type, -+}; -+ -+static void gpio_irq_handler(unsigned irq, struct irq_desc *desc) -+{ -+ struct pio_device *pio = get_irq_chip_data(irq); -+ unsigned gpio_irq; -+ -+ gpio_irq = (unsigned) get_irq_data(irq); -+ for (;;) { -+ u32 isr; -+ struct irq_desc *d; -+ -+ /* ack pending GPIO interrupts */ -+ isr = pio_readl(pio, ISR) & pio_readl(pio, IMR); -+ if (!isr) -+ break; -+ do { -+ int i; -+ -+ i = ffs(isr) - 1; -+ isr &= ~(1 << i); -+ -+ i += gpio_irq; -+ d = &irq_desc[i]; -+ -+ d->handle_irq(i, d); -+ } while (isr); -+ } -+} -+ -+static void __init -+gpio_irq_setup(struct pio_device *pio, int irq, int gpio_irq) -+{ -+ unsigned i; -+ -+ set_irq_chip_data(irq, pio); -+ set_irq_data(irq, (void *) gpio_irq); -+ -+ for (i = 0; i < 32; i++, gpio_irq++) { -+ set_irq_chip_data(gpio_irq, pio); -+ set_irq_chip_and_handler(gpio_irq, &gpio_irqchip, -+ handle_simple_irq); -+ } -+ -+ set_irq_chained_handler(irq, gpio_irq_handler); -+} -+ -+/*--------------------------------------------------------------------------*/ -+ -+#ifdef CONFIG_PIO_DEV -+#include <linux/configfs.h> -+#include <linux/cdev.h> -+#include <linux/fs.h> -+#include <linux/interrupt.h> -+#include <linux/poll.h> -+#include <linux/uaccess.h> -+#include <linux/wait.h> -+ -+#define GPIO_DEV_MAX 8 -+ -+static struct class *gpio_dev_class; -+static dev_t gpio_devt; -+ -+struct gpio_item { -+ spinlock_t lock; -+ -+ struct pio_device *pio; -+ -+ int enabled; -+ int pio_id; -+ u32 pin_mask; -+ u32 oe_mask; -+ -+ /* Pin state last time we read it (for blocking reads) */ -+ u32 pin_state; -+ int changed; -+ -+ wait_queue_head_t change_wq; -+ struct fasync_struct *async_queue; -+ -+ int id; -+ struct class_device *gpio_dev; -+ struct cdev char_dev; -+ struct config_item item; -+}; -+ -+struct gpio_attribute { -+ struct configfs_attribute attr; -+ ssize_t (*show)(struct gpio_item *, char *); -+ ssize_t (*store)(struct gpio_item *, const char *, size_t); -+}; -+ -+static irqreturn_t gpio_dev_interrupt(int irq, void *dev_id) -+{ -+ struct gpio_item *gpio = dev_id; -+ u32 old_state, new_state; -+ -+ old_state = gpio->pin_state; -+ new_state = pio_readl(gpio->pio, PDSR); -+ gpio->pin_state = new_state; -+ -+ if (new_state != old_state) { -+ gpio->changed = 1; -+ wake_up_interruptible(&gpio->change_wq); -+ -+ if (gpio->async_queue) -+ kill_fasync(&gpio->async_queue, SIGIO, POLL_IN); -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+static int gpio_dev_open(struct inode *inode, struct file *file) -+{ -+ struct gpio_item *gpio = container_of(inode->i_cdev, -+ struct gpio_item, -+ char_dev); -+ unsigned int irq; -+ unsigned int i; -+ int ret; -+ -+ nonseekable_open(inode, file); -+ config_item_get(&gpio->item); -+ file->private_data = gpio; -+ -+ gpio->pin_state = pio_readl(gpio->pio, PDSR) & gpio->pin_mask; -+ gpio->changed = 1; -+ -+ for (i = 0; i < 32; i++) { -+ if (gpio->pin_mask & (1 << i)) { -+ irq = gpio_to_irq(32 * pio_id(gpio->pio) + i); -+ ret = request_irq(irq, gpio_dev_interrupt, 0, -+ "gpio-dev", gpio); -+ if (ret) -+ goto err_irq; -+ } -+ } -+ -+ return 0; -+ -+err_irq: -+ while (i--) { -+ if (gpio->pin_mask & (1 << i)) { -+ irq = gpio_to_irq(32 * pio_id(gpio->pio) + i); -+ free_irq(irq, gpio); -+ } -+ } -+ -+ config_item_put(&gpio->item); -+ -+ return ret; -+} -+ -+static int gpio_dev_fasync(int fd, struct file *file, int mode) -+{ -+ struct gpio_item *gpio = file->private_data; -+ -+ return fasync_helper(fd, file, mode, &gpio->async_queue); -+} -+ -+static int gpio_dev_release(struct inode *inode, struct file *file) -+{ -+ struct gpio_item *gpio = file->private_data; -+ unsigned int irq; -+ unsigned int i; -+ -+ gpio_dev_fasync(-1, file, 0); -+ -+ for (i = 0; i < 32; i++) { -+ if (gpio->pin_mask & (1 << i)) { -+ irq = gpio_to_irq(32 * pio_id(gpio->pio) + i); -+ free_irq(irq, gpio); -+ } -+ } -+ -+ config_item_put(&gpio->item); -+ -+ return 0; -+} -+ -+static unsigned int gpio_dev_poll(struct file *file, poll_table *wait) -+{ -+ struct gpio_item *gpio = file->private_data; -+ unsigned int mask = 0; -+ -+ poll_wait(file, &gpio->change_wq, wait); -+ if (gpio->changed) -+ mask |= POLLIN | POLLRDNORM; -+ -+ return mask; -+} -+ -+static ssize_t gpio_dev_read(struct file *file, char __user *buf, -+ size_t count, loff_t *offset) -+{ -+ struct gpio_item *gpio = file->private_data; -+ u32 value; -+ -+ spin_lock_irq(&gpio->lock); -+ while (!gpio->changed) { -+ spin_unlock_irq(&gpio->lock); -+ -+ if (file->f_flags & O_NONBLOCK) -+ return -EAGAIN; -+ -+ if (wait_event_interruptible(gpio->change_wq, gpio->changed)) -+ return -ERESTARTSYS; -+ -+ spin_lock_irq(&gpio->lock); -+ } -+ -+ gpio->changed = 0; -+ value = pio_readl(gpio->pio, PDSR) & gpio->pin_mask; -+ -+ spin_unlock_irq(&gpio->lock); -+ -+ count = min(count, (size_t)4); -+ if (copy_to_user(buf, &value, count)) -+ return -EFAULT; -+ -+ return count; -+} -+ -+static ssize_t gpio_dev_write(struct file *file, const char __user *buf, -+ size_t count, loff_t *offset) -+{ -+ struct gpio_item *gpio = file->private_data; -+ u32 value = 0; -+ u32 mask = ~0UL; -+ -+ count = min(count, (size_t)4); -+ if (copy_from_user(&value, buf, count)) -+ return -EFAULT; -+ -+ /* Assuming big endian */ -+ mask <<= (4 - count) * 8; -+ mask &= gpio->pin_mask; -+ -+ pio_writel(gpio->pio, CODR, ~value & mask); -+ pio_writel(gpio->pio, SODR, value & mask); -+ -+ return count; -+} -+ -+static struct file_operations gpio_dev_fops = { -+ .owner = THIS_MODULE, -+ .llseek = no_llseek, -+ .open = gpio_dev_open, -+ .release = gpio_dev_release, -+ .fasync = gpio_dev_fasync, -+ .poll = gpio_dev_poll, -+ .read = gpio_dev_read, -+ .write = gpio_dev_write, -+}; -+ -+static struct gpio_item *to_gpio_item(struct config_item *item) -+{ -+ return item ? container_of(item, struct gpio_item, item) : NULL; -+} -+ -+static ssize_t gpio_show_gpio_id(struct gpio_item *gpio, char *page) -+{ -+ return sprintf(page, "%d\n", gpio->pio_id); -+} -+ -+static ssize_t gpio_store_gpio_id(struct gpio_item *gpio, -+ const char *page, size_t count) -+{ -+ unsigned long id; -+ char *p = (char *)page; -+ ssize_t ret = -EINVAL; -+ -+ id = simple_strtoul(p, &p, 0); -+ if (!p || (*p && (*p != '\n'))) -+ return -EINVAL; -+ -+ /* Switching PIO is not allowed when live... */ -+ spin_lock(&gpio->lock); -+ if (!gpio->enabled) { -+ ret = -ENXIO; -+ if ((id < MAX_NR_PIO_DEVICES) && pio_dev[id].regs) { -+ gpio->pio_id = id; -+ ret = count; -+ } -+ } -+ spin_unlock(&gpio->lock); -+ -+ return ret; -+} -+ -+static ssize_t gpio_show_pin_mask(struct gpio_item *gpio, char *page) -+{ -+ return sprintf(page, "0x%08x\n", gpio->pin_mask); -+} -+ -+static ssize_t gpio_store_pin_mask(struct gpio_item *gpio, -+ const char *page, size_t count) -+{ -+ u32 new_mask; -+ char *p = (char *)page; -+ ssize_t ret = -EINVAL; -+ -+ new_mask = simple_strtoul(p, &p, 0); -+ if (!p || (*p && (*p != '\n'))) -+ return -EINVAL; -+ -+ /* Can't update the pin mask while live. */ -+ spin_lock(&gpio->lock); -+ if (!gpio->enabled) { -+ gpio->oe_mask &= new_mask; -+ gpio->pin_mask = new_mask; -+ ret = count; -+ } -+ spin_unlock(&gpio->lock); -+ -+ return ret; -+} -+ -+static ssize_t gpio_show_oe_mask(struct gpio_item *gpio, char *page) -+{ -+ return sprintf(page, "0x%08x\n", gpio->oe_mask); -+} -+ -+static ssize_t gpio_store_oe_mask(struct gpio_item *gpio, -+ const char *page, size_t count) -+{ -+ u32 mask; -+ char *p = (char *)page; -+ ssize_t ret = -EINVAL; -+ -+ mask = simple_strtoul(p, &p, 0); -+ if (!p || (*p && (*p != '\n'))) -+ return -EINVAL; -+ -+ spin_lock(&gpio->lock); -+ if (!gpio->enabled) { -+ gpio->oe_mask = mask & gpio->pin_mask; -+ ret = count; -+ } -+ spin_unlock(&gpio->lock); -+ -+ return ret; -+} -+ -+static ssize_t gpio_show_enabled(struct gpio_item *gpio, char *page) -+{ -+ return sprintf(page, "%d\n", gpio->enabled); -+} -+ -+static ssize_t gpio_store_enabled(struct gpio_item *gpio, -+ const char *page, size_t count) -+{ -+ struct pio_device *pio; -+ u32 old, new; -+ char *p = (char *)page; -+ int enabled; -+ int ret; -+ -+ enabled = simple_strtoul(p, &p, 0); -+ if (!p || (*p && (*p != '\n'))) -+ return -EINVAL; -+ -+ /* make it a boolean value */ -+ enabled = !!enabled; -+ -+ if (gpio->enabled == enabled) -+ /* Already enabled; do nothing. */ -+ return count; -+ -+ BUG_ON(gpio->id >= GPIO_DEV_MAX); -+ -+ if (!enabled) { -+ class_device_unregister(gpio->gpio_dev); -+ cdev_del(&gpio->char_dev); -+ __disable_gpio(gpio->pio, gpio->pin_mask); -+ pio_dealloc_mask(gpio->pio, gpio->pin_mask); -+ gpio->pio = NULL; -+ } else { -+ if (gpio->pio_id < 0 || !gpio->pin_mask) -+ return -ENODEV; -+ } -+ -+ /* Disallow any updates to gpio_id or pin_mask */ -+ spin_lock(&gpio->lock); -+ gpio->enabled = enabled; -+ spin_unlock(&gpio->lock); -+ -+ if (!enabled) -+ return count; -+ -+ /* Now, try to allocate the pins */ -+ ret = -EBUSY; -+ pio = gpio->pio = &pio_dev[gpio->pio_id]; -+ do { -+ old = pio->pinmux_mask; -+ if (old & gpio->pin_mask) -+ goto err_alloc_pins; -+ -+ new = old | gpio->pin_mask; -+ } while (cmpxchg(&pio->pinmux_mask, old, new) != old); -+ -+ pio_writel(pio, OER, gpio->oe_mask); -+ pio_writel(pio, PER, gpio->pin_mask); -+ -+ cdev_init(&gpio->char_dev, &gpio_dev_fops); -+ gpio->char_dev.owner = THIS_MODULE; -+ ret = cdev_add(&gpio->char_dev, MKDEV(MAJOR(gpio_devt), gpio->id), 1); -+ if (ret < 0) -+ goto err_cdev_add; -+ gpio->gpio_dev = class_device_create(gpio_dev_class, NULL, -+ MKDEV(MAJOR(gpio_devt), gpio->id), -+ &gpio->pio->pdev->dev, -+ "gpio%d", gpio->id); -+ if (IS_ERR(gpio->gpio_dev)) { -+ printk(KERN_ERR "failed to create gpio%d\n", gpio->id); -+ ret = PTR_ERR(gpio->gpio_dev); -+ goto err_class_dev; -+ } -+ -+ printk(KERN_INFO "created gpio%d (pio%d/0x%08x) as (%d:%d)\n", -+ gpio->id, pio_id(gpio->pio), gpio->pin_mask, -+ MAJOR(gpio->gpio_dev->devt), MINOR(gpio->gpio_dev->devt)); -+ -+ return 0; -+ -+err_class_dev: -+ cdev_del(&gpio->char_dev); -+err_cdev_add: -+ __disable_gpio(pio, gpio->pin_mask); -+ pio_dealloc_mask(pio, gpio->pin_mask); -+err_alloc_pins: -+ spin_lock(&gpio->lock); -+ gpio->enabled = 0; -+ spin_unlock(&gpio->lock); -+ gpio->pio = NULL; -+ -+ return ret; -+} -+ -+static struct gpio_attribute gpio_item_attr_gpio_id = { -+ .attr = { -+ .ca_owner = THIS_MODULE, -+ .ca_name = "gpio_id", -+ .ca_mode = S_IRUGO | S_IWUSR, -+ }, -+ .show = gpio_show_gpio_id, -+ .store = gpio_store_gpio_id, -+}; -+static struct gpio_attribute gpio_item_attr_pin_mask = { -+ .attr = { -+ .ca_owner = THIS_MODULE, -+ .ca_name = "pin_mask", -+ .ca_mode = S_IRUGO | S_IWUSR, -+ }, -+ .show = gpio_show_pin_mask, -+ .store = gpio_store_pin_mask, -+}; -+static struct gpio_attribute gpio_item_attr_oe_mask = { -+ .attr = { -+ .ca_owner = THIS_MODULE, -+ .ca_name = "oe_mask", -+ .ca_mode = S_IRUGO | S_IWUSR, -+ }, -+ .show = gpio_show_oe_mask, -+ .store = gpio_store_oe_mask, -+}; -+static struct gpio_attribute gpio_item_attr_enabled = { -+ .attr = { -+ .ca_owner = THIS_MODULE, -+ .ca_name = "enabled", -+ .ca_mode = S_IRUGO | S_IWUSR, -+ }, -+ .show = gpio_show_enabled, -+ .store = gpio_store_enabled, -+}; -+ -+static struct configfs_attribute *gpio_item_attrs[] = { -+ &gpio_item_attr_gpio_id.attr, -+ &gpio_item_attr_pin_mask.attr, -+ &gpio_item_attr_oe_mask.attr, -+ &gpio_item_attr_enabled.attr, -+ NULL, -+}; -+ -+static ssize_t gpio_show_attr(struct config_item *item, -+ struct configfs_attribute *attr, -+ char *page) -+{ -+ struct gpio_item *gpio_item = to_gpio_item(item); -+ struct gpio_attribute *gpio_attr -+ = container_of(attr, struct gpio_attribute, attr); -+ ssize_t ret = 0; -+ -+ if (gpio_attr->show) -+ ret = gpio_attr->show(gpio_item, page); -+ return ret; -+} -+ -+static ssize_t gpio_store_attr(struct config_item *item, -+ struct configfs_attribute *attr, -+ const char *page, size_t count) -+{ -+ struct gpio_item *gpio_item = to_gpio_item(item); -+ struct gpio_attribute *gpio_attr -+ = container_of(attr, struct gpio_attribute, attr); -+ ssize_t ret = -EINVAL; -+ -+ if (gpio_attr->store) -+ ret = gpio_attr->store(gpio_item, page, count); -+ return ret; -+} -+ -+static void gpio_release(struct config_item *item) -+{ -+ kfree(to_gpio_item(item)); -+} -+ -+static struct configfs_item_operations gpio_item_ops = { -+ .release = gpio_release, -+ .show_attribute = gpio_show_attr, -+ .store_attribute = gpio_store_attr, -+}; -+ -+static struct config_item_type gpio_item_type = { -+ .ct_item_ops = &gpio_item_ops, -+ .ct_attrs = gpio_item_attrs, -+ .ct_owner = THIS_MODULE, -+}; -+ -+static struct config_item *gpio_make_item(struct config_group *group, -+ const char *name) -+{ -+ static int next_id; -+ struct gpio_item *gpio; -+ -+ if (next_id >= GPIO_DEV_MAX) -+ return NULL; -+ -+ gpio = kzalloc(sizeof(struct gpio_item), GFP_KERNEL); -+ if (!gpio) -+ return NULL; -+ -+ gpio->id = next_id++; -+ config_item_init_type_name(&gpio->item, name, &gpio_item_type); -+ spin_lock_init(&gpio->lock); -+ init_waitqueue_head(&gpio->change_wq); -+ -+ return &gpio->item; -+} -+ -+static void gpio_drop_item(struct config_group *group, -+ struct config_item *item) -+{ -+ struct gpio_item *gpio = to_gpio_item(item); -+ struct pio_device *pio; -+ -+ spin_lock(&gpio->lock); -+ if (gpio->enabled) { -+ class_device_unregister(gpio->gpio_dev); -+ cdev_del(&gpio->char_dev); -+ } -+ -+ pio = gpio->pio; -+ if (pio) { -+ __disable_gpio(pio, gpio->pin_mask); -+ pio_dealloc_mask(pio, gpio->pin_mask); -+ gpio->pio = NULL; -+ } -+ spin_unlock(&gpio->lock); -+} -+ -+static struct configfs_group_operations gpio_group_ops = { -+ .make_item = gpio_make_item, -+ .drop_item = gpio_drop_item, -+}; -+ -+static struct config_item_type gpio_group_type = { -+ .ct_group_ops = &gpio_group_ops, -+ .ct_owner = THIS_MODULE, -+}; -+ -+static struct configfs_subsystem gpio_subsys = { -+ .su_group = { -+ .cg_item = { -+ .ci_namebuf = "gpio", -+ .ci_type = &gpio_group_type, -+ }, -+ }, -+}; -+ -+static int __init pio_init_dev(void) -+{ -+ int err; -+ -+ gpio_dev_class = class_create(THIS_MODULE, "gpio-dev"); -+ if (IS_ERR(gpio_dev_class)) { -+ err = PTR_ERR(gpio_dev_class); -+ goto err_class_create; -+ } -+ -+ err = alloc_chrdev_region(&gpio_devt, 0, GPIO_DEV_MAX, "gpio"); -+ if (err < 0) -+ goto err_alloc_chrdev; -+ -+ /* Configfs initialization */ -+ config_group_init(&gpio_subsys.su_group); -+ init_MUTEX(&gpio_subsys.su_sem); -+ err = configfs_register_subsystem(&gpio_subsys); -+ if (err) -+ goto err_register_subsys; -+ -+ return 0; -+ -+err_register_subsys: -+ unregister_chrdev_region(gpio_devt, GPIO_DEV_MAX); -+err_alloc_chrdev: -+ class_destroy(gpio_dev_class); -+err_class_create: -+ printk(KERN_WARNING "Failed to initialize gpio /dev interface\n"); -+ return err; -+} -+late_initcall(pio_init_dev); -+#endif /* CONFIG_PIO_DEV */ -+ - static int __init pio_probe(struct platform_device *pdev) - { - struct pio_device *pio = NULL; -+ int irq = platform_get_irq(pdev, 0); -+ int gpio_irq_base = GPIO_IRQ_BASE + pdev->id * 32; - - BUG_ON(pdev->id >= MAX_NR_PIO_DEVICES); - pio = &pio_dev[pdev->id]; - BUG_ON(!pio->regs); - -- /* TODO: Interrupts */ -+ gpio_irq_setup(pio, irq, gpio_irq_base); - - platform_set_drvdata(pdev, pio); - -- printk(KERN_INFO "%s: Atmel Port Multiplexer at 0x%p (irq %d)\n", -- pio->name, pio->regs, platform_get_irq(pdev, 0)); -+ printk(KERN_DEBUG "%s: base 0x%p, irq %d chains %d..%d\n", -+ pio->name, pio->regs, irq, gpio_irq_base, gpio_irq_base + 31); - - return 0; - } -@@ -148,7 +960,7 @@ - { - return platform_driver_register(&pio_driver); - } --subsys_initcall(pio_init); -+postcore_initcall(pio_init); - - void __init at32_init_pio(struct platform_device *pdev) - { -@@ -184,6 +996,13 @@ - pio->pdev = pdev; - pio->regs = ioremap(regs->start, regs->end - regs->start + 1); - -- pio_writel(pio, ODR, ~0UL); -- pio_writel(pio, PER, ~0UL); -+ /* -+ * request_gpio() is only valid for pins that have been -+ * explicitly configured as GPIO and not previously requested -+ */ -+ pio->gpio_mask = ~0UL; -+ -+ /* start with irqs disabled and acked */ -+ pio_writel(pio, IDR, ~0UL); -+ (void) pio_readl(pio, ISR); - } -diff -urN linux-2.6.20.4-0rig/arch/avr32/Makefile linux-2.6.20.4-atmel/arch/avr32/Makefile ---- linux-2.6.20.4-0rig/arch/avr32/Makefile 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/avr32/Makefile 2007-03-24 16:42:29.000000000 +0100 -@@ -30,6 +30,8 @@ - core-$(CONFIG_LOADER_U_BOOT) += arch/avr32/boot/u-boot/ - core-y += arch/avr32/kernel/ - core-y += arch/avr32/mm/ -+drivers-$(CONFIG_OPROFILE) += arch/avr32/oprofile/ -+drivers-y += arch/avr32/drivers/ - libs-y += arch/avr32/lib/ - - archincdir-$(CONFIG_PLATFORM_AT32AP) := arch-at32ap -diff -urN linux-2.6.20.4-0rig/arch/avr32/mm/cache.c linux-2.6.20.4-atmel/arch/avr32/mm/cache.c ---- linux-2.6.20.4-0rig/arch/avr32/mm/cache.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/avr32/mm/cache.c 2007-03-24 16:42:28.000000000 +0100 -@@ -22,18 +22,34 @@ - - void invalidate_dcache_region(void *start, size_t size) - { -- unsigned long v, begin, end, linesz; -+ unsigned long v, begin, end, linesz, mask; -+ int flush = 0; - - linesz = boot_cpu_data.dcache.linesz; -+ mask = linesz - 1; - -- //printk("invalidate dcache: %p + %u\n", start, size); -- -- /* You asked for it, you got it */ -- begin = (unsigned long)start & ~(linesz - 1); -- end = ((unsigned long)start + size + linesz - 1) & ~(linesz - 1); -+ /* when first and/or last cachelines are shared, flush them -+ * instead of invalidating ... never discard valid data! -+ */ -+ begin = (unsigned long)start; -+ end = begin + size - 1; -+ -+ if (begin & mask) { -+ flush_dcache_line(start); -+ begin += linesz; -+ flush = 1; -+ } -+ if ((end & mask) != mask) { -+ flush_dcache_line((void *)end); -+ end -= linesz; -+ flush = 1; -+ } - -- for (v = begin; v < end; v += linesz) -+ /* remaining cachelines only need invalidation */ -+ for (v = begin; v <= end; v += linesz) - invalidate_dcache_line((void *)v); -+ if (flush) -+ flush_write_buffer(); - } - - void clean_dcache_region(void *start, size_t size) -diff -urN linux-2.6.20.4-0rig/arch/avr32/mm/dma-coherent.c linux-2.6.20.4-atmel/arch/avr32/mm/dma-coherent.c ---- linux-2.6.20.4-0rig/arch/avr32/mm/dma-coherent.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/avr32/mm/dma-coherent.c 2007-03-24 16:42:29.000000000 +0100 -@@ -41,6 +41,13 @@ - struct page *page, *free, *end; - int order; - -+ /* Following is a work-around (a.k.a. hack) to prevent pages -+ * with __GFP_COMP being passed to split_page() which cannot -+ * handle them. The real problem is that this flag probably -+ * should be 0 on AVR32 as it is not supported on this -+ * platform--see CONFIG_HUGETLB_PAGE. */ -+ gfp &= ~(__GFP_COMP); -+ - size = PAGE_ALIGN(size); - order = get_order(size); - -diff -urN linux-2.6.20.4-0rig/arch/avr32/oprofile/common.c linux-2.6.20.4-atmel/arch/avr32/oprofile/common.c ---- linux-2.6.20.4-0rig/arch/avr32/oprofile/common.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/avr32/oprofile/common.c 2007-03-24 16:42:29.000000000 +0100 -@@ -0,0 +1,169 @@ -+/* -+ * 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. -+ * -+ * Author: Ronny Pedersen -+ */ -+ -+#define DEBUG -+#include <linux/init.h> -+#include <linux/oprofile.h> -+#include <linux/errno.h> -+#include <asm/semaphore.h> -+#include <linux/sysdev.h> -+ -+#include "op_avr32_model.h" -+#include "op_counter.h" -+ -+static struct op_avr32_model_spec *pc_model; -+static int pc_enabled = 0; -+static struct semaphore pc_sem; -+ -+ -+static int pc_start(void); -+static int pc_setup(void); -+static void pc_stop(void); -+static int pc_create_files(struct super_block *, struct dentry *); -+ -+ -+struct op_counter_config counter_config[OP_MAX_COUNTER]; -+ -+static int pc_suspend(struct sys_device *dev, u32 state) -+{ -+ if (pc_enabled) -+ pc_stop(); -+ return 0; -+} -+ -+static int pc_resume(struct sys_device *dev) -+{ -+ if (pc_enabled) -+ pc_start(); -+ return 0; -+} -+ -+static struct sysdev_class oprofile_sysclass = { -+ set_kset_name("oprofile"), -+ .resume = pc_resume, -+ .suspend = pc_suspend, -+}; -+ -+static struct sys_device device_oprofile = { -+ .id = 0, -+ .cls = &oprofile_sysclass, -+}; -+ -+static int __init init_driverfs(void) -+{ -+ int ret; -+ -+ if (!(ret = sysdev_class_register(&oprofile_sysclass))) -+ ret = sysdev_register(&device_oprofile); -+ -+ return ret; -+} -+ -+static void exit_driverfs(void) -+{ -+ sysdev_unregister(&device_oprofile); -+ sysdev_class_unregister(&oprofile_sysclass); -+} -+ -+static int pc_create_files(struct super_block *sb, struct dentry *root) -+{ -+ unsigned int i; -+ -+ pr_debug("AVR32 Peformance Counters: create files\n"); -+ for (i = 0; i < pc_model->num_counters; i++) { -+ struct dentry *dir; -+ char buf[2]; -+ -+ snprintf(buf, sizeof buf, "%d", i); -+ dir = oprofilefs_mkdir(sb, root, buf); -+ oprofilefs_create_ulong(sb, dir, "enabled", -+ &counter_config[i].enabled); -+ oprofilefs_create_ulong(sb, dir, "event", -+ &counter_config[i].event); -+ oprofilefs_create_ulong(sb, dir, "count", -+ &counter_config[i].count); -+ oprofilefs_create_ulong(sb, dir, "unit_mask", -+ &counter_config[i].unit_mask); -+ oprofilefs_create_ulong(sb, dir, "kernel", -+ &counter_config[i].kernel); -+ oprofilefs_create_ulong(sb, dir, "user", -+ &counter_config[i].user); -+ } -+ -+ return 0; -+} -+ -+static int pc_setup(void) -+{ -+ int ret; -+ -+ spin_lock(&oprofilefs_lock); -+ pr_debug("AVR32 Peformance Counters: setup\n"); -+ ret = pc_model->setup_ctrs(); -+ spin_unlock(&oprofilefs_lock); -+ return ret; -+} -+ -+static int pc_start(void) -+{ -+ int ret = -EBUSY; -+ -+ down(&pc_sem); -+ if (!pc_enabled) { -+ pr_debug("AVR32 Peformance Counters: start\n"); -+ ret = pc_model->start(); -+ pc_enabled = !ret; -+ } -+ up(&pc_sem); -+ return ret; -+} -+ -+static void pc_stop(void) -+{ -+ down(&pc_sem); -+ pr_debug("AVR32 Peformance Counters: stop\n"); -+ if (pc_enabled) -+ pc_model->stop(); -+ pc_enabled = 0; -+ up(&pc_sem); -+} -+ -+int __init pc_init(struct oprofile_operations *ops, -+ struct op_avr32_model_spec *spec) -+{ -+ init_MUTEX(&pc_sem); -+ -+ if ( spec->init ) -+ if (spec->init() < 0) -+ return -ENODEV; -+ -+ pc_model = spec; -+ init_driverfs(); -+ ops->create_files = pc_create_files; -+ ops->setup = pc_setup; -+ ops->shutdown = pc_stop; -+ ops->start = pc_start; -+ ops->stop = pc_stop; -+ ops->cpu_type = pc_model->name; -+ printk(KERN_INFO "oprofile: using %s Performance Counters\n", -+ spec->name); -+ pr_debug("AVR32 Peformance Counters: pc_init\n"); -+ -+ return 0; -+} -+ -+void pc_exit(void) -+{ -+ if (pc_model) { -+ pr_debug("AVR32 Peformance Counters: exit\n"); -+ exit_driverfs(); -+ pc_model = NULL; -+ } -+} -diff -urN linux-2.6.20.4-0rig/arch/avr32/oprofile/init.c linux-2.6.20.4-atmel/arch/avr32/oprofile/init.c ---- linux-2.6.20.4-0rig/arch/avr32/oprofile/init.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/avr32/oprofile/init.c 2007-03-24 16:42:29.000000000 +0100 -@@ -0,0 +1,29 @@ -+/* -+ * 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. -+ * -+ * Author: Ronny Pedersen -+ */ -+ -+#include <linux/oprofile.h> -+#include <linux/init.h> -+#include <linux/errno.h> -+#include "op_avr32_model.h" -+#include "op_model_avr32.h" -+ -+int __init oprofile_arch_init(struct oprofile_operations *ops) -+{ -+ int ret = -ENODEV; -+ -+ ret = pc_init(ops, &op_avr32_spec); -+ -+ return ret; -+} -+ -+void oprofile_arch_exit(void) -+{ -+ pc_exit(); -+} -diff -urN linux-2.6.20.4-0rig/arch/avr32/oprofile/Kconfig linux-2.6.20.4-atmel/arch/avr32/oprofile/Kconfig ---- linux-2.6.20.4-0rig/arch/avr32/oprofile/Kconfig 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/avr32/oprofile/Kconfig 2007-03-24 16:42:29.000000000 +0100 -@@ -0,0 +1,23 @@ -+ -+menu "Profiling support" -+ depends on EXPERIMENTAL -+ -+config PROFILING -+ bool "Profiling support (EXPERIMENTAL)" -+ help -+ Say Y here to enable the extended profiling support mechanisms used -+ by profilers such as OProfile. -+ -+ -+config OPROFILE -+ tristate "OProfile system profiling (EXPERIMENTAL)" -+ depends on PROFILING -+ help -+ OProfile is a profiling system capable of profiling the -+ whole system, including the kernel, kernel modules, libraries, -+ and applications. -+ -+ If unsure, say N. -+ -+endmenu -+ -diff -urN linux-2.6.20.4-0rig/arch/avr32/oprofile/Makefile linux-2.6.20.4-atmel/arch/avr32/oprofile/Makefile ---- linux-2.6.20.4-0rig/arch/avr32/oprofile/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/avr32/oprofile/Makefile 2007-03-24 16:42:29.000000000 +0100 -@@ -0,0 +1,10 @@ -+obj-$(CONFIG_OPROFILE) += oprofile.o -+ -+DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \ -+ oprof.o cpu_buffer.o buffer_sync.o \ -+ event_buffer.o oprofile_files.o \ -+ oprofilefs.o oprofile_stats.o \ -+ timer_int.o ) -+ -+oprofile-y := $(DRIVER_OBJS) init.o common.o -+oprofile-y += op_model_avr32.o -diff -urN linux-2.6.20.4-0rig/arch/avr32/oprofile/op_avr32_model.h linux-2.6.20.4-atmel/arch/avr32/oprofile/op_avr32_model.h ---- linux-2.6.20.4-0rig/arch/avr32/oprofile/op_avr32_model.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/avr32/oprofile/op_avr32_model.h 2007-03-24 16:42:29.000000000 +0100 -@@ -0,0 +1,25 @@ -+/* -+ * interface to AVR32 machine specific operations -+ * -+ * 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. -+ * -+ * Author: Ronny Pedersen -+ */ -+ -+#ifndef OP_AVR32_MODEL_H -+#define OP_AVR32_MODEL_H -+ -+struct op_avr32_model_spec { -+ int (*init)(void); -+ unsigned int num_counters; -+ int (*setup_ctrs)(void); -+ int (*start)(void); -+ void (*stop)(void); -+ char *name; -+}; -+ -+#endif /* OP_AVR32_MODEL_H */ -diff -urN linux-2.6.20.4-0rig/arch/avr32/oprofile/op_counter.h linux-2.6.20.4-atmel/arch/avr32/oprofile/op_counter.h ---- linux-2.6.20.4-0rig/arch/avr32/oprofile/op_counter.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/avr32/oprofile/op_counter.h 2007-03-24 16:42:29.000000000 +0100 -@@ -0,0 +1,29 @@ -+/* -+ * 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. -+ * -+ * Author: Ronny Pedersen -+ */ -+#ifndef OP_COUNTER_H -+#define OP_COUNTER_H -+ -+#define OP_MAX_COUNTER 3 -+ -+/* Per performance monitor configuration as set via -+ * oprofilefs. -+ */ -+struct op_counter_config { -+ unsigned long count; -+ unsigned long enabled; -+ unsigned long event; -+ unsigned long unit_mask; -+ unsigned long kernel; -+ unsigned long user; -+}; -+ -+extern struct op_counter_config counter_config[]; -+ -+#endif /* OP_COUNTER_H */ -diff -urN linux-2.6.20.4-0rig/arch/avr32/oprofile/op_model_avr32.c linux-2.6.20.4-atmel/arch/avr32/oprofile/op_model_avr32.c ---- linux-2.6.20.4-0rig/arch/avr32/oprofile/op_model_avr32.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/avr32/oprofile/op_model_avr32.c 2007-03-24 16:42:29.000000000 +0100 -@@ -0,0 +1,222 @@ -+/* -+ * AVR32 Performance Counter Driver -+ * -+ * 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. -+ * -+ * Authors: Sondre Garsjoe, Ronny Pedersen -+ */ -+ -+#define DEBUG -+ -+#include <linux/types.h> -+#include <linux/errno.h> -+#include <linux/sched.h> -+#include <linux/oprofile.h> -+#include <linux/interrupt.h> -+#include <asm/intc.h> -+#include <asm/irq.h> -+#include <asm/system.h> -+#include <asm/sysreg.h> -+ -+#include "op_counter.h" -+#include "op_avr32_model.h" -+ -+ -+#define PC_ENABLE 0x001 /* Enable counters */ -+#define PCNT_RESET 0x002 /* Reset event counters */ -+#define CCNT_RESET 0x004 /* Reset clock counter */ -+#define PC_RESET (CCNT_RESET | PCNT_RESET) -+#define PC_CNT64 0x008 /* Make CCNT count every 64th cycle */ -+ -+ -+#define EVT_UNUSED 0xFF -+ -+struct pc_counter { -+ volatile unsigned long ovf; -+ unsigned long reset_counter; -+}; -+ -+enum { PCCNT, PCNT0, PCNT1, MAX_COUNTERS }; -+ -+#define PCCNT_IE (1 << 4) -+#define PCNT0_IE (1 << 5) -+#define PCNT1_IE (1 << 6) -+ -+#define PCCNT_F (1 << 8) -+#define PCNT0_F (1 << 9) -+#define PCNT1_F (1 << 10) -+ -+#define AVR32_PC_IRQ 0 -+ -+static const u32 int_mask[MAX_COUNTERS] = { PCCNT_IE, PCNT0_IE, PCNT1_IE }; -+static const u32 ovf_mask[MAX_COUNTERS] = { PCCNT_F, PCNT0_F, PCNT1_F }; -+ -+static struct pc_counter results[MAX_COUNTERS]; -+ -+static void write_pccr(u32 val) -+{ -+ sysreg_write(PCCR, val); -+} -+ -+static u32 read_pccr(void) -+{ -+ return sysreg_read(PCCR); -+} -+ -+static u32 read_counter(int counter) -+{ -+ switch (counter) { -+ case PCCNT: -+ return sysreg_read(PCCNT); -+ case PCNT0: -+ return sysreg_read(PCNT0); -+ case PCNT1: -+ return sysreg_read(PCNT1); -+ default: -+ return 0; -+ } -+} -+ -+static void write_counter(int counter, u32 val) -+{ -+ switch (counter) { -+ case PCCNT: -+ sysreg_write(PCCNT, val); -+ case PCNT0: -+ sysreg_write(PCNT0, val); -+ case PCNT1: -+ sysreg_write(PCNT1, val); -+ default: -+ break; -+ } -+} -+ -+static int avr32_setup_ctrs(void) -+{ -+ u32 pccr; -+ int i; -+ -+ for (i = PCCNT; i < MAX_COUNTERS; i++) { -+ if (counter_config[i].enabled) -+ continue; -+ -+ counter_config[i].event = EVT_UNUSED; -+ } -+ -+ pccr = ((counter_config[PCNT1].event << 18) -+ | (counter_config[PCNT0].event << 12)); -+ pr_debug("avr32_setup_ctrs: pccr: %#08x\n", pccr); -+ write_pccr(pccr); -+ -+ for (i = PCCNT; i < MAX_COUNTERS; i++) { -+ if (counter_config[i].event == EVT_UNUSED) { -+ counter_config[i].event = 0; -+ continue; -+ } -+ -+ results[i].reset_counter = counter_config[i].count; -+ write_counter(i, -(u32)counter_config[i].count); -+ pr_debug("avr32_setup_ctrs: counter%d %#08x from %#08lx\n", -+ i, read_counter(i), counter_config[i].count); -+ } -+ -+ return 0; -+} -+ -+static void inline check_ctrs(void) -+{ -+ int i; -+ u32 pccr = read_pccr(); -+ -+ /* Writeback clears overflow flag */ -+ write_pccr(pccr & ~PC_ENABLE); -+ -+ for (i = PCCNT; i < MAX_COUNTERS; i++) { -+ if (!(int_mask[i] & pccr)) -+ continue; -+ -+ if (pccr & ovf_mask[i]) -+ results[i].ovf++; -+ } -+} -+ -+static irqreturn_t avr32_pc_interrupt(int irq, void *arg, -+ struct pt_regs *regs) -+{ -+ int i; -+ -+ /* Check if this is a performance counter interrupt */ -+ if (!(intc_get_pending(irq) & 2)) -+ return IRQ_NONE; -+ -+ check_ctrs(); -+ -+ for (i = PCCNT; i < MAX_COUNTERS; i++) { -+ if (!results[i].ovf) -+ continue; -+ -+ write_counter(i, -(u32)results[i].reset_counter); -+ oprofile_add_sample(regs, i); -+ results[i].ovf--; -+ } -+ -+ /* Enable Performance Counter */ -+ write_pccr(read_pccr() | PC_ENABLE); -+ -+ return IRQ_HANDLED; -+} -+ -+static void avr32_pc_stop(void) -+{ -+ write_pccr(read_pccr() & ~PC_ENABLE); -+ -+ free_irq(AVR32_PC_IRQ, results); -+} -+ -+static int avr32_pc_start(void) -+{ -+ int i, ret; -+ u32 pccr = read_pccr(); -+ -+ ret = request_irq(AVR32_PC_IRQ, avr32_pc_interrupt, IRQF_SHARED | IRQF_DISABLED, -+ "AVR32 Performance Counter", (void *)results); -+ -+ if (ret < 0) { -+ printk(KERN_ERR -+ "oprofile: unable to request IRQ%d for AVR32" -+ " Performance Counter\n", -+ AVR32_PC_IRQ); -+ return ret; -+ } -+ -+ /* Enable interrupts */ -+ for (i = PCCNT; i < MAX_COUNTERS; i++) { -+ if (counter_config[i].enabled) -+ pccr |= int_mask[i]; -+ } -+ -+ /* Disable scaler */ -+ pccr &= ~PC_CNT64; -+ -+ /* Enable Performance Counter */ -+ pccr |= PC_ENABLE; -+ -+ write_pccr(pccr); -+ pr_debug("avr32_pc_start: pc: %#08x\n", pccr); -+ return 0; -+} -+ -+ -+struct op_avr32_model_spec op_avr32_spec = { -+ .init = 0, -+ .setup_ctrs = avr32_setup_ctrs, -+ .start = avr32_pc_start, -+ .stop = avr32_pc_stop, -+ .num_counters = MAX_COUNTERS, -+ .name = "avr32/at32ap7000", -+}; -+ -diff -urN linux-2.6.20.4-0rig/arch/avr32/oprofile/op_model_avr32.h linux-2.6.20.4-atmel/arch/avr32/oprofile/op_model_avr32.h ---- linux-2.6.20.4-0rig/arch/avr32/oprofile/op_model_avr32.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/arch/avr32/oprofile/op_model_avr32.h 2007-03-24 16:42:29.000000000 +0100 -@@ -0,0 +1,21 @@ -+/** -+ * AVR32 Machine Specific Operations -+ * -+ * 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. -+ * -+ * Author: Ronny Pedersen -+ */ -+#ifndef OP_MODEL_AVR32_H -+#define OP_MODEL_AVR32_H -+ -+extern struct op_avr32_model_spec op_avr32_spec; -+extern int pc_init(struct oprofile_operations *ops, -+ struct op_avr32_model_spec *spec); -+extern void pc_exit(void); -+ -+ -+#endif -diff -urN linux-2.6.20.4-0rig/drivers/char/at91_spi.c linux-2.6.20.4-atmel/drivers/char/at91_spi.c ---- linux-2.6.20.4-0rig/drivers/char/at91_spi.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/char/at91_spi.c 2007-03-24 16:39:15.000000000 +0100 -@@ -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") -diff -urN linux-2.6.20.4-0rig/drivers/char/at91_spidev.c linux-2.6.20.4-atmel/drivers/char/at91_spidev.c ---- linux-2.6.20.4-0rig/drivers/char/at91_spidev.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/char/at91_spidev.c 2007-03-24 16:39:15.000000000 +0100 -@@ -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") -diff -urN linux-2.6.20.4-0rig/drivers/char/Kconfig linux-2.6.20.4-atmel/drivers/char/Kconfig ---- linux-2.6.20.4-0rig/drivers/char/Kconfig 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/char/Kconfig 2007-03-24 16:39:15.000000000 +0100 -@@ -1030,5 +1030,21 @@ - sysfs directory, /sys/devices/platform/telco_clock, with a number of - files for controlling the behavior of this hardware. - -+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 - -diff -urN linux-2.6.20.4-0rig/drivers/char/Makefile linux-2.6.20.4-atmel/drivers/char/Makefile ---- linux-2.6.20.4-0rig/drivers/char/Makefile 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/char/Makefile 2007-03-24 16:39:15.000000000 +0100 -@@ -90,6 +90,8 @@ - obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o - obj-$(CONFIG_TANBAC_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/ -diff -urN linux-2.6.20.4-0rig/drivers/i2c/busses/atmeltwi.h linux-2.6.20.4-atmel/drivers/i2c/busses/atmeltwi.h ---- linux-2.6.20.4-0rig/drivers/i2c/busses/atmeltwi.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/i2c/busses/atmeltwi.h 2007-03-24 16:42:29.000000000 +0100 -@@ -0,0 +1,117 @@ -+/* -+ * Register definitions for the Atmel Two-Wire Interface -+ */ -+ -+#ifndef __ASM_AVR32_TWI_H__ -+#define __ASM_AVR32_TWI_H__ -+ -+/* TWI register offsets */ -+#define TWI_CR 0x0000 -+#define TWI_MMR 0x0004 -+#define TWI_SMR 0x0008 -+#define TWI_IADR 0x000c -+#define TWI_CWGR 0x0010 -+#define TWI_SR 0x0020 -+#define TWI_IER 0x0024 -+#define TWI_IDR 0x0028 -+#define TWI_IMR 0x002c -+#define TWI_RHR 0x0030 -+#define TWI_THR 0x0034 -+ -+/* Bitfields in CR */ -+#define TWI_START_OFFSET 0 -+#define TWI_START_SIZE 1 -+#define TWI_STOP_OFFSET 1 -+#define TWI_STOP_SIZE 1 -+#define TWI_MSEN_OFFSET 2 -+#define TWI_MSEN_SIZE 1 -+#define TWI_MSDIS_OFFSET 3 -+#define TWI_MSDIS_SIZE 1 -+#define TWI_SVEN_OFFSET 4 -+#define TWI_SVEN_SIZE 1 -+#define TWI_SVDIS_OFFSET 5 -+#define TWI_SVDIS_SIZE 1 -+#define TWI_SWRST_OFFSET 7 -+#define TWI_SWRST_SIZE 1 -+ -+/* Bitfields in MMR */ -+#define TWI_IADRSZ_OFFSET 8 -+#define TWI_IADRSZ_SIZE 2 -+#define TWI_MREAD_OFFSET 12 -+#define TWI_MREAD_SIZE 1 -+#define TWI_DADR_OFFSET 16 -+#define TWI_DADR_SIZE 7 -+ -+/* Bitfields in SMR */ -+#define TWI_SADR_OFFSET 16 -+#define TWI_SADR_SIZE 7 -+ -+/* Bitfields in IADR */ -+#define TWI_IADR_OFFSET 0 -+#define TWI_IADR_SIZE 24 -+ -+/* Bitfields in CWGR */ -+#define TWI_CLDIV_OFFSET 0 -+#define TWI_CLDIV_SIZE 8 -+#define TWI_CHDIV_OFFSET 8 -+#define TWI_CHDIV_SIZE 8 -+#define TWI_CKDIV_OFFSET 16 -+#define TWI_CKDIV_SIZE 3 -+ -+/* Bitfields in SR */ -+#define TWI_TXCOMP_OFFSET 0 -+#define TWI_TXCOMP_SIZE 1 -+#define TWI_RXRDY_OFFSET 1 -+#define TWI_RXRDY_SIZE 1 -+#define TWI_TXRDY_OFFSET 2 -+#define TWI_TXRDY_SIZE 1 -+#define TWI_SVDIR_OFFSET 3 -+#define TWI_SVDIR_SIZE 1 -+#define TWI_SVACC_OFFSET 4 -+#define TWI_SVACC_SIZE 1 -+#define TWI_GCACC_OFFSET 5 -+#define TWI_GCACC_SIZE 1 -+#define TWI_OVRE_OFFSET 6 -+#define TWI_OVRE_SIZE 1 -+#define TWI_UNRE_OFFSET 7 -+#define TWI_UNRE_SIZE 1 -+#define TWI_NACK_OFFSET 8 -+#define TWI_NACK_SIZE 1 -+#define TWI_ARBLST_OFFSET 9 -+#define TWI_ARBLST_SIZE 1 -+ -+/* Bitfields in RHR */ -+#define TWI_RXDATA_OFFSET 0 -+#define TWI_RXDATA_SIZE 8 -+ -+/* Bitfields in THR */ -+#define TWI_TXDATA_OFFSET 0 -+#define TWI_TXDATA_SIZE 8 -+ -+/* Constants for IADRSZ */ -+#define TWI_IADRSZ_NO_ADDR 0 -+#define TWI_IADRSZ_ONE_BYTE 1 -+#define TWI_IADRSZ_TWO_BYTES 2 -+#define TWI_IADRSZ_THREE_BYTES 3 -+ -+/* Bit manipulation macros */ -+#define TWI_BIT(name) \ -+ (1 << TWI_##name##_OFFSET) -+#define TWI_BF(name,value) \ -+ (((value) & ((1 << TWI_##name##_SIZE) - 1)) \ -+ << TWI_##name##_OFFSET) -+#define TWI_BFEXT(name,value) \ -+ (((value) >> TWI_##name##_OFFSET) \ -+ & ((1 << TWI_##name##_SIZE) - 1)) -+#define TWI_BFINS(name,value,old) \ -+ (((old) & ~(((1 << TWI_##name##_SIZE) - 1) \ -+ << TWI_##name##_OFFSET)) \ -+ | TWI_BF(name,value)) -+ -+/* Register access macros */ -+#define twi_readl(port,reg) \ -+ __raw_readl((port)->regs + TWI_##reg) -+#define twi_writel(port,reg,value) \ -+ __raw_writel((value), (port)->regs + TWI_##reg) -+ -+#endif /* __ASM_AVR32_TWI_H__ */ -diff -urN linux-2.6.20.4-0rig/drivers/i2c/busses/i2c-at91.c linux-2.6.20.4-atmel/drivers/i2c/busses/i2c-at91.c ---- linux-2.6.20.4-0rig/drivers/i2c/busses/i2c-at91.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/i2c/busses/i2c-at91.c 2007-03-24 16:39:15.000000000 +0100 -@@ -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) { -@@ -63,9 +66,14 @@ - - if (cpu_is_at91rm9200()) { /* AT91RM9200 Errata #22 */ - if (ckdiv > 5) { -- printk(KERN_ERR "AT91 I2C: Invalid TWI_CLOCK value!\n"); -+ 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 -urN linux-2.6.20.4-0rig/drivers/i2c/busses/i2c-atmeltwi.c linux-2.6.20.4-atmel/drivers/i2c/busses/i2c-atmeltwi.c ---- linux-2.6.20.4-0rig/drivers/i2c/busses/i2c-atmeltwi.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/i2c/busses/i2c-atmeltwi.c 2007-03-24 16:42:29.000000000 +0100 -@@ -0,0 +1,348 @@ -+/* -+ * i2c Support for Atmel's Two-Wire Interface (TWI) -+ * -+ * Based on the work of Copyright (C) 2004 Rick Bronson -+ * Converted to 2.6 by Andrew Victor <andrew at sanpeople.com> -+ * Ported to AVR32 and heavily modified by Espen Krangnes <ekrangnes at atmel.com> -+ * -+ * Copyright (C) 2006 Atmel Corporation -+ * -+ * Borrowed heavily from the original work by: -+ * Copyright (C) 2000 Philip Edelbrock <phil at stimpy.netroedge.com> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ */ -+ -+ -+#include <linux/err.h> -+#include <linux/module.h> -+#include <linux/kernel.h> -+#include <linux/slab.h> -+#include <linux/types.h> -+#include <linux/delay.h> -+#include <linux/i2c.h> -+#include <linux/init.h> -+#include <linux/clk.h> -+#include <linux/interrupt.h> -+#include <linux/irq.h> -+#include <linux/platform_device.h> -+#include <linux/completion.h> -+#include <asm/io.h> -+#include <linux/time.h> -+#include "atmeltwi.h" -+ -+static unsigned int baudrate = CONFIG_I2C_ATMELTWI_BAUDRATE; -+module_param(baudrate, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); -+MODULE_PARM_DESC(baudrate, "The TWI baudrate"); -+ -+ -+struct atmel_twi { -+ void __iomem *regs; -+ struct i2c_adapter adapter; -+ struct clk *pclk; -+ spinlock_t lock; -+ struct completion comp; -+ u32 intmask; -+ u8 *buf; -+ u8 len; -+ u8 acks_left; -+ unsigned int irq; -+ -+}; -+#define to_atmel_twi(adap) container_of(adap, struct atmel_twi, adapter) -+ -+/* -+ * Initialize the TWI hardware registers. -+ */ -+static int __devinit twi_hwinit(struct atmel_twi *twi) -+{ -+ unsigned long cdiv, ckdiv=0; -+ -+ twi_writel(twi, IDR, ~0UL); -+ twi_writel(twi, CR, TWI_BIT(SWRST)); /*Reset peripheral*/ -+ twi_readl(twi, SR); -+ -+ cdiv = (clk_get_rate(twi->pclk) / (2 * baudrate)) - 4; -+ -+ while (cdiv > 255) { -+ ckdiv++; -+ cdiv = cdiv >> 1; -+ } -+ -+ if (ckdiv > 7) -+ return -EINVAL; -+ else -+ twi_writel(twi, CWGR, (TWI_BF(CKDIV, ckdiv) -+ | TWI_BF(CHDIV, cdiv) -+ | TWI_BF(CLDIV, cdiv))); -+ return 0; -+} -+ -+/* -+ * Waits for the i2c status register to set the specified bitmask -+ * Returns 0 if timed out (~100ms). -+ */ -+static short twi_wait_for_completion(struct atmel_twi *twi, -+ u32 mask) -+{ -+ int timeout = msecs_to_jiffies(100); -+ -+ twi->intmask = mask; -+ init_completion(&twi->comp); -+ -+ twi_writel(twi, IER, mask); -+ -+ if(!wait_for_completion_timeout(&twi->comp, timeout)) -+ return -ETIMEDOUT; -+ -+ return 0; -+} -+ -+/* -+ * Generic i2c master transfer entrypoint. -+ */ -+static int twi_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) -+{ -+ struct atmel_twi *twi = to_atmel_twi(adap); -+ struct i2c_msg *pmsg; -+ int i; -+ -+ /* get first message */ -+ pmsg = msgs; -+ -+ dev_dbg(&adap->dev, "twi_xfer: processing %d messages:\n", num); -+ -+ for (i = 0; i < num; i++, pmsg++) { -+ -+ twi->len = pmsg->len; -+ twi->buf = pmsg->buf; -+ twi->acks_left = pmsg->len; -+ twi_writel(twi, MMR, TWI_BF(DADR, pmsg->addr) | -+ (pmsg->flags & I2C_M_RD ? TWI_BIT(MREAD) : 0)); -+ twi_writel(twi, IADR, TWI_BF(IADR, pmsg->addr)); -+ -+ dev_dbg(&adap->dev,"#%d: internal addr %d %s byte%s %s 0x%02x\n", -+ i,pmsg->len, pmsg->flags & I2C_M_RD ? "reading" : "writing", -+ pmsg->len > 1 ? "s" : "", -+ pmsg->flags & I2C_M_RD ? "from" : "to", pmsg->addr); -+ -+ /* enable */ -+ twi_writel(twi, CR, TWI_BIT(MSEN)); -+ -+ if (pmsg->flags & I2C_M_RD) { -+ twi_writel(twi, CR, TWI_BIT(START)); -+ if ( twi_wait_for_completion(twi,TWI_BIT(RXRDY))==-ETIMEDOUT ) { -+ dev_dbg(&adap->dev, "RXRDY timeout. Stopped with %d bytes left\n", -+ twi->acks_left); -+ return -ETIMEDOUT; -+ } -+ -+ /* Send Stop, and Wait until transfer is finished */ -+ if ( twi_wait_for_completion(twi,TWI_BIT(TXCOMP))==-ETIMEDOUT ) { -+ dev_dbg(&adap->dev, "TXCOMP timeout\n"); -+ return -ETIMEDOUT; -+ } -+ -+ } else { -+ twi_writel(twi, THR, twi->buf[0]); -+ if ( twi_wait_for_completion(twi,TWI_BIT(TXRDY))==-ETIMEDOUT ) { -+ dev_dbg(&adap->dev, "TXRDY timeout. Stopped with %d bytes left\n", -+ twi->acks_left); -+ return -ETIMEDOUT; -+ } -+ } -+ -+ /* Disable TWI interface */ -+ twi_writel(twi, CR, TWI_BIT(MSDIS)); -+ -+ } /* end cur msg */ -+ -+ return i; -+} -+ -+ -+static irqreturn_t twi_interrupt(int irq, void *dev_id) -+{ -+ struct atmel_twi *twi = dev_id; -+ int status = twi_readl(twi, SR); -+ -+ if (twi->intmask & status){ -+ if (twi->intmask & TWI_BIT(NACK)) { -+ goto nack; -+ } else if (twi->intmask & TWI_BIT(RXRDY)){ -+ twi->buf[twi->len - twi->acks_left] = twi_readl(twi,RHR); -+ if(--twi->acks_left==1) -+ twi_writel(twi, CR, TWI_BIT(STOP)); -+ if (twi->acks_left==0) -+ goto complete; -+ } else if (twi->intmask & TWI_BIT(TXRDY)) { -+ twi->acks_left--; -+ if (twi->acks_left==0) { -+ twi->intmask = TWI_BIT(TXCOMP); -+ twi_writel(twi, IER, TWI_BIT(TXCOMP)); -+ } else -+ twi_writel(twi, THR, twi->buf[twi->len - twi->acks_left]); -+ } else if (twi->intmask & TWI_BIT(TXCOMP)) { -+ goto complete; -+ } -+ } -+ -+ return IRQ_HANDLED; -+ -+nack: -+ printk(KERN_INFO "NACK received!\n"); -+ -+complete: -+ twi_writel(twi, IDR, ~0UL); -+ complete(&twi->comp); -+ -+ return IRQ_HANDLED; -+ -+} -+ -+ -+/* -+ * Return list of supported functionality. -+ */ -+static u32 twi_func(struct i2c_adapter *adapter) -+{ -+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -+} -+ -+/* For now, we only handle combined mode (smbus) */ -+static struct i2c_algorithm twi_algorithm = { -+ .master_xfer = twi_xfer, -+ .functionality = twi_func, -+}; -+ -+/* -+ * Main initialization routine. -+ */ -+static int __devinit twi_probe(struct platform_device *pdev) -+{ -+ struct atmel_twi *twi; -+ struct resource *regs; -+ struct clk *pclk; -+ struct i2c_adapter *adapter; -+ int rc, irq; -+ -+ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!regs) -+ return -ENXIO; -+ -+ pclk = clk_get(&pdev->dev, "pclk"); -+ if (IS_ERR(pclk)) -+ return PTR_ERR(pclk); -+ clk_enable(pclk); -+ -+ rc = -ENOMEM; -+ twi = kzalloc(sizeof(struct atmel_twi), GFP_KERNEL); -+ if (!twi) { -+ dev_err(&pdev->dev, "can't allocate interface!\n"); -+ goto err_alloc_twi; -+ } -+ -+ twi->pclk = pclk; -+ twi->regs = ioremap(regs->start, regs->end - regs->start + 1); -+ if (!twi->regs) -+ goto err_ioremap; -+ -+ irq = platform_get_irq(pdev,0); -+ rc = request_irq(irq, twi_interrupt, 0, "twi", twi); -+ if (rc) { -+ dev_err(&pdev->dev, "can't bind irq!\n"); -+ goto err_irq; -+ } -+ twi->irq = irq; -+ -+ rc = twi_hwinit(twi); -+ if (rc) { -+ dev_err(&pdev->dev, "Unable to set baudrate\n"); -+ goto err_hw_init; -+ } -+ -+ adapter = &twi->adapter; -+ sprintf(adapter->name, "TWI"); -+ adapter->algo = &twi_algorithm; -+ adapter->class = I2C_CLASS_HWMON; -+ adapter->dev.parent = &pdev->dev; -+ -+ platform_set_drvdata(pdev, twi); -+ -+ rc = i2c_add_adapter(adapter); -+ if (rc) { -+ dev_err(&pdev->dev, "Adapter %s registration failed\n", -+ adapter->name); -+ goto err_register; -+ } -+ -+ dev_info(&pdev->dev, "Atmel TWI i2c bus device (baudrate %dk) at 0x%08lx.\n", -+ baudrate/1000, (unsigned long)regs->start); -+ -+ return 0; -+ -+ -+err_register: -+ platform_set_drvdata(pdev, NULL); -+ -+err_hw_init: -+ free_irq(irq, twi); -+ -+err_irq: -+ iounmap(twi->regs); -+ -+err_ioremap: -+ kfree(twi); -+ -+err_alloc_twi: -+ clk_disable(pclk); -+ clk_put(pclk); -+ -+ return rc; -+} -+ -+static int __devexit twi_remove(struct platform_device *pdev) -+{ -+ struct atmel_twi *twi = platform_get_drvdata(pdev); -+ int res; -+ -+ platform_set_drvdata(pdev, NULL); -+ res = i2c_del_adapter(&twi->adapter); -+ twi_writel(twi, CR, TWI_BIT(MSDIS)); -+ iounmap(twi->regs); -+ clk_disable(twi->pclk); -+ clk_put(twi->pclk); -+ free_irq(twi->irq, twi); -+ kfree(twi); -+ -+ return res; -+} -+ -+static struct platform_driver twi_driver = { -+ .probe = twi_probe, -+ .remove = __devexit_p(twi_remove), -+ .driver = { -+ .name = "atmel_twi", -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+static int __init atmel_twi_init(void) -+{ -+ return platform_driver_register(&twi_driver); -+} -+ -+static void __exit atmel_twi_exit(void) -+{ -+ platform_driver_unregister(&twi_driver); -+} -+ -+module_init(atmel_twi_init); -+module_exit(atmel_twi_exit); -+ -+MODULE_AUTHOR("Espen Krangnes"); -+MODULE_DESCRIPTION("I2C driver for Atmel TWI"); -+MODULE_LICENSE("GPL"); -diff -urN linux-2.6.20.4-0rig/drivers/i2c/busses/Kconfig linux-2.6.20.4-atmel/drivers/i2c/busses/Kconfig ---- linux-2.6.20.4-0rig/drivers/i2c/busses/Kconfig 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/i2c/busses/Kconfig 2007-03-24 16:42:29.000000000 +0100 -@@ -5,6 +5,26 @@ - menu "I2C Hardware Bus support" - depends on I2C - -+config I2C_ATMELTWI -+ tristate "Atmel TWI/I2C" -+ depends on I2C -+ help -+ Atmel on-chip TWI controller. Say Y if you have an AT32 or -+ AT91-based device and want to use its built-in TWI -+ functionality. Atmel's TWI is compatible with Philips' I2C -+ protocol. If in doubt, say NO -+ -+config I2C_ATMELTWI_BAUDRATE -+ prompt "Atmel TWI baudrate" -+ depends on I2C_ATMELTWI -+ int -+ default 100000 -+ help -+ Set the TWI/I2C baudrate. This will alter the default value. A -+ different baudrate can be set by using a module parameter as well. If -+ no parameter is provided when loading, this is the value that will be -+ used. -+ - config I2C_ALI1535 - tristate "ALI 1535" - depends on I2C && PCI -@@ -81,6 +101,14 @@ - This supports the use of the I2C interface on Atmel AT91 - processors. - -+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. -+ - config I2C_AU1550 - tristate "Au1550/Au1200 SMBus interface" - depends on I2C && (SOC_AU1550 || SOC_AU1200) -diff -urN linux-2.6.20.4-0rig/drivers/i2c/busses/Makefile linux-2.6.20.4-atmel/drivers/i2c/busses/Makefile ---- linux-2.6.20.4-0rig/drivers/i2c/busses/Makefile 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/i2c/busses/Makefile 2007-03-24 16:42:29.000000000 +0100 -@@ -46,6 +46,7 @@ - obj-$(CONFIG_I2C_VOODOO3) += i2c-voodoo3.o - obj-$(CONFIG_SCx200_ACB) += scx200_acb.o - obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o -+obj-$(CONFIG_I2C_ATMELTWI) += i2c-atmeltwi.o - - ifeq ($(CONFIG_I2C_DEBUG_BUS),y) - EXTRA_CFLAGS += -DDEBUG -diff -urN linux-2.6.20.4-0rig/drivers/input/touchscreen/ads7846.c linux-2.6.20.4-atmel/drivers/input/touchscreen/ads7846.c ---- linux-2.6.20.4-0rig/drivers/input/touchscreen/ads7846.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/input/touchscreen/ads7846.c 2007-03-24 16:39:15.000000000 +0100 -@@ -17,8 +17,9 @@ - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ --#include <linux/device.h> -+#include <linux/hwmon.h> - #include <linux/init.h> -+#include <linux/err.h> - #include <linux/delay.h> - #include <linux/input.h> - #include <linux/interrupt.h> -@@ -38,7 +39,8 @@ - /* - * This code has been heavily tested on a Nokia 770, and lightly - * tested on other ads7846 devices (OSK/Mistral, Lubbock). -- * Support for ads7843 and ads7845 has only been stubbed in. -+ * Support for ads7843 tested on Atmel at91sam926x-EK. -+ * Support for ads7845 has only been stubbed in. - * - * IRQ handling needs a workaround because of a shortcoming in handling - * edge triggered IRQs on some platforms like the OMAP1/2. These -@@ -54,7 +56,8 @@ - * files. - */ - --#define TS_POLL_PERIOD msecs_to_jiffies(10) -+#define TS_POLL_DELAY (1 * 1000000) /* ns delay before the first sample */ -+#define TS_POLL_PERIOD (5 * 1000000) /* ns delay between samples */ - - /* this driver doesn't aim at the peak continuous sample rate */ - #define SAMPLE_BITS (8 /*cmd*/ + 16 /*sample*/ + 2 /* before, after */) -@@ -63,12 +66,12 @@ - /* For portability, we can't read 12 bit values using SPI (which - * would make the controller deliver them as native byteorder u16 - * with msbs zeroed). Instead, we read them as two 8-bit values, -- * which need byteswapping then range adjustment. -+ * *** WHICH NEED BYTESWAPPING *** and range adjustment. - */ -- __be16 x; -- __be16 y; -- __be16 z1, z2; -- int ignore; -+ u16 x; -+ u16 y; -+ u16 z1, z2; -+ int ignore; - }; - - struct ads7846 { -@@ -76,7 +79,12 @@ - char phys[32]; - - struct spi_device *spi; -+ -+#if defined(CONFIG_HWMON) || defined(CONFIG_HWMON_MODULE) - struct attribute_group *attr_group; -+ struct class_device *hwmon; -+#endif -+ - u16 model; - u16 vref_delay_usecs; - u16 x_plate_ohms; -@@ -99,13 +107,16 @@ - u16 debounce_rep; - - spinlock_t lock; -- struct timer_list timer; /* P: lock */ -+ struct hrtimer timer; - unsigned pendown:1; /* P: lock */ - unsigned pending:1; /* P: lock */ - // FIXME remove "irq_disabled" - unsigned irq_disabled:1; /* P: lock */ - unsigned disabled:1; - -+ int (*filter)(void *data, int data_idx, int *val); -+ void *filter_data; -+ void (*filter_cleanup)(void *data); - int (*get_pendown_state)(void); - }; - -@@ -142,15 +153,16 @@ - #define MAX_12BIT ((1<<12)-1) - - /* leave ADC powered up (disables penirq) between differential samples */ --#define READ_12BIT_DFR(x) (ADS_START | ADS_A2A1A0_d_ ## x \ -- | ADS_12_BIT | ADS_DFR) -- --#define READ_Y (READ_12BIT_DFR(y) | ADS_PD10_ADC_ON) --#define READ_Z1 (READ_12BIT_DFR(z1) | ADS_PD10_ADC_ON) --#define READ_Z2 (READ_12BIT_DFR(z2) | ADS_PD10_ADC_ON) -+#define READ_12BIT_DFR(x, adc, vref) (ADS_START | ADS_A2A1A0_d_ ## x \ -+ | ADS_12_BIT | ADS_DFR | \ -+ (adc ? ADS_PD10_ADC_ON : 0) | (vref ? ADS_PD10_REF_ON : 0)) -+ -+#define READ_Y(vref) (READ_12BIT_DFR(y, 1, vref)) -+#define READ_Z1(vref) (READ_12BIT_DFR(z1, 1, vref)) -+#define READ_Z2(vref) (READ_12BIT_DFR(z2, 1, vref)) - --#define READ_X (READ_12BIT_DFR(x) | ADS_PD10_ADC_ON) --#define PWRDOWN (READ_12BIT_DFR(y) | ADS_PD10_PDOWN) /* LAST */ -+#define READ_X(vref) (READ_12BIT_DFR(x, 1, vref)) -+#define PWRDOWN (READ_12BIT_DFR(y, 0, 0)) /* LAST */ - - /* single-ended samples need to first power up reference voltage; - * we leave both ADC and VREF powered -@@ -158,14 +170,19 @@ - #define READ_12BIT_SER(x) (ADS_START | ADS_A2A1A0_ ## x \ - | ADS_12_BIT | ADS_SER) - --#define REF_ON (READ_12BIT_DFR(x) | ADS_PD10_ALL_ON) --#define REF_OFF (READ_12BIT_DFR(y) | ADS_PD10_PDOWN) -+#define REF_ON (READ_12BIT_DFR(x, 1, 1)) -+#define REF_OFF (READ_12BIT_DFR(y, 0, 0)) - - /*--------------------------------------------------------------------------*/ - - /* - * Non-touchscreen sensors only use single-ended conversions. -+ * The range is GND..vREF. The ads7843 and ads7835 must use external vREF; -+ * ads7846 lets that pin be unconnected, to use internal vREF. - */ -+static unsigned vREF_mV; -+module_param(vREF_mV, uint, 0); -+MODULE_PARM_DESC(vREF_mV, "external vREF voltage, in milliVolts"); - - struct ser_req { - u8 ref_on; -@@ -193,50 +210,53 @@ - struct ser_req *req = kzalloc(sizeof *req, GFP_KERNEL); - int status; - int sample; -- int i; -+ int use_internal; - - if (!req) - return -ENOMEM; - - spi_message_init(&req->msg); - -- /* activate reference, so it has time to settle; */ -- req->ref_on = REF_ON; -- req->xfer[0].tx_buf = &req->ref_on; -- req->xfer[0].len = 1; -- req->xfer[1].rx_buf = &req->scratch; -- req->xfer[1].len = 2; -- -- /* -- * for external VREF, 0 usec (and assume it's always on); -- * for 1uF, use 800 usec; -- * no cap, 100 usec. -- */ -- req->xfer[1].delay_usecs = ts->vref_delay_usecs; -+ /* FIXME boards with ads7846 might use external vref instead ... */ -+ use_internal = (ts->model == 7846); -+ -+ /* maybe turn on internal vREF, and let it settle */ -+ if (use_internal) { -+ req->ref_on = REF_ON; -+ req->xfer[0].tx_buf = &req->ref_on; -+ req->xfer[0].len = 1; -+ spi_message_add_tail(&req->xfer[0], &req->msg); -+ -+ req->xfer[1].rx_buf = &req->scratch; -+ req->xfer[1].len = 2; -+ -+ /* for 1uF, settle for 800 usec; no cap, 100 usec. */ -+ req->xfer[1].delay_usecs = ts->vref_delay_usecs; -+ spi_message_add_tail(&req->xfer[1], &req->msg); -+ } - - /* take sample */ - req->command = (u8) command; - req->xfer[2].tx_buf = &req->command; - req->xfer[2].len = 1; -+ spi_message_add_tail(&req->xfer[2], &req->msg); -+ - req->xfer[3].rx_buf = &req->sample; - req->xfer[3].len = 2; -+ spi_message_add_tail(&req->xfer[3], &req->msg); - - /* REVISIT: take a few more samples, and compare ... */ - -- /* turn off reference */ -- req->ref_off = REF_OFF; -+ /* converter in low power mode & enable PENIRQ */ -+ req->ref_off = PWRDOWN; - req->xfer[4].tx_buf = &req->ref_off; - req->xfer[4].len = 1; -+ spi_message_add_tail(&req->xfer[4], &req->msg); -+ - req->xfer[5].rx_buf = &req->scratch; - req->xfer[5].len = 2; -- - CS_CHANGE(req->xfer[5]); -- -- /* group all the transfers together, so we can't interfere with -- * reading touchscreen state; disable penirq while sampling -- */ -- for (i = 0; i < 6; i++) -- spi_message_add_tail(&req->xfer[i], &req->msg); -+ spi_message_add_tail(&req->xfer[5], &req->msg); - - ts->irq_disabled = 1; - disable_irq(spi->irq); -@@ -256,25 +276,173 @@ - return status ? status : sample; - } - --#define SHOW(name) static ssize_t \ -+#if defined(CONFIG_HWMON) || defined(CONFIG_HWMON_MODULE) -+ -+#define SHOW(name, var, adjust) static ssize_t \ - name ## _show(struct device *dev, struct device_attribute *attr, char *buf) \ - { \ -+ struct ads7846 *ts = dev_get_drvdata(dev); \ - ssize_t v = ads7846_read12_ser(dev, \ -- READ_12BIT_SER(name) | ADS_PD10_ALL_ON); \ -+ READ_12BIT_SER(var) | ADS_PD10_ALL_ON); \ - if (v < 0) \ - return v; \ -- return sprintf(buf, "%u\n", (unsigned) v); \ -+ return sprintf(buf, "%u\n", adjust(ts, v)); \ - } \ - static DEVICE_ATTR(name, S_IRUGO, name ## _show, NULL); - --SHOW(temp0) --SHOW(temp1) --SHOW(vaux) --SHOW(vbatt) -+ -+/* Sysfs conventions report temperatures in millidegrees Celcius. -+ * ADS7846 could use the low-accuracy two-sample scheme, but can't do the high -+ * accuracy scheme without calibration data. For now we won't try either; -+ * userspace sees raw sensor values, and must scale/calibrate appropriately. -+ */ -+static inline unsigned null_adjust(struct ads7846 *ts, ssize_t v) -+{ -+ return v; -+} -+ -+SHOW(temp0, temp0, null_adjust) /* temp1_input */ -+SHOW(temp1, temp1, null_adjust) /* temp2_input */ -+ -+ -+/* sysfs conventions report voltages in millivolts. We can convert voltages -+ * if we know vREF. userspace may need to scale vAUX to match the board's -+ * external resistors; we assume that vBATT only uses the internal ones. -+ */ -+static inline unsigned vaux_adjust(struct ads7846 *ts, ssize_t v) -+{ -+ unsigned retval = v; -+ -+ /* external resistors may scale vAUX into 0..vREF */ -+ retval *= vREF_mV; -+ retval = retval >> 12; -+ return retval; -+} -+ -+static inline unsigned vbatt_adjust(struct ads7846 *ts, ssize_t v) -+{ -+ unsigned retval = vaux_adjust(ts, v); -+ -+ /* ads7846 has a resistor ladder to scale this signal down */ -+ if (ts->model == 7846) -+ retval *= 4; -+ return retval; -+} -+ -+SHOW(in0_input, vaux, vaux_adjust) -+SHOW(in1_input, vbatt, vbatt_adjust) -+ -+ -+static struct attribute *ads7846_attributes[] = { -+ &dev_attr_temp0.attr, -+ &dev_attr_temp1.attr, -+ &dev_attr_in0_input.attr, -+ &dev_attr_in1_input.attr, -+ NULL, -+}; -+ -+static struct attribute_group ads7846_attr_group = { -+ .attrs = ads7846_attributes, -+}; -+ -+static struct attribute *ads7843_attributes[] = { -+ &dev_attr_in0_input.attr, -+ &dev_attr_in1_input.attr, -+ NULL, -+}; -+ -+static struct attribute_group ads7843_attr_group = { -+ .attrs = ads7843_attributes, -+}; -+ -+static struct attribute *ads7845_attributes[] = { -+ &dev_attr_in0_input.attr, -+ NULL, -+}; -+ -+static struct attribute_group ads7845_attr_group = { -+ .attrs = ads7845_attributes, -+}; -+ -+static int ads784x_hwmon_register(struct spi_device *spi, struct ads7846 *ts) -+{ -+ struct class_device *hwmon; -+ int err; -+ -+ /* hwmon sensors need a reference voltage */ -+ switch (ts->model) { -+ case 7846: -+ if (!vREF_mV) { -+ dev_dbg(&spi->dev, "assuming 2.5V internal vREF\n"); -+ vREF_mV = 2500; -+ } -+ break; -+ case 7845: -+ case 7843: -+ if (!vREF_mV) { -+ dev_warn(&spi->dev, -+ "external vREF for ADS%d not specified\n", -+ ts->model); -+ return 0; -+ } -+ break; -+ } -+ -+ /* different chips have different sensor groups */ -+ switch (ts->model) { -+ case 7846: -+ ts->attr_group = &ads7846_attr_group; -+ break; -+ case 7845: -+ ts->attr_group = &ads7845_attr_group; -+ break; -+ case 7843: -+ ts->attr_group = &ads7843_attr_group; -+ break; -+ default: -+ dev_dbg(&spi->dev, "ADS%d not recognized\n", ts->model); -+ return 0; -+ } -+ -+ err = sysfs_create_group(&spi->dev.kobj, ts->attr_group); -+ if (err) -+ return err; -+ -+ hwmon = hwmon_device_register(&spi->dev); -+ if (IS_ERR(hwmon)) { -+ sysfs_remove_group(&spi->dev.kobj, ts->attr_group); -+ return PTR_ERR(hwmon); -+ } -+ -+ ts->hwmon = hwmon; -+ return 0; -+} -+ -+static void ads784x_hwmon_unregister(struct spi_device *spi, -+ struct ads7846 *ts) -+{ -+ if (ts->hwmon) { -+ sysfs_remove_group(&spi->dev.kobj, ts->attr_group); -+ hwmon_device_unregister(ts->hwmon); -+ } -+} -+ -+#else -+static inline int ads784x_hwmon_register(struct spi_device *spi, -+ struct ads7846 *ts) -+{ -+ return 0; -+} -+ -+static inline void ads784x_hwmon_unregister(struct spi_device *spi, -+ struct ads7846 *ts) -+{ -+} -+#endif - - static int is_pen_down(struct device *dev) - { -- struct ads7846 *ts = dev_get_drvdata(dev); -+ struct ads7846 *ts = dev_get_drvdata(dev); - - return ts->pendown; - } -@@ -318,46 +486,14 @@ - - static DEVICE_ATTR(disable, 0664, ads7846_disable_show, ads7846_disable_store); - --static struct attribute *ads7846_attributes[] = { -- &dev_attr_temp0.attr, -- &dev_attr_temp1.attr, -- &dev_attr_vbatt.attr, -- &dev_attr_vaux.attr, -- &dev_attr_pen_down.attr, -- &dev_attr_disable.attr, -- NULL, --}; -- --static struct attribute_group ads7846_attr_group = { -- .attrs = ads7846_attributes, --}; -- --/* -- * ads7843/7845 don't have temperature sensors, and -- * use the other sensors a bit differently too -- */ -- --static struct attribute *ads7843_attributes[] = { -- &dev_attr_vbatt.attr, -- &dev_attr_vaux.attr, -+static struct attribute *ads784x_attributes[] = { - &dev_attr_pen_down.attr, - &dev_attr_disable.attr, - NULL, - }; - --static struct attribute_group ads7843_attr_group = { -- .attrs = ads7843_attributes, --}; -- --static struct attribute *ads7845_attributes[] = { -- &dev_attr_vaux.attr, -- &dev_attr_pen_down.attr, -- &dev_attr_disable.attr, -- NULL, --}; -- --static struct attribute_group ads7845_attr_group = { -- .attrs = ads7845_attributes, -+static struct attribute_group ads784x_attr_group = { -+ .attrs = ads784x_attributes, - }; - - /*--------------------------------------------------------------------------*/ -@@ -373,25 +509,22 @@ - static void ads7846_rx(void *ads) - { - struct ads7846 *ts = ads; -- struct input_dev *input_dev = ts->input; - unsigned Rt; -- unsigned sync = 0; - u16 x, y, z1, z2; -- unsigned long flags; - -- /* adjust: on-wire is a must-ignore bit, a BE12 value, then padding; -- * built from two 8 bit values written msb-first. -+ /* ads7846_rx_val() did in-place conversion (including byteswap) from -+ * on-the-wire format as part of debouncing to get stable readings. - */ -- x = (be16_to_cpu(ts->tc.x) >> 3) & 0x0fff; -- y = (be16_to_cpu(ts->tc.y) >> 3) & 0x0fff; -- z1 = (be16_to_cpu(ts->tc.z1) >> 3) & 0x0fff; -- z2 = (be16_to_cpu(ts->tc.z2) >> 3) & 0x0fff; -+ x = ts->tc.x; -+ y = ts->tc.y; -+ z1 = ts->tc.z1; -+ z2 = ts->tc.z2; - - /* range filtering */ - if (x == MAX_12BIT) - x = 0; - -- if (likely(x && z1 && !device_suspended(&ts->spi->dev))) { -+ if (likely(x && z1)) { - /* compute touch pressure resistance using equation #2 */ - Rt = z2; - Rt -= z1; -@@ -402,101 +535,134 @@ - } else - Rt = 0; - -+ if (ts->model == 7843) -+ Rt = ts->pressure_max / 2; -+ -+ - /* Sample found inconsistent by debouncing or pressure is beyond -- * the maximum. Don't report it to user space, repeat at least -- * once more the measurement */ -+ * the maximum. Don't report it to user space, repeat at least -+ * once more the measurement -+ */ - if (ts->tc.ignore || Rt > ts->pressure_max) { -- mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD); -+#ifdef VERBOSE -+ pr_debug("%s: ignored %d pressure %d\n", -+ ts->spi->dev.bus_id, ts->tc.ignore, Rt); -+#endif -+ hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), -+ HRTIMER_REL); - return; - } - -- /* NOTE: "pendown" is inferred from pressure; we don't rely on -- * being able to check nPENIRQ status, or "friendly" trigger modes -- * (both-edges is much better than just-falling or low-level). -- * -- * REVISIT: some boards may require reading nPENIRQ; it's -- * needed on 7843. and 7845 reads pressure differently... -+ /* NOTE: We can't rely on the pressure to determine the pen down -+ * state, even this controller has a pressure sensor. The pressure -+ * value can fluctuate for quite a while after lifting the pen and -+ * in some cases may not even settle at the expected value. - * -- * REVISIT: the touchscreen might not be connected; this code -- * won't notice that, even if nPENIRQ never fires ... -+ * The only safe way to check for the pen up condition is in the -+ * timer by reading the pen signal state (it's a GPIO _and_ IRQ). - */ -- if (!ts->pendown && Rt != 0) { -- input_report_key(input_dev, BTN_TOUCH, 1); -- sync = 1; -- } else if (ts->pendown && Rt == 0) { -- input_report_key(input_dev, BTN_TOUCH, 0); -- sync = 1; -- } -- - if (Rt) { -- input_report_abs(input_dev, ABS_X, x); -- input_report_abs(input_dev, ABS_Y, y); -- sync = 1; -- } -+ struct input_dev *input = ts->input; - -- if (sync) { -- input_report_abs(input_dev, ABS_PRESSURE, Rt); -- input_sync(input_dev); -- } -- --#ifdef VERBOSE -- if (Rt || ts->pendown) -- pr_debug("%s: %d/%d/%d%s\n", ts->spi->dev.bus_id, -- x, y, Rt, Rt ? "" : " UP"); -+ if (!ts->pendown) { -+ input_report_key(input, BTN_TOUCH, 1); -+ ts->pendown = 1; -+#ifdef VERBOSE -+ dev_dbg(&ts->spi->dev, "DOWN\n"); - #endif -+ } -+ input_report_abs(input, ABS_X, x); -+ input_report_abs(input, ABS_Y, y); -+ input_report_abs(input, ABS_PRESSURE, Rt); -+ -+ input_sync(input); -+#ifdef VERBOSE -+ dev_dbg(&ts->spi->dev, "%4d/%4d/%4d\n", x, y, Rt); -+#endif -+ } - -- spin_lock_irqsave(&ts->lock, flags); -- -- ts->pendown = (Rt != 0); -- mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD); -- -- spin_unlock_irqrestore(&ts->lock, flags); -+ hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), HRTIMER_REL); - } - --static void ads7846_debounce(void *ads) -+static int ads7846_debounce(void *ads, int data_idx, int *val) - { - struct ads7846 *ts = ads; -- struct spi_message *m; -- struct spi_transfer *t; -- int val; -- int status; - -- m = &ts->msg[ts->msg_idx]; -- t = list_entry(m->transfers.prev, struct spi_transfer, transfer_list); -- val = (be16_to_cpu(*(__be16 *)t->rx_buf) >> 3) & 0x0fff; -- if (!ts->read_cnt || (abs(ts->last_read - val) > ts->debounce_tol)) { -+ if (!ts->read_cnt || (abs(ts->last_read - *val) > ts->debounce_tol)) { -+ /* Start over collecting consistent readings. */ -+ ts->read_rep = 0; - /* Repeat it, if this was the first read or the read - * wasn't consistent enough. */ - if (ts->read_cnt < ts->debounce_max) { -- ts->last_read = val; -+ ts->last_read = *val; - ts->read_cnt++; -+ return ADS7846_FILTER_REPEAT; - } else { - /* Maximum number of debouncing reached and still - * not enough number of consistent readings. Abort - * the whole sample, repeat it in the next sampling - * period. - */ -- ts->tc.ignore = 1; - ts->read_cnt = 0; -- /* Last message will contain ads7846_rx() as the -- * completion function. -- */ -- m = ts->last_msg; -+ return ADS7846_FILTER_IGNORE; - } -- /* Start over collecting consistent readings. */ -- ts->read_rep = 0; - } else { - if (++ts->read_rep > ts->debounce_rep) { - /* Got a good reading for this coordinate, - * go for the next one. */ -- ts->tc.ignore = 0; -- ts->msg_idx++; - ts->read_cnt = 0; - ts->read_rep = 0; -- m++; -- } else -+ return ADS7846_FILTER_OK; -+ } else { - /* Read more values that are consistent. */ - ts->read_cnt++; -+ return ADS7846_FILTER_REPEAT; -+ } -+ } -+} -+ -+static int ads7846_no_filter(void *ads, int data_idx, int *val) -+{ -+ return ADS7846_FILTER_OK; -+} -+ -+static void ads7846_rx_val(void *ads) -+{ -+ struct ads7846 *ts = ads; -+ struct spi_message *m; -+ struct spi_transfer *t; -+ u16 *rx_val; -+ int val; -+ int action; -+ int status; -+ -+ m = &ts->msg[ts->msg_idx]; -+ t = list_entry(m->transfers.prev, struct spi_transfer, transfer_list); -+ rx_val = t->rx_buf; -+ -+ /* adjust: on-wire is a must-ignore bit, a BE12 value, then padding; -+ * built from two 8 bit values written msb-first. -+ */ -+ val = be16_to_cpu(*rx_val) >> 3; -+ -+ action = ts->filter(ts->filter_data, ts->msg_idx, &val); -+ switch (action) { -+ case ADS7846_FILTER_REPEAT: -+ break; -+ case ADS7846_FILTER_IGNORE: -+ ts->tc.ignore = 1; -+ /* Last message will contain ads7846_rx() as the -+ * completion function. -+ */ -+ m = ts->last_msg; -+ break; -+ case ADS7846_FILTER_OK: -+ *rx_val = val; -+ ts->tc.ignore = 0; -+ m = &ts->msg[++ts->msg_idx]; -+ break; -+ default: -+ BUG(); - } - status = spi_async(ts->spi, m); - if (status) -@@ -504,21 +670,34 @@ - status); - } - --static void ads7846_timer(unsigned long handle) -+static int ads7846_timer(struct hrtimer *handle) - { -- struct ads7846 *ts = (void *)handle; -+ struct ads7846 *ts = container_of(handle, struct ads7846, timer); - int status = 0; - - spin_lock_irq(&ts->lock); - -- if (unlikely(ts->msg_idx && !ts->pendown)) { -+ if (unlikely(!ts->get_pendown_state() || -+ device_suspended(&ts->spi->dev))) { -+ if (ts->pendown) { -+ struct input_dev *input = ts->input; -+ -+ input_report_key(input, BTN_TOUCH, 0); -+ input_report_abs(input, ABS_PRESSURE, 0); -+ input_sync(input); -+ -+ ts->pendown = 0; -+#ifdef VERBOSE -+ dev_dbg(&ts->spi->dev, "UP\n"); -+#endif -+ } -+ - /* measurement cycle ended */ - if (!device_suspended(&ts->spi->dev)) { - ts->irq_disabled = 0; - enable_irq(ts->spi->irq); - } - ts->pending = 0; -- ts->msg_idx = 0; - } else { - /* pen is still down, continue with the measurement */ - ts->msg_idx = 0; -@@ -528,6 +707,7 @@ - } - - spin_unlock_irq(&ts->lock); -+ return HRTIMER_NORESTART; - } - - static irqreturn_t ads7846_irq(int irq, void *handle) -@@ -546,7 +726,8 @@ - ts->irq_disabled = 1; - disable_irq(ts->spi->irq); - ts->pending = 1; -- mod_timer(&ts->timer, jiffies); -+ hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_DELAY), -+ HRTIMER_REL); - } - } - spin_unlock_irqrestore(&ts->lock, flags); -@@ -632,6 +813,7 @@ - struct ads7846_platform_data *pdata = spi->dev.platform_data; - struct spi_message *m; - struct spi_transfer *x; -+ int vref; - int err; - - if (!spi->irq) { -@@ -665,6 +847,10 @@ - * may not. So we stick to very-portable 8 bit words, both RX and TX. - */ - spi->bits_per_word = 8; -+ spi->mode = SPI_MODE_1; -+ err = spi_setup(spi); -+ if (err < 0) -+ return err; - - ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL); - input_dev = input_allocate_device(); -@@ -679,8 +865,7 @@ - ts->spi = spi; - ts->input = input_dev; - -- init_timer(&ts->timer); -- ts->timer.data = (unsigned long) ts; -+ hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_REL); - ts->timer.function = ads7846_timer; - - spin_lock_init(&ts->lock); -@@ -689,14 +874,25 @@ - ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100; - ts->x_plate_ohms = pdata->x_plate_ohms ? : 400; - ts->pressure_max = pdata->pressure_max ? : ~0; -- if (pdata->debounce_max) { -+ -+ if (pdata->filter != NULL) { -+ if (pdata->filter_init != NULL) { -+ err = pdata->filter_init(pdata, &ts->filter_data); -+ if (err < 0) -+ goto err_free_mem; -+ } -+ ts->filter = pdata->filter; -+ ts->filter_cleanup = pdata->filter_cleanup; -+ } else if (pdata->debounce_max) { - ts->debounce_max = pdata->debounce_max; -+ if (ts->debounce_max < 2) -+ ts->debounce_max = 2; - ts->debounce_tol = pdata->debounce_tol; - ts->debounce_rep = pdata->debounce_rep; -- if (ts->debounce_rep > ts->debounce_max + 1) -- ts->debounce_rep = ts->debounce_max - 1; -+ ts->filter = ads7846_debounce; -+ ts->filter_data = ts; - } else -- ts->debounce_tol = ~0; -+ ts->filter = ads7846_no_filter; - ts->get_pendown_state = pdata->get_pendown_state; - - snprintf(ts->phys, sizeof(ts->phys), "%s/input0", spi->dev.bus_id); -@@ -718,6 +914,8 @@ - input_set_abs_params(input_dev, ABS_PRESSURE, - pdata->pressure_min, pdata->pressure_max, 0, 0); - -+ vref = pdata->keep_vref_on; -+ - /* set up the transfers to read touchscreen state; this assumes we - * use formula #2 for pressure, not #3. - */ -@@ -727,7 +925,7 @@ - spi_message_init(m); - - /* y- still on; turn on only y+ (and ADC) */ -- ts->read_y = READ_Y; -+ ts->read_y = READ_Y(vref); - x->tx_buf = &ts->read_y; - x->len = 1; - spi_message_add_tail(x, m); -@@ -737,7 +935,7 @@ - x->len = 2; - spi_message_add_tail(x, m); - -- m->complete = ads7846_debounce; -+ m->complete = ads7846_rx_val; - m->context = ts; - - m++; -@@ -745,7 +943,7 @@ - - /* turn y- off, x+ on, then leave in lowpower */ - x++; -- ts->read_x = READ_X; -+ ts->read_x = READ_X(vref); - x->tx_buf = &ts->read_x; - x->len = 1; - spi_message_add_tail(x, m); -@@ -755,7 +953,7 @@ - x->len = 2; - spi_message_add_tail(x, m); - -- m->complete = ads7846_debounce; -+ m->complete = ads7846_rx_val; - m->context = ts; - - /* turn y+ off, x- on; we'll use formula #2 */ -@@ -764,7 +962,7 @@ - spi_message_init(m); - - x++; -- ts->read_z1 = READ_Z1; -+ ts->read_z1 = READ_Z1(vref); - x->tx_buf = &ts->read_z1; - x->len = 1; - spi_message_add_tail(x, m); -@@ -774,14 +972,14 @@ - x->len = 2; - spi_message_add_tail(x, m); - -- m->complete = ads7846_debounce; -+ m->complete = ads7846_rx_val; - m->context = ts; - - m++; - spi_message_init(m); - - x++; -- ts->read_z2 = READ_Z2; -+ ts->read_z2 = READ_Z2(vref); - x->tx_buf = &ts->read_z2; - x->len = 1; - spi_message_add_tail(x, m); -@@ -791,7 +989,7 @@ - x->len = 2; - spi_message_add_tail(x, m); - -- m->complete = ads7846_debounce; -+ m->complete = ads7846_rx_val; - m->context = ts; - } - -@@ -820,31 +1018,24 @@ - spi->dev.driver->name, ts)) { - dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq); - err = -EBUSY; -- goto err_free_mem; -+ goto err_cleanup_filter; - } - -+ err = ads784x_hwmon_register(spi, ts); -+ if (err) -+ goto err_free_irq; -+ - dev_info(&spi->dev, "touchscreen, irq %d\n", spi->irq); - -- /* take a first sample, leaving nPENIRQ active; avoid -+ /* take a first sample, leaving nPENIRQ active and vREF off; avoid - * the touchscreen, in case it's not connected. - */ - (void) ads7846_read12_ser(&spi->dev, - READ_12BIT_SER(vaux) | ADS_PD10_ALL_ON); - -- switch (ts->model) { -- case 7846: -- ts->attr_group = &ads7846_attr_group; -- break; -- case 7845: -- ts->attr_group = &ads7845_attr_group; -- break; -- default: -- ts->attr_group = &ads7843_attr_group; -- break; -- } -- err = sysfs_create_group(&spi->dev.kobj, ts->attr_group); -+ err = sysfs_create_group(&spi->dev.kobj, &ads784x_attr_group); - if (err) -- goto err_free_irq; -+ goto err_remove_hwmon; - - err = input_register_device(input_dev); - if (err) -@@ -853,9 +1044,14 @@ - return 0; - - err_remove_attr_group: -- sysfs_remove_group(&spi->dev.kobj, ts->attr_group); -+ sysfs_remove_group(&spi->dev.kobj, &ads784x_attr_group); -+ err_remove_hwmon: -+ ads784x_hwmon_unregister(spi, ts); - err_free_irq: - free_irq(spi->irq, ts); -+ err_cleanup_filter: -+ if (ts->filter_cleanup) -+ ts->filter_cleanup(ts->filter_data); - err_free_mem: - input_free_device(input_dev); - kfree(ts); -@@ -866,16 +1062,20 @@ - { - struct ads7846 *ts = dev_get_drvdata(&spi->dev); - -+ ads784x_hwmon_unregister(spi, ts); - input_unregister_device(ts->input); - - ads7846_suspend(spi, PMSG_SUSPEND); - -- sysfs_remove_group(&spi->dev.kobj, ts->attr_group); -+ sysfs_remove_group(&spi->dev.kobj, &ads784x_attr_group); - - free_irq(ts->spi->irq, ts); - /* suspend left the IRQ disabled */ - enable_irq(ts->spi->irq); - -+ if (ts->filter_cleanup) -+ ts->filter_cleanup(ts->filter_data); -+ - kfree(ts); - - dev_dbg(&spi->dev, "unregistered touchscreen\n"); -diff -urN linux-2.6.20.4-0rig/drivers/leds/Kconfig linux-2.6.20.4-atmel/drivers/leds/Kconfig ---- linux-2.6.20.4-0rig/drivers/leds/Kconfig 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/leds/Kconfig 2007-03-24 16:39:15.000000000 +0100 -@@ -76,6 +76,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 -+ This option enables support for LEDs connected to GPIO lines -+ on AT91-based boards. -+ - config LEDS_WRAP - tristate "LED Support for the WRAP series LEDs" - depends on LEDS_CLASS && SCx200_GPIO -diff -urN linux-2.6.20.4-0rig/drivers/leds/leds-at91.c linux-2.6.20.4-atmel/drivers/leds/leds-at91.c ---- linux-2.6.20.4-0rig/drivers/leds/leds-at91.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/leds/leds-at91.c 2007-03-24 16:39:15.000000000 +0100 -@@ -0,0 +1,140 @@ -+/* -+ * AT91 GPIO based LED driver -+ * -+ * 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. -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/init.h> -+#include <linux/platform_device.h> -+#include <linux/leds.h> -+ -+#include <asm/arch/board.h> -+#include <asm/arch/gpio.h> -+ -+static LIST_HEAD(at91_led_list); /* list of AT91 LEDs */ -+ -+struct at91_led { -+ struct led_classdev cdev; -+ struct list_head list; -+ struct at91_gpio_led *led_data; -+}; -+ -+/* -+ * 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); -+ -+ if (led->led_data->flags & 1) /* active high/low? */ -+ active = !active; -+ at91_set_gpio_value(led->led_data->gpio, value == LED_OFF); -+} -+ -+static int __devexit at91_led_remove(struct platform_device *pdev) -+{ -+ struct at91_led *led; -+ -+ list_for_each_entry (led, &at91_led_list, list) -+ led_classdev_unregister(&led->cdev); -+ -+#warning "Free allocated memory" -+ // TODO: Free memory. kfree(led); -+ -+ return 0; -+} -+ -+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; -+ -+ if (!pdata) -+ return -ENODEV; -+ -+ nr_leds = pdata->index; /* first index stores number of LEDs */ -+ -+ 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 at91_led *led; -+ -+ list_for_each_entry (led, &at91_led_list, list) -+ led_classdev_suspend(&led->cdev); -+ -+ return 0; -+} -+ -+static int at91_led_resume(struct platform_device *dev) -+{ -+ struct at91_led *led; -+ -+ list_for_each_entry (led, &at91_led_list, list) -+ led_classdev_resume(&led->cdev); -+ -+ return 0; -+} -+#else -+#define at91_led_suspend NULL -+#define at91_led_resume NULL -+#endif -+ -+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, -+ }, -+}; -+ -+static int __init at91_led_init(void) -+{ -+ return platform_driver_register(&at91_led_driver); -+} -+module_init(at91_led_init); -+ -+static void __exit at91_led_exit(void) -+{ -+ platform_driver_unregister(&at91_led_driver); -+} -+module_exit(at91_led_exit); -+ -+MODULE_DESCRIPTION("AT91 GPIO LED driver"); -+MODULE_AUTHOR("David Brownell"); -+MODULE_LICENSE("GPL"); -diff -urN linux-2.6.20.4-0rig/drivers/leds/Makefile linux-2.6.20.4-atmel/drivers/leds/Makefile ---- linux-2.6.20.4-0rig/drivers/leds/Makefile 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/leds/Makefile 2007-03-24 16:39:15.000000000 +0100 -@@ -14,6 +14,7 @@ - obj-$(CONFIG_LEDS_AMS_DELTA) += leds-ams-delta.o - obj-$(CONFIG_LEDS_NET48XX) += leds-net48xx.o - obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o -+obj-$(CONFIG_LEDS_AT91) += leds-at91.o - - # LED Triggers - obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o -diff -urN linux-2.6.20.4-0rig/drivers/mmc/at91_mci.c linux-2.6.20.4-atmel/drivers/mmc/at91_mci.c ---- linux-2.6.20.4-0rig/drivers/mmc/at91_mci.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/mmc/at91_mci.c 2007-03-24 16:39:15.000000000 +0100 -@@ -64,6 +64,7 @@ - #include <linux/err.h> - #include <linux/dma-mapping.h> - #include <linux/clk.h> -+#include <linux/atmel_pdc.h> - - #include <linux/mmc/host.h> - #include <linux/mmc/protocol.h> -@@ -75,7 +76,7 @@ - #include <asm/arch/cpu.h> - #include <asm/arch/gpio.h> - #include <asm/arch/at91_mci.h> --#include <asm/arch/at91_pdc.h> -+ - - #define DRIVER_NAME "at91_mci" - -@@ -85,8 +86,8 @@ - #define FL_SENT_STOP (1 << 1) - - #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_RENDE | AT91_MCI_RTOE | AT91_MCI_DCRCE \ -+ | 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)) -@@ -211,13 +212,13 @@ - - /* Check to see if this needs filling */ - if (i == 0) { -- if (at91_mci_read(host, AT91_PDC_RCR) != 0) { -+ if (at91_mci_read(host, ATMEL_PDC_RCR) != 0) { - pr_debug("Transfer active in current\n"); - continue; - } - } - else { -- if (at91_mci_read(host, AT91_PDC_RNCR) != 0) { -+ if (at91_mci_read(host, ATMEL_PDC_RNCR) != 0) { - pr_debug("Transfer active in next\n"); - continue; - } -@@ -234,12 +235,12 @@ - pr_debug("dma address = %08X, length = %d\n", sg->dma_address, sg->length); - - if (i == 0) { -- at91_mci_write(host, AT91_PDC_RPR, sg->dma_address); -- at91_mci_write(host, AT91_PDC_RCR, sg->length / 4); -+ at91_mci_write(host, ATMEL_PDC_RPR, sg->dma_address); -+ at91_mci_write(host, ATMEL_PDC_RCR, sg->length / 4); - } - else { -- at91_mci_write(host, AT91_PDC_RNPR, sg->dma_address); -- at91_mci_write(host, AT91_PDC_RNCR, sg->length / 4); -+ at91_mci_write(host, ATMEL_PDC_RNPR, sg->dma_address); -+ at91_mci_write(host, ATMEL_PDC_RNCR, sg->length / 4); - } - } - -@@ -303,37 +304,12 @@ - at91mci_pre_dma_read(host); - else { - at91_mci_write(host, AT91_MCI_IER, AT91_MCI_RXBUFF); -- at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS); -+ at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS); - } - - pr_debug("post dma read done\n"); - } - --/* -- * Handle transmitted data -- */ --static void at91_mci_handle_transmitted(struct at91mci_host *host) --{ -- struct mmc_command *cmd; -- struct mmc_data *data; -- -- pr_debug("Handling the transmit\n"); -- -- /* Disable the transfer */ -- at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS); -- -- /* Now wait for cmd ready */ -- at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_TXBUFE); -- at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY); -- -- cmd = host->cmd; -- if (!cmd) return; -- -- data = cmd->data; -- if (!data) return; -- -- data->bytes_xfered = host->total_length; --} - - /* - * Enable the controller -@@ -431,15 +407,15 @@ - cmd->opcode, cmdr, cmd->arg, blocks, block_length, at91_mci_read(host, AT91_MCI_MR)); - - if (!data) { -- at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_TXTDIS | AT91_PDC_RXTDIS); -- at91_mci_write(host, AT91_PDC_RPR, 0); -- at91_mci_write(host, AT91_PDC_RCR, 0); -- at91_mci_write(host, AT91_PDC_RNPR, 0); -- at91_mci_write(host, AT91_PDC_RNCR, 0); -- at91_mci_write(host, AT91_PDC_TPR, 0); -- at91_mci_write(host, AT91_PDC_TCR, 0); -- at91_mci_write(host, AT91_PDC_TNPR, 0); -- at91_mci_write(host, AT91_PDC_TNCR, 0); -+ at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS | ATMEL_PDC_RXTDIS); -+ at91_mci_write(host, ATMEL_PDC_RPR, 0); -+ at91_mci_write(host, ATMEL_PDC_RCR, 0); -+ at91_mci_write(host, ATMEL_PDC_RNPR, 0); -+ at91_mci_write(host, ATMEL_PDC_RNCR, 0); -+ at91_mci_write(host, ATMEL_PDC_TPR, 0); -+ at91_mci_write(host, ATMEL_PDC_TCR, 0); -+ at91_mci_write(host, ATMEL_PDC_TNPR, 0); -+ at91_mci_write(host, ATMEL_PDC_TNCR, 0); - - at91_mci_write(host, AT91_MCI_ARGR, cmd->arg); - at91_mci_write(host, AT91_MCI_CMDR, cmdr); -@@ -452,7 +428,7 @@ - /* - * Disable the PDC controller - */ -- at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS); -+ at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS); - - if (cmdr & AT91_MCI_TRCMD_START) { - data->bytes_xfered = 0; -@@ -474,15 +450,15 @@ - */ - host->total_length = block_length * blocks; - host->buffer = dma_alloc_coherent(NULL, -- host->total_length, -- &host->physical_address, GFP_KERNEL); -+ host->total_length, -+ &host->physical_address, GFP_KERNEL); - - at91mci_sg_to_dma(host, data); - - pr_debug("Transmitting %d bytes\n", host->total_length); - -- at91_mci_write(host, AT91_PDC_TPR, host->physical_address); -- at91_mci_write(host, AT91_PDC_TCR, host->total_length / 4); -+ at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address); -+ at91_mci_write(host, ATMEL_PDC_TCR, host->total_length / 4); - ier = AT91_MCI_TXBUFE; - } - } -@@ -497,9 +473,9 @@ - - if (cmdr & AT91_MCI_TRCMD_START) { - if (cmdr & AT91_MCI_TRDIR) -- at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_RXTEN); -+ at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN); - else -- at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_TXTEN); -+ at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN); - } - return ier; - } -@@ -561,9 +537,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) && - ((cmd->opcode == MMC_SEND_OP_COND) || (cmd->opcode == SD_APP_OP_COND))) { - cmd->error = MMC_ERR_NONE; -@@ -601,6 +575,32 @@ - } - - /* -+ * Handle transmitted data -+ */ -+static void at91_mci_handle_transmitted(struct at91mci_host *host) -+{ -+ struct mmc_command *cmd; -+ struct mmc_data *data; -+ -+ pr_debug("Handling the transmit\n"); -+ -+ /* Disable the transfer */ -+ at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS); -+ -+ /* Now wait for cmd ready */ -+ at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_TXBUFE); -+ at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY); -+ -+ cmd = host->cmd; -+ if (!cmd) return; -+ -+ data = cmd->data; -+ if (!data) return; -+ -+ data->bytes_xfered = host->total_length; -+} -+ -+/* - * Set the IOS - */ - static void at91_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) -@@ -665,15 +665,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; - - 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) -@@ -821,7 +821,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; - - host = mmc_priv(mmc); - host->mmc = mmc; -@@ -853,15 +853,15 @@ - host->baseaddr = ioremap(res->start, res->end - res->start + 1); - if (!host->baseaddr) { - clk_put(host->mci_clk); -- mmc_free_host(mmc); - release_mem_region(res->start, res->end - res->start + 1); -+ mmc_free_host(mmc); - return -ENOMEM; - } - - /* - * Reset hardware - */ -- clk_enable(host->mci_clk); /* Enable the peripheral clock */ -+ clk_enable(host->mci_clk); /* Enable the peripheral clock */ - at91_mci_disable(host); - at91_mci_enable(host); - -@@ -874,9 +874,9 @@ - printk(KERN_ERR "AT91 MMC: Failed to request MCI interrupt\n"); - clk_disable(host->mci_clk); - clk_put(host->mci_clk); -- mmc_free_host(mmc); - iounmap(host->baseaddr); - release_mem_region(res->start, res->end - res->start + 1); -+ mmc_free_host(mmc); - return ret; - } - -@@ -930,13 +930,13 @@ - mmc_remove_host(mmc); - free_irq(host->irq, host); - -- clk_disable(host->mci_clk); /* Disable the peripheral clock */ -- clk_put(host->mci_clk); -- - iounmap(host->baseaddr); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(res->start, res->end - res->start + 1); - -+ clk_disable(host->mci_clk); /* Disable the peripheral clock */ -+ clk_put(host->mci_clk); -+ - mmc_free_host(mmc); - platform_set_drvdata(pdev, NULL); - pr_debug("MCI Removed\n"); -diff -urN linux-2.6.20.4-0rig/drivers/mmc/atmel-mci.c linux-2.6.20.4-atmel/drivers/mmc/atmel-mci.c ---- linux-2.6.20.4-0rig/drivers/mmc/atmel-mci.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/mmc/atmel-mci.c 2007-03-24 16:42:29.000000000 +0100 -@@ -0,0 +1,1218 @@ -+/* -+ * Atmel MultiMedia Card Interface driver -+ * -+ * Copyright (C) 2004-2006 Atmel Corporation -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+#include <linux/blkdev.h> -+#include <linux/clk.h> -+#include <linux/device.h> -+#include <linux/dma-mapping.h> -+#include <linux/init.h> -+#include <linux/interrupt.h> -+#include <linux/ioport.h> -+#include <linux/module.h> -+#include <linux/platform_device.h> -+ -+#include <linux/mmc/host.h> -+#include <linux/mmc/protocol.h> -+ -+#include <asm/dma-controller.h> -+#include <asm/io.h> -+#include <asm/arch/board.h> -+#include <asm/arch/gpio.h> -+ -+#include "atmel-mci.h" -+ -+#define DRIVER_NAME "atmel_mci" -+ -+#define MCI_CMD_ERROR_FLAGS (MCI_BIT(RINDE) | MCI_BIT(RDIRE) | \ -+ MCI_BIT(RCRCE) | MCI_BIT(RENDE) | \ -+ MCI_BIT(RTOE)) -+#define MCI_DATA_ERROR_FLAGS (MCI_BIT(DCRCE) | MCI_BIT(DTOE) | \ -+ MCI_BIT(OVRE) | MCI_BIT(UNRE)) -+ -+enum { -+ EVENT_CMD_COMPLETE = 0, -+ EVENT_CMD_ERROR, -+ EVENT_DATA_COMPLETE, -+ EVENT_DATA_ERROR, -+ EVENT_STOP_SENT, -+ EVENT_STOP_COMPLETE, -+ EVENT_STOP_ERROR, -+ EVENT_DMA_ERROR, -+ EVENT_CARD_DETECT, -+}; -+ -+struct atmel_mci_dma { -+ struct dma_request_sg req; -+ unsigned short rx_periph_id; -+ unsigned short tx_periph_id; -+}; -+ -+struct atmel_mci { -+ struct mmc_host *mmc; -+ void __iomem *regs; -+ struct atmel_mci_dma dma; -+ -+ struct mmc_request *mrq; -+ struct mmc_command *cmd; -+ struct mmc_data *data; -+ -+ u32 stop_cmdr; -+ u32 stop_iflags; -+ -+ struct tasklet_struct tasklet; -+ unsigned long pending_events; -+ unsigned long completed_events; -+ u32 error_status; -+ -+ int present; -+ int detect_pin; -+ int wp_pin; -+ -+ unsigned long bus_hz; -+ unsigned long mapbase; -+ struct clk *mck; -+ struct platform_device *pdev; -+ -+#ifdef CONFIG_DEBUG_FS -+ struct dentry *debugfs_root; -+ struct dentry *debugfs_regs; -+ struct dentry *debugfs_req; -+ struct dentry *debugfs_pending_events; -+ struct dentry *debugfs_completed_events; -+#endif -+}; -+ -+/* Those printks take an awful lot of time... */ -+#ifndef DEBUG -+static unsigned int fmax = 15000000U; -+#else -+static unsigned int fmax = 1000000U; -+#endif -+module_param(fmax, uint, 0444); -+MODULE_PARM_DESC(fmax, "Max frequency in Hz of the MMC bus clock"); -+ -+/* Test bit macros for completed events */ -+#define mci_cmd_is_complete(host) \ -+ test_bit(EVENT_CMD_COMPLETE, &host->completed_events) -+#define mci_cmd_error_is_complete(host) \ -+ test_bit(EVENT_CMD_ERROR, &host->completed_events) -+#define mci_data_is_complete(host) \ -+ test_bit(EVENT_DATA_COMPLETE, &host->completed_events) -+#define mci_data_error_is_complete(host) \ -+ test_bit(EVENT_DATA_ERROR, &host->completed_events) -+#define mci_stop_sent_is_complete(host) \ -+ test_bit(EVENT_STOP_SENT, &host->completed_events) -+#define mci_stop_is_complete(host) \ -+ test_bit(EVENT_STOP_COMPLETE, &host->completed_events) -+#define mci_stop_error_is_complete(host) \ -+ test_bit(EVENT_STOP_ERROR, &host->completed_events) -+#define mci_dma_error_is_complete(host) \ -+ test_bit(EVENT_DMA_ERROR, &host->completed_events) -+#define mci_card_detect_is_complete(host) \ -+ test_bit(EVENT_CARD_DETECT, &host->completed_events) -+ -+/* Test and clear bit macros for pending events */ -+#define mci_clear_cmd_is_pending(host) \ -+ test_and_clear_bit(EVENT_CMD_COMPLETE, &host->pending_events) -+#define mci_clear_cmd_error_is_pending(host) \ -+ test_and_clear_bit(EVENT_CMD_ERROR, &host->pending_events) -+#define mci_clear_data_is_pending(host) \ -+ test_and_clear_bit(EVENT_DATA_COMPLETE, &host->pending_events) -+#define mci_clear_data_error_is_pending(host) \ -+ test_and_clear_bit(EVENT_DATA_ERROR, &host->pending_events) -+#define mci_clear_stop_sent_is_pending(host) \ -+ test_and_clear_bit(EVENT_STOP_SENT, &host->pending_events) -+#define mci_clear_stop_is_pending(host) \ -+ test_and_clear_bit(EVENT_STOP_COMPLETE, &host->pending_events) -+#define mci_clear_stop_error_is_pending(host) \ -+ test_and_clear_bit(EVENT_STOP_ERROR, &host->pending_events) -+#define mci_clear_dma_error_is_pending(host) \ -+ test_and_clear_bit(EVENT_DMA_ERROR, &host->pending_events) -+#define mci_clear_card_detect_is_pending(host) \ -+ test_and_clear_bit(EVENT_CARD_DETECT, &host->pending_events) -+ -+/* Test and set bit macros for completed events */ -+#define mci_set_cmd_is_completed(host) \ -+ test_and_set_bit(EVENT_CMD_COMPLETE, &host->completed_events) -+#define mci_set_cmd_error_is_completed(host) \ -+ test_and_set_bit(EVENT_CMD_ERROR, &host->completed_events) -+#define mci_set_data_is_completed(host) \ -+ test_and_set_bit(EVENT_DATA_COMPLETE, &host->completed_events) -+#define mci_set_data_error_is_completed(host) \ -+ test_and_set_bit(EVENT_DATA_ERROR, &host->completed_events) -+#define mci_set_stop_sent_is_completed(host) \ -+ test_and_set_bit(EVENT_STOP_SENT, &host->completed_events) -+#define mci_set_stop_is_completed(host) \ -+ test_and_set_bit(EVENT_STOP_COMPLETE, &host->completed_events) -+#define mci_set_stop_error_is_completed(host) \ -+ test_and_set_bit(EVENT_STOP_ERROR, &host->completed_events) -+#define mci_set_dma_error_is_completed(host) \ -+ test_and_set_bit(EVENT_DMA_ERROR, &host->completed_events) -+#define mci_set_card_detect_is_completed(host) \ -+ test_and_set_bit(EVENT_CARD_DETECT, &host->completed_events) -+ -+/* Set bit macros for completed events */ -+#define mci_set_cmd_complete(host) \ -+ set_bit(EVENT_CMD_COMPLETE, &host->completed_events) -+#define mci_set_cmd_error_complete(host) \ -+ set_bit(EVENT_CMD_ERROR, &host->completed_events) -+#define mci_set_data_complete(host) \ -+ set_bit(EVENT_DATA_COMPLETE, &host->completed_events) -+#define mci_set_data_error_complete(host) \ -+ set_bit(EVENT_DATA_ERROR, &host->completed_events) -+#define mci_set_stop_sent_complete(host) \ -+ set_bit(EVENT_STOP_SENT, &host->completed_events) -+#define mci_set_stop_complete(host) \ -+ set_bit(EVENT_STOP_COMPLETE, &host->completed_events) -+#define mci_set_stop_error_complete(host) \ -+ set_bit(EVENT_STOP_ERROR, &host->completed_events) -+#define mci_set_dma_error_complete(host) \ -+ set_bit(EVENT_DMA_ERROR, &host->completed_events) -+#define mci_set_card_detect_complete(host) \ -+ set_bit(EVENT_CARD_DETECT, &host->completed_events) -+ -+/* Set bit macros for pending events */ -+#define mci_set_cmd_pending(host) \ -+ set_bit(EVENT_CMD_COMPLETE, &host->pending_events) -+#define mci_set_cmd_error_pending(host) \ -+ set_bit(EVENT_CMD_ERROR, &host->pending_events) -+#define mci_set_data_pending(host) \ -+ set_bit(EVENT_DATA_COMPLETE, &host->pending_events) -+#define mci_set_data_error_pending(host) \ -+ set_bit(EVENT_DATA_ERROR, &host->pending_events) -+#define mci_set_stop_sent_pending(host) \ -+ set_bit(EVENT_STOP_SENT, &host->pending_events) -+#define mci_set_stop_pending(host) \ -+ set_bit(EVENT_STOP_COMPLETE, &host->pending_events) -+#define mci_set_stop_error_pending(host) \ -+ set_bit(EVENT_STOP_ERROR, &host->pending_events) -+#define mci_set_dma_error_pending(host) \ -+ set_bit(EVENT_DMA_ERROR, &host->pending_events) -+#define mci_set_card_detect_pending(host) \ -+ set_bit(EVENT_CARD_DETECT, &host->pending_events) -+ -+/* Clear bit macros for pending events */ -+#define mci_clear_cmd_pending(host) \ -+ clear_bit(EVENT_CMD_COMPLETE, &host->pending_events) -+#define mci_clear_cmd_error_pending(host) \ -+ clear_bit(EVENT_CMD_ERROR, &host->pending_events) -+#define mci_clear_data_pending(host) \ -+ clear_bit(EVENT_DATA_COMPLETE, &host->pending_events) -+#define mci_clear_data_error_pending(host) \ -+ clear_bit(EVENT_DATA_ERROR, &host->pending_events) -+#define mci_clear_stop_sent_pending(host) \ -+ clear_bit(EVENT_STOP_SENT, &host->pending_events) -+#define mci_clear_stop_pending(host) \ -+ clear_bit(EVENT_STOP_COMPLETE, &host->pending_events) -+#define mci_clear_stop_error_pending(host) \ -+ clear_bit(EVENT_STOP_ERROR, &host->pending_events) -+#define mci_clear_dma_error_pending(host) \ -+ clear_bit(EVENT_DMA_ERROR, &host->pending_events) -+#define mci_clear_card_detect_pending(host) \ -+ clear_bit(EVENT_CARD_DETECT, &host->pending_events) -+ -+ -+#ifdef CONFIG_DEBUG_FS -+#include <linux/debugfs.h> -+ -+#define DBG_REQ_BUF_SIZE (4096 - sizeof(unsigned int)) -+ -+struct req_dbg_data { -+ unsigned int nbytes; -+ char str[DBG_REQ_BUF_SIZE]; -+}; -+ -+static int req_dbg_open(struct inode *inode, struct file *file) -+{ -+ struct atmel_mci *host; -+ struct mmc_request *mrq; -+ struct mmc_command *cmd, *stop; -+ struct mmc_data *data; -+ struct req_dbg_data *priv; -+ char *str; -+ unsigned long n = 0; -+ -+ priv = kzalloc(DBG_REQ_BUF_SIZE, GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ str = priv->str; -+ -+ mutex_lock(&inode->i_mutex); -+ host = inode->i_private; -+ -+ spin_lock_irq(&host->mmc->lock); -+ mrq = host->mrq; -+ if (mrq) { -+ cmd = mrq->cmd; -+ data = mrq->data; -+ stop = mrq->stop; -+ n = snprintf(str, DBG_REQ_BUF_SIZE, -+ "CMD%u(0x%x) %x %x %x %x %x (err %u)\n", -+ cmd->opcode, cmd->arg, cmd->flags, -+ cmd->resp[0], cmd->resp[1], cmd->resp[2], -+ cmd->resp[3], cmd->error); -+ if (n < DBG_REQ_BUF_SIZE && data) -+ n += snprintf(str + n, DBG_REQ_BUF_SIZE - n, -+ "DATA %u * %u (%u) %x (err %u)\n", -+ data->blocks, data->blksz, -+ data->bytes_xfered, data->flags, -+ data->error); -+ if (n < DBG_REQ_BUF_SIZE && stop) -+ n += snprintf(str + n, DBG_REQ_BUF_SIZE - n, -+ "CMD%u(0x%x) %x %x %x %x %x (err %u)\n", -+ stop->opcode, stop->arg, stop->flags, -+ stop->resp[0], stop->resp[1], -+ stop->resp[2], stop->resp[3], -+ stop->error); -+ } -+ spin_unlock_irq(&host->mmc->lock); -+ mutex_unlock(&inode->i_mutex); -+ -+ priv->nbytes = min(n, DBG_REQ_BUF_SIZE); -+ file->private_data = priv; -+ -+ return 0; -+} -+ -+static ssize_t req_dbg_read(struct file *file, char __user *buf, -+ size_t nbytes, loff_t *ppos) -+{ -+ struct req_dbg_data *priv = file->private_data; -+ -+ return simple_read_from_buffer(buf, nbytes, ppos, -+ priv->str, priv->nbytes); -+} -+ -+static int req_dbg_release(struct inode *inode, struct file *file) -+{ -+ kfree(file->private_data); -+ return 0; -+} -+ -+static const struct file_operations req_dbg_fops = { -+ .owner = THIS_MODULE, -+ .open = req_dbg_open, -+ .llseek = no_llseek, -+ .read = req_dbg_read, -+ .release = req_dbg_release, -+}; -+ -+static int regs_dbg_open(struct inode *inode, struct file *file) -+{ -+ struct atmel_mci *host; -+ unsigned int i; -+ u32 *data; -+ int ret = -ENOMEM; -+ -+ mutex_lock(&inode->i_mutex); -+ host = inode->i_private; -+ data = kmalloc(inode->i_size, GFP_KERNEL); -+ if (!data) -+ goto out; -+ -+ spin_lock_irq(&host->mmc->lock); -+ for (i = 0; i < inode->i_size / 4; i++) -+ data[i] = __raw_readl(host->regs + i * 4); -+ spin_unlock_irq(&host->mmc->lock); -+ -+ file->private_data = data; -+ ret = 0; -+ -+out: -+ mutex_unlock(&inode->i_mutex); -+ -+ return ret; -+} -+ -+static ssize_t regs_dbg_read(struct file *file, char __user *buf, -+ size_t nbytes, loff_t *ppos) -+{ -+ struct inode *inode = file->f_dentry->d_inode; -+ int ret; -+ -+ mutex_lock(&inode->i_mutex); -+ ret = simple_read_from_buffer(buf, nbytes, ppos, -+ file->private_data, -+ file->f_dentry->d_inode->i_size); -+ mutex_unlock(&inode->i_mutex); -+ -+ return ret; -+} -+ -+static int regs_dbg_release(struct inode *inode, struct file *file) -+{ -+ kfree(file->private_data); -+ return 0; -+} -+ -+static const struct file_operations regs_dbg_fops = { -+ .owner = THIS_MODULE, -+ .open = regs_dbg_open, -+ .llseek = generic_file_llseek, -+ .read = regs_dbg_read, -+ .release = regs_dbg_release, -+}; -+ -+static void atmci_init_debugfs(struct atmel_mci *host) -+{ -+ struct mmc_host *mmc; -+ struct dentry *root, *regs; -+ struct resource *res; -+ -+ mmc = host->mmc; -+ root = debugfs_create_dir(mmc_hostname(mmc), NULL); -+ if (IS_ERR(root) || !root) -+ goto err_root; -+ host->debugfs_root = root; -+ -+ regs = debugfs_create_file("regs", 0400, root, host, ®s_dbg_fops); -+ if (!regs) -+ goto err_regs; -+ -+ res = platform_get_resource(host->pdev, IORESOURCE_MEM, 0); -+ regs->d_inode->i_size = res->end - res->start + 1; -+ host->debugfs_regs = regs; -+ -+ host->debugfs_req = debugfs_create_file("req", 0400, root, -+ host, &req_dbg_fops); -+ if (!host->debugfs_req) -+ goto err_req; -+ -+ host->debugfs_pending_events -+ = debugfs_create_u32("pending_events", 0400, root, -+ (u32 *)&host->pending_events); -+ if (!host->debugfs_pending_events) -+ goto err_pending_events; -+ -+ host->debugfs_completed_events -+ = debugfs_create_u32("completed_events", 0400, root, -+ (u32 *)&host->completed_events); -+ if (!host->debugfs_completed_events) -+ goto err_completed_events; -+ -+ return; -+ -+err_completed_events: -+ debugfs_remove(host->debugfs_pending_events); -+err_pending_events: -+ debugfs_remove(host->debugfs_req); -+err_req: -+ debugfs_remove(host->debugfs_regs); -+err_regs: -+ debugfs_remove(host->debugfs_root); -+err_root: -+ host->debugfs_root = NULL; -+ dev_err(&host->pdev->dev, -+ "failed to initialize debugfs for %s\n", -+ mmc_hostname(mmc)); -+} -+ -+static void atmci_cleanup_debugfs(struct atmel_mci *host) -+{ -+ if (host->debugfs_root) { -+ debugfs_remove(host->debugfs_completed_events); -+ debugfs_remove(host->debugfs_pending_events); -+ debugfs_remove(host->debugfs_req); -+ debugfs_remove(host->debugfs_regs); -+ debugfs_remove(host->debugfs_root); -+ host->debugfs_root = NULL; -+ } -+} -+#else -+static inline void atmci_init_debugfs(struct atmel_mci *host) -+{ -+ -+} -+ -+static inline void atmci_cleanup_debugfs(struct atmel_mci *host) -+{ -+ -+} -+#endif /* CONFIG_DEBUG_FS */ -+ -+static inline unsigned int ns_to_clocks(struct atmel_mci *host, -+ unsigned int ns) -+{ -+ return (ns * (host->bus_hz / 1000000) + 999) / 1000; -+} -+ -+static void atmci_set_timeout(struct atmel_mci *host, -+ struct mmc_data *data) -+{ -+ static unsigned dtomul_to_shift[] = { -+ 0, 4, 7, 8, 10, 12, 16, 20 -+ }; -+ unsigned timeout; -+ unsigned dtocyc, dtomul; -+ -+ timeout = ns_to_clocks(host, data->timeout_ns) + data->timeout_clks; -+ -+ for (dtomul = 0; dtomul < 8; dtomul++) { -+ unsigned shift = dtomul_to_shift[dtomul]; -+ dtocyc = (timeout + (1 << shift) - 1) >> shift; -+ if (dtocyc < 15) -+ break; -+ } -+ -+ if (dtomul >= 8) { -+ dtomul = 7; -+ dtocyc = 15; -+ } -+ -+ pr_debug("%s: setting timeout to %u cycles\n", -+ mmc_hostname(host->mmc), -+ dtocyc << dtomul_to_shift[dtomul]); -+ mci_writel(host, DTOR, (MCI_BF(DTOMUL, dtomul) -+ | MCI_BF(DTOCYC, dtocyc))); -+} -+ -+/* -+ * Return mask with interrupt flags to be handled for this command. -+ */ -+static u32 atmci_prepare_command(struct mmc_host *mmc, -+ struct mmc_command *cmd, -+ u32 *cmd_flags) -+{ -+ u32 cmdr; -+ u32 iflags; -+ -+ cmd->error = MMC_ERR_NONE; -+ -+ cmdr = 0; -+ BUG_ON(MCI_BFEXT(CMDNB, cmdr) != 0); -+ cmdr = MCI_BFINS(CMDNB, cmd->opcode, cmdr); -+ -+ if (cmd->flags & MMC_RSP_PRESENT) { -+ if (cmd->flags & MMC_RSP_136) -+ cmdr |= MCI_BF(RSPTYP, MCI_RSPTYP_136_BIT); -+ else -+ cmdr |= MCI_BF(RSPTYP, MCI_RSPTYP_48_BIT); -+ } -+ -+ /* -+ * This should really be MAXLAT_5 for CMD2 and ACMD41, but -+ * it's too difficult to determine whether this is an ACMD or -+ * not. Better make it 64. -+ */ -+ cmdr |= MCI_BIT(MAXLAT); -+ -+ if (mmc->ios.bus_mode == MMC_BUSMODE_OPENDRAIN) -+ cmdr |= MCI_BIT(OPDCMD); -+ -+ iflags = MCI_BIT(CMDRDY) | MCI_CMD_ERROR_FLAGS; -+ if (!(cmd->flags & MMC_RSP_CRC)) -+ iflags &= ~MCI_BIT(RCRCE); -+ -+ pr_debug("%s: cmd: op %02x arg %08x flags %08x, cmdflags %08lx\n", -+ mmc_hostname(mmc), cmd->opcode, cmd->arg, cmd->flags, -+ (unsigned long)cmdr); -+ -+ *cmd_flags = cmdr; -+ return iflags; -+} -+ -+static void atmci_start_command(struct atmel_mci *host, -+ struct mmc_command *cmd, -+ u32 cmd_flags) -+{ -+ WARN_ON(host->cmd); -+ host->cmd = cmd; -+ -+ mci_writel(host, ARGR, cmd->arg); -+ mci_writel(host, CMDR, cmd_flags); -+ -+ if (cmd->data) -+ dma_start_request(host->dma.req.req.dmac, -+ host->dma.req.req.channel); -+} -+ -+/* -+ * Returns a mask of flags to be set in the command register when the -+ * command to start the transfer is to be sent. -+ */ -+static u32 atmci_prepare_data(struct mmc_host *mmc, struct mmc_data *data) -+{ -+ struct atmel_mci *host = mmc_priv(mmc); -+ u32 cmd_flags; -+ -+ WARN_ON(host->data); -+ host->data = data; -+ -+ atmci_set_timeout(host, data); -+ mci_writel(host, BLKR, (MCI_BF(BCNT, data->blocks) -+ | MCI_BF(BLKLEN, data->blksz))); -+ host->dma.req.block_size = data->blksz; -+ host->dma.req.nr_blocks = data->blocks; -+ -+ cmd_flags = MCI_BF(TRCMD, MCI_TRCMD_START_TRANS); -+ if (data->flags & MMC_DATA_STREAM) -+ cmd_flags |= MCI_BF(TRTYP, MCI_TRTYP_STREAM); -+ else if (data->blocks > 1) -+ cmd_flags |= MCI_BF(TRTYP, MCI_TRTYP_MULTI_BLOCK); -+ else -+ cmd_flags |= MCI_BF(TRTYP, MCI_TRTYP_BLOCK); -+ -+ if (data->flags & MMC_DATA_READ) { -+ cmd_flags |= MCI_BIT(TRDIR); -+ host->dma.req.nr_sg -+ = dma_map_sg(&host->pdev->dev, data->sg, -+ data->sg_len, DMA_FROM_DEVICE); -+ host->dma.req.periph_id = host->dma.rx_periph_id; -+ host->dma.req.direction = DMA_DIR_PERIPH_TO_MEM; -+ host->dma.req.data_reg = host->mapbase + MCI_RDR; -+ } else { -+ host->dma.req.nr_sg -+ = dma_map_sg(&host->pdev->dev, data->sg, -+ data->sg_len, DMA_TO_DEVICE); -+ host->dma.req.periph_id = host->dma.tx_periph_id; -+ host->dma.req.direction = DMA_DIR_MEM_TO_PERIPH; -+ host->dma.req.data_reg = host->mapbase + MCI_TDR; -+ } -+ host->dma.req.sg = data->sg; -+ -+ dma_prepare_request_sg(host->dma.req.req.dmac, &host->dma.req); -+ -+ return cmd_flags; -+} -+ -+static void atmci_request(struct mmc_host *mmc, struct mmc_request *mrq) -+{ -+ struct atmel_mci *host = mmc_priv(mmc); -+ struct mmc_data *data = mrq->data; -+ u32 iflags; -+ u32 cmdflags = 0; -+ -+ iflags = mci_readl(host, IMR); -+ if (iflags) -+ printk("WARNING: IMR=0x%08x\n", mci_readl(host, IMR)); -+ -+ WARN_ON(host->mrq != NULL); -+ host->mrq = mrq; -+ host->pending_events = 0; -+ host->completed_events = 0; -+ -+ iflags = atmci_prepare_command(mmc, mrq->cmd, &cmdflags); -+ -+ if (mrq->stop) { -+ BUG_ON(!data); -+ -+ host->stop_iflags = atmci_prepare_command(mmc, mrq->stop, -+ &host->stop_cmdr); -+ host->stop_cmdr |= MCI_BF(TRCMD, MCI_TRCMD_STOP_TRANS); -+ if (!(data->flags & MMC_DATA_WRITE)) -+ host->stop_cmdr |= MCI_BIT(TRDIR); -+ if (data->flags & MMC_DATA_STREAM) -+ host->stop_cmdr |= MCI_BF(TRTYP, MCI_TRTYP_STREAM); -+ else -+ host->stop_cmdr |= MCI_BF(TRTYP, MCI_TRTYP_MULTI_BLOCK); -+ } -+ if (data) { -+ cmdflags |= atmci_prepare_data(mmc, data); -+ iflags |= MCI_DATA_ERROR_FLAGS; -+ } -+ -+ atmci_start_command(host, mrq->cmd, cmdflags); -+ mci_writel(host, IER, iflags); -+} -+ -+static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) -+{ -+ struct atmel_mci *host = mmc_priv(mmc); -+ -+ if (ios->clock) { -+ u32 clkdiv; -+ -+ clkdiv = host->bus_hz / (2 * ios->clock) - 1; -+ if (clkdiv > 255) -+ clkdiv = 255; -+ mci_writel(host, MR, (clkdiv -+ | MCI_BIT(WRPROOF) -+ | MCI_BIT(RDPROOF))); -+ } -+ -+ switch (ios->bus_width) { -+ case MMC_BUS_WIDTH_1: -+ mci_writel(host, SDCR, 0); -+ break; -+ case MMC_BUS_WIDTH_4: -+ mci_writel(host, SDCR, MCI_BIT(SDCBUS)); -+ break; -+ } -+ -+ switch (ios->power_mode) { -+ case MMC_POWER_OFF: -+ mci_writel(host, CR, MCI_BIT(MCIDIS)); -+ break; -+ case MMC_POWER_UP: -+ mci_writel(host, CR, MCI_BIT(SWRST)); -+ break; -+ case MMC_POWER_ON: -+ mci_writel(host, CR, MCI_BIT(MCIEN)); -+ break; -+ } -+} -+ -+static int atmci_get_ro(struct mmc_host *mmc) -+{ -+ int read_only = 0; -+ struct atmel_mci *host = mmc_priv(mmc); -+ -+ if (host->wp_pin >= 0) { -+ read_only = gpio_get_value(host->wp_pin); -+ pr_debug("%s: card is %s\n", mmc_hostname(mmc), -+ read_only ? "read-only" : "read-write"); -+ } else { -+ pr_debug("%s: no pin for checking read-only switch." -+ " Assuming write-enable.\n", mmc_hostname(mmc)); -+ } -+ -+ return read_only; -+} -+ -+static struct mmc_host_ops atmci_ops = { -+ .request = atmci_request, -+ .set_ios = atmci_set_ios, -+ .get_ro = atmci_get_ro, -+}; -+ -+static void atmci_request_end(struct mmc_host *mmc, struct mmc_request *mrq) -+{ -+ struct atmel_mci *host = mmc_priv(mmc); -+ -+ WARN_ON(host->cmd || host->data); -+ host->mrq = NULL; -+ -+ mmc_request_done(mmc, mrq); -+} -+ -+static void send_stop_cmd(struct mmc_host *mmc, struct mmc_data *data, -+ u32 flags) -+{ -+ struct atmel_mci *host = mmc_priv(mmc); -+ -+ atmci_start_command(host, data->stop, host->stop_cmdr | flags); -+ mci_writel(host, IER, host->stop_iflags); -+} -+ -+static void atmci_data_complete(struct atmel_mci *host, struct mmc_data *data) -+{ -+ host->data = NULL; -+ dma_unmap_sg(&host->pdev->dev, data->sg, host->dma.req.nr_sg, -+ ((data->flags & MMC_DATA_WRITE) -+ ? DMA_TO_DEVICE : DMA_FROM_DEVICE)); -+ -+ /* -+ * Data might complete before command for very short transfers -+ * (like READ_SCR) -+ */ -+ if (mci_cmd_is_complete(host) -+ && (!data->stop || mci_stop_is_complete(host))) -+ atmci_request_end(host->mmc, data->mrq); -+} -+ -+static void atmci_command_error(struct mmc_host *mmc, -+ struct mmc_command *cmd, -+ u32 status) -+{ -+ pr_debug("%s: command error: status=0x%08x\n", -+ mmc_hostname(mmc), status); -+ -+ if (status & MCI_BIT(RTOE)) -+ cmd->error = MMC_ERR_TIMEOUT; -+ else if (status & MCI_BIT(RCRCE)) -+ cmd->error = MMC_ERR_BADCRC; -+ else -+ cmd->error = MMC_ERR_FAILED; -+} -+ -+static void atmci_tasklet_func(unsigned long priv) -+{ -+ struct mmc_host *mmc = (struct mmc_host *)priv; -+ struct atmel_mci *host = mmc_priv(mmc); -+ struct mmc_request *mrq = host->mrq; -+ struct mmc_data *data = host->data; -+ -+ pr_debug("atmci_tasklet: pending/completed/mask %lx/%lx/%x\n", -+ host->pending_events, host->completed_events, -+ mci_readl(host, IMR)); -+ -+ if (mci_clear_cmd_error_is_pending(host)) { -+ struct mmc_command *cmd; -+ -+ mci_set_cmd_error_complete(host); -+ mci_clear_cmd_pending(host); -+ cmd = host->mrq->cmd; -+ -+ if (cmd->data) { -+ dma_stop_request(host->dma.req.req.dmac, -+ host->dma.req.req.channel); -+ host->data = NULL; -+ } -+ -+ atmci_command_error(mmc, cmd, host->error_status); -+ atmci_request_end(mmc, cmd->mrq); -+ } -+ if (mci_clear_stop_error_is_pending(host)) { -+ mci_set_stop_error_complete(host); -+ mci_clear_stop_pending(host); -+ atmci_command_error(mmc, host->mrq->stop, -+ host->error_status); -+ if (!host->data) -+ atmci_request_end(mmc, host->mrq); -+ } -+ if (mci_clear_cmd_is_pending(host)) { -+ mci_set_cmd_complete(host); -+ if (!mrq->data || mci_data_is_complete(host) -+ || mci_data_error_is_complete(host)) -+ atmci_request_end(mmc, mrq); -+ } -+ if (mci_clear_stop_is_pending(host)) { -+ mci_set_stop_complete(host); -+ if (mci_data_is_complete(host) -+ || mci_data_error_is_complete(host)) -+ atmci_request_end(mmc, mrq); -+ } -+ if (mci_clear_dma_error_is_pending(host)) { -+ mci_set_dma_error_complete(host); -+ mci_clear_data_pending(host); -+ -+ /* DMA controller got bus error => invalid address */ -+ data->error = MMC_ERR_INVALID; -+ -+ printk(KERN_DEBUG "%s: dma error after %u bytes xfered\n", -+ mmc_hostname(mmc), host->data->bytes_xfered); -+ -+ if (data->stop -+ && !mci_set_stop_sent_is_completed(host)) -+ /* TODO: Check if card is still present */ -+ send_stop_cmd(host->mmc, data, 0); -+ -+ atmci_data_complete(host, data); -+ } -+ if (mci_clear_data_error_is_pending(host)) { -+ u32 status = host->error_status; -+ -+ mci_set_data_error_complete(host); -+ mci_clear_data_pending(host); -+ -+ dma_stop_request(host->dma.req.req.dmac, -+ host->dma.req.req.channel); -+ -+ printk(KERN_DEBUG "%s: data error: status=0x%08x\n", -+ mmc_hostname(host->mmc), status); -+ -+ if (status & MCI_BIT(DCRCE)) { -+ printk(KERN_DEBUG "%s: Data CRC error\n", -+ mmc_hostname(host->mmc)); -+ data->error = MMC_ERR_BADCRC; -+ } else if (status & MCI_BIT(DTOE)) { -+ printk(KERN_DEBUG "%s: Data Timeout error\n", -+ mmc_hostname(host->mmc)); -+ data->error = MMC_ERR_TIMEOUT; -+ } else { -+ printk(KERN_DEBUG "%s: Data FIFO error\n", -+ mmc_hostname(host->mmc)); -+ data->error = MMC_ERR_FIFO; -+ } -+ printk(KERN_DEBUG "%s: Bytes xfered: %u\n", -+ mmc_hostname(host->mmc), data->bytes_xfered); -+ -+ if (data->stop -+ && !mci_set_stop_sent_is_completed(host)) -+ /* TODO: Check if card is still present */ -+ send_stop_cmd(host->mmc, data, 0); -+ -+ atmci_data_complete(host, data); -+ } -+ if (mci_clear_data_is_pending(host)) { -+ mci_set_data_complete(host); -+ data->bytes_xfered = data->blocks * data->blksz; -+ atmci_data_complete(host, data); -+ } -+ if (mci_clear_card_detect_is_pending(host)) { -+ /* Reset controller if card is gone */ -+ if (!host->present) { -+ mci_writel(host, CR, MCI_BIT(SWRST)); -+ mci_writel(host, IDR, ~0UL); -+ mci_writel(host, CR, MCI_BIT(MCIEN)); -+ } -+ -+ /* Clean up queue if present */ -+ if (mrq) { -+ if (!mci_cmd_is_complete(host) -+ && !mci_cmd_error_is_complete(host)) { -+ mrq->cmd->error = MMC_ERR_TIMEOUT; -+ } -+ if (mrq->data && !mci_data_is_complete(host) -+ && !mci_data_error_is_complete(host)) { -+ dma_stop_request(host->dma.req.req.dmac, -+ host->dma.req.req.channel); -+ host->data->error = MMC_ERR_TIMEOUT; -+ atmci_data_complete(host, data); -+ } -+ if (mrq->stop && !mci_stop_is_complete(host) -+ && !mci_stop_error_is_complete(host)) { -+ mrq->stop->error = MMC_ERR_TIMEOUT; -+ } -+ -+ host->cmd = NULL; -+ atmci_request_end(mmc, mrq); -+ } -+ mmc_detect_change(host->mmc, msecs_to_jiffies(100)); -+ } -+} -+ -+static void atmci_cmd_interrupt(struct mmc_host *mmc, u32 status) -+{ -+ struct atmel_mci *host = mmc_priv(mmc); -+ struct mmc_command *cmd = host->cmd; -+ -+ /* -+ * Read the response now so that we're free to send a new -+ * command immediately. -+ */ -+ cmd->resp[0] = mci_readl(host, RSPR); -+ cmd->resp[1] = mci_readl(host, RSPR); -+ cmd->resp[2] = mci_readl(host, RSPR); -+ cmd->resp[3] = mci_readl(host, RSPR); -+ -+ mci_writel(host, IDR, MCI_BIT(CMDRDY) | MCI_CMD_ERROR_FLAGS); -+ host->cmd = NULL; -+ -+ if (mci_stop_sent_is_complete(host)) -+ mci_set_stop_pending(host); -+ else -+ mci_set_cmd_pending(host); -+ -+ tasklet_schedule(&host->tasklet); -+} -+ -+static void atmci_xfer_complete(struct dma_request *_req) -+{ -+ struct dma_request_sg *req = to_dma_request_sg(_req); -+ struct atmel_mci_dma *dma; -+ struct atmel_mci *host; -+ struct mmc_data *data; -+ -+ dma = container_of(req, struct atmel_mci_dma, req); -+ host = container_of(dma, struct atmel_mci, dma); -+ data = host->data; -+ -+ if (data->stop && !mci_set_stop_sent_is_completed(host)) -+ send_stop_cmd(host->mmc, data, 0); -+ -+ if (data->flags & MMC_DATA_READ) { -+ mci_writel(host, IDR, MCI_DATA_ERROR_FLAGS); -+ mci_set_data_pending(host); -+ tasklet_schedule(&host->tasklet); -+ } else { -+ /* -+ * For the WRITE case, wait for NOTBUSY. This function -+ * is called when everything has been written to the -+ * controller, not when the card is done programming. -+ */ -+ mci_writel(host, IER, MCI_BIT(NOTBUSY)); -+ } -+} -+ -+static void atmci_dma_error(struct dma_request *_req) -+{ -+ struct dma_request_sg *req = to_dma_request_sg(_req); -+ struct atmel_mci_dma *dma; -+ struct atmel_mci *host; -+ -+ dma = container_of(req, struct atmel_mci_dma, req); -+ host = container_of(dma, struct atmel_mci, dma); -+ -+ mci_writel(host, IDR, (MCI_BIT(NOTBUSY) -+ | MCI_DATA_ERROR_FLAGS)); -+ -+ mci_set_dma_error_pending(host); -+ tasklet_schedule(&host->tasklet); -+} -+ -+static irqreturn_t atmci_interrupt(int irq, void *dev_id) -+{ -+ struct mmc_host *mmc = dev_id; -+ struct atmel_mci *host = mmc_priv(mmc); -+ u32 status, mask, pending; -+ -+ spin_lock(&mmc->lock); -+ -+ status = mci_readl(host, SR); -+ mask = mci_readl(host, IMR); -+ pending = status & mask; -+ -+ do { -+ if (pending & MCI_CMD_ERROR_FLAGS) { -+ mci_writel(host, IDR, (MCI_BIT(CMDRDY) -+ | MCI_BIT(NOTBUSY) -+ | MCI_CMD_ERROR_FLAGS -+ | MCI_DATA_ERROR_FLAGS)); -+ host->error_status = status; -+ host->cmd = NULL; -+ if (mci_stop_sent_is_complete(host)) -+ mci_set_stop_error_pending(host); -+ else -+ mci_set_cmd_error_pending(host); -+ tasklet_schedule(&host->tasklet); -+ break; -+ } -+ if (pending & MCI_DATA_ERROR_FLAGS) { -+ mci_writel(host, IDR, (MCI_BIT(NOTBUSY) -+ | MCI_DATA_ERROR_FLAGS)); -+ host->error_status = status; -+ mci_set_data_error_pending(host); -+ tasklet_schedule(&host->tasklet); -+ break; -+ } -+ if (pending & MCI_BIT(CMDRDY)) -+ atmci_cmd_interrupt(mmc, status); -+ if (pending & MCI_BIT(NOTBUSY)) { -+ mci_writel(host, IDR, (MCI_BIT(NOTBUSY) -+ | MCI_DATA_ERROR_FLAGS)); -+ mci_set_data_pending(host); -+ tasklet_schedule(&host->tasklet); -+ } -+ -+ status = mci_readl(host, SR); -+ mask = mci_readl(host, IMR); -+ pending = status & mask; -+ } while (pending); -+ -+ spin_unlock(&mmc->lock); -+ -+ return IRQ_HANDLED; -+} -+ -+static irqreturn_t atmci_detect_change(int irq, void *dev_id) -+{ -+ struct mmc_host *mmc = dev_id; -+ struct atmel_mci *host = mmc_priv(mmc); -+ -+ int present = !gpio_get_value(irq_to_gpio(irq)); -+ -+ if (present != host->present) { -+ pr_debug("%s: card %s\n", mmc_hostname(host->mmc), -+ present ? "inserted" : "removed"); -+ host->present = present; -+ mci_set_card_detect_pending(host); -+ tasklet_schedule(&host->tasklet); -+ } -+ return IRQ_HANDLED; -+} -+ -+static int __devinit atmci_probe(struct platform_device *pdev) -+{ -+ struct mci_platform_data *board; -+ struct atmel_mci *host; -+ struct mmc_host *mmc; -+ struct resource *regs; -+ int irq; -+ int ret; -+ -+ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!regs) -+ return -ENXIO; -+ irq = platform_get_irq(pdev, 0); -+ if (irq < 0) -+ return irq; -+ -+ board = pdev->dev.platform_data; -+ -+ mmc = mmc_alloc_host(sizeof(struct atmel_mci), &pdev->dev); -+ if (!mmc) -+ return -ENOMEM; -+ -+ host = mmc_priv(mmc); -+ host->pdev = pdev; -+ host->mmc = mmc; -+ if (board) { -+ host->detect_pin = board->detect_pin; -+ host->wp_pin = board->wp_pin; -+ } else { -+ host->detect_pin = -1; -+ host->detect_pin = -1; -+ } -+ -+ host->mck = clk_get(&pdev->dev, "mci_clk"); -+ if (IS_ERR(host->mck)) { -+ ret = PTR_ERR(host->mck); -+ goto out_free_host; -+ } -+ clk_enable(host->mck); -+ -+ ret = -ENOMEM; -+ host->regs = ioremap(regs->start, regs->end - regs->start + 1); -+ if (!host->regs) -+ goto out_disable_clk; -+ -+ host->bus_hz = clk_get_rate(host->mck); -+ host->mapbase = regs->start; -+ -+ mmc->ops = &atmci_ops; -+ mmc->f_min = (host->bus_hz + 511) / 512; -+ mmc->f_max = min((unsigned int)(host->bus_hz / 2), fmax); -+ mmc->ocr_avail = 0x00100000; -+ mmc->caps |= MMC_CAP_4_BIT_DATA; -+ -+ tasklet_init(&host->tasklet, atmci_tasklet_func, (unsigned long)mmc); -+ -+ ret = request_irq(irq, atmci_interrupt, 0, "mmci", mmc); -+ if (ret) -+ goto out_unmap; -+ -+ /* Assume card is present if we don't have a detect pin */ -+ host->present = 1; -+ if (host->detect_pin >= 0) { -+ if (gpio_request(host->detect_pin, "mmc_detect")) { -+ printk(KERN_WARNING "%s: no detect pin available\n", -+ mmc_hostname(host->mmc)); -+ host->detect_pin = -1; -+ } else { -+ host->present = !gpio_get_value(host->detect_pin); -+ } -+ } -+ if (host->wp_pin >= 0) { -+ if (gpio_request(host->wp_pin, "mmc_wp")) { -+ printk(KERN_WARNING "%s: no WP pin available\n", -+ mmc_hostname(host->mmc)); -+ host->wp_pin = -1; -+ } -+ } -+ -+ /* TODO: Get this information from platform data */ -+ ret = -ENOMEM; -+ host->dma.req.req.dmac = find_dma_controller(0); -+ if (!host->dma.req.req.dmac) { -+ printk(KERN_ERR -+ "mmci: No DMA controller available, aborting\n"); -+ goto out_free_irq; -+ } -+ ret = dma_alloc_channel(host->dma.req.req.dmac); -+ if (ret < 0) { -+ printk(KERN_ERR -+ "mmci: Unable to allocate DMA channel, aborting\n"); -+ goto out_free_irq; -+ } -+ host->dma.req.req.channel = ret; -+ host->dma.req.width = DMA_WIDTH_32BIT; -+ host->dma.req.req.xfer_complete = atmci_xfer_complete; -+ host->dma.req.req.block_complete = NULL; // atmci_block_complete; -+ host->dma.req.req.error = atmci_dma_error; -+ host->dma.rx_periph_id = 0; -+ host->dma.tx_periph_id = 1; -+ -+ mci_writel(host, CR, MCI_BIT(SWRST)); -+ mci_writel(host, IDR, ~0UL); -+ mci_writel(host, CR, MCI_BIT(MCIEN)); -+ -+ platform_set_drvdata(pdev, host); -+ -+ mmc_add_host(mmc); -+ -+ if (host->detect_pin >= 0) { -+ ret = request_irq(gpio_to_irq(host->detect_pin), -+ atmci_detect_change, -+ IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, -+ DRIVER_NAME, mmc); -+ if (ret) { -+ printk(KERN_ERR -+ "%s: could not request IRQ %d for detect pin\n", -+ mmc_hostname(mmc), -+ gpio_to_irq(host->detect_pin)); -+ gpio_free(host->detect_pin); -+ host->detect_pin = -1; -+ } -+ } -+ -+ printk(KERN_INFO "%s: Atmel MCI controller at 0x%08lx irq %d\n", -+ mmc_hostname(mmc), host->mapbase, irq); -+ -+ atmci_init_debugfs(host); -+ -+ return 0; -+ -+out_free_irq: -+ if (host->detect_pin >= 0) -+ gpio_free(host->detect_pin); -+ if (host->wp_pin >= 0) -+ gpio_free(host->wp_pin); -+ free_irq(irq, mmc); -+out_unmap: -+ iounmap(host->regs); -+out_disable_clk: -+ clk_disable(host->mck); -+ clk_put(host->mck); -+out_free_host: -+ mmc_free_host(mmc); -+ return ret; -+} -+ -+static int __devexit atmci_remove(struct platform_device *pdev) -+{ -+ struct atmel_mci *host = platform_get_drvdata(pdev); -+ -+ platform_set_drvdata(pdev, NULL); -+ -+ if (host) { -+ atmci_cleanup_debugfs(host); -+ -+ if (host->detect_pin >= 0) { -+ free_irq(gpio_to_irq(host->detect_pin), host->mmc); -+ cancel_delayed_work(&host->mmc->detect); -+ gpio_free(host->detect_pin); -+ } -+ -+ mmc_remove_host(host->mmc); -+ -+ mci_writel(host, IDR, ~0UL); -+ mci_writel(host, CR, MCI_BIT(MCIDIS)); -+ mci_readl(host, SR); -+ -+ dma_release_channel(host->dma.req.req.dmac, -+ host->dma.req.req.channel); -+ -+ if (host->wp_pin >= 0) -+ gpio_free(host->wp_pin); -+ -+ free_irq(platform_get_irq(pdev, 0), host->mmc); -+ iounmap(host->regs); -+ -+ clk_disable(host->mck); -+ clk_put(host->mck); -+ -+ mmc_free_host(host->mmc); -+ } -+ return 0; -+} -+ -+static struct platform_driver atmci_driver = { -+ .probe = atmci_probe, -+ .remove = __devexit_p(atmci_remove), -+ .driver = { -+ .name = DRIVER_NAME, -+ }, -+}; -+ -+static int __init atmci_init(void) -+{ -+ return platform_driver_register(&atmci_driver); -+} -+ -+static void __exit atmci_exit(void) -+{ -+ platform_driver_unregister(&atmci_driver); -+} -+ -+module_init(atmci_init); -+module_exit(atmci_exit); -+ -+MODULE_DESCRIPTION("Atmel Multimedia Card Interface driver"); -+MODULE_LICENSE("GPL"); -diff -urN linux-2.6.20.4-0rig/drivers/mmc/atmel-mci.h linux-2.6.20.4-atmel/drivers/mmc/atmel-mci.h ---- linux-2.6.20.4-0rig/drivers/mmc/atmel-mci.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/mmc/atmel-mci.h 2007-03-24 16:42:29.000000000 +0100 -@@ -0,0 +1,192 @@ -+/* -+ * Atmel MultiMedia Card Interface driver -+ * -+ * Copyright (C) 2004-2006 Atmel Corporation -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+#ifndef __DRIVERS_MMC_ATMEL_MCI_H__ -+#define __DRIVERS_MMC_ATMEL_MCI_H__ -+ -+/* MCI register offsets */ -+#define MCI_CR 0x0000 -+#define MCI_MR 0x0004 -+#define MCI_DTOR 0x0008 -+#define MCI_SDCR 0x000c -+#define MCI_ARGR 0x0010 -+#define MCI_CMDR 0x0014 -+#define MCI_BLKR 0x0018 -+#define MCI_RSPR 0x0020 -+#define MCI_RSPR1 0x0024 -+#define MCI_RSPR2 0x0028 -+#define MCI_RSPR3 0x002c -+#define MCI_RDR 0x0030 -+#define MCI_TDR 0x0034 -+#define MCI_SR 0x0040 -+#define MCI_IER 0x0044 -+#define MCI_IDR 0x0048 -+#define MCI_IMR 0x004c -+ -+/* Bitfields in CR */ -+#define MCI_MCIEN_OFFSET 0 -+#define MCI_MCIEN_SIZE 1 -+#define MCI_MCIDIS_OFFSET 1 -+#define MCI_MCIDIS_SIZE 1 -+#define MCI_PWSEN_OFFSET 2 -+#define MCI_PWSEN_SIZE 1 -+#define MCI_PWSDIS_OFFSET 3 -+#define MCI_PWSDIS_SIZE 1 -+#define MCI_SWRST_OFFSET 7 -+#define MCI_SWRST_SIZE 1 -+ -+/* Bitfields in MR */ -+#define MCI_CLKDIV_OFFSET 0 -+#define MCI_CLKDIV_SIZE 8 -+#define MCI_PWSDIV_OFFSET 8 -+#define MCI_PWSDIV_SIZE 3 -+#define MCI_RDPROOF_OFFSET 11 -+#define MCI_RDPROOF_SIZE 1 -+#define MCI_WRPROOF_OFFSET 12 -+#define MCI_WRPROOF_SIZE 1 -+#define MCI_DMAPADV_OFFSET 14 -+#define MCI_DMAPADV_SIZE 1 -+#define MCI_BLKLEN_OFFSET 16 -+#define MCI_BLKLEN_SIZE 16 -+ -+/* Bitfields in DTOR */ -+#define MCI_DTOCYC_OFFSET 0 -+#define MCI_DTOCYC_SIZE 4 -+#define MCI_DTOMUL_OFFSET 4 -+#define MCI_DTOMUL_SIZE 3 -+ -+/* Bitfields in SDCR */ -+#define MCI_SDCSEL_OFFSET 0 -+#define MCI_SDCSEL_SIZE 4 -+#define MCI_SDCBUS_OFFSET 7 -+#define MCI_SDCBUS_SIZE 1 -+ -+/* Bitfields in ARGR */ -+#define MCI_ARG_OFFSET 0 -+#define MCI_ARG_SIZE 32 -+ -+/* Bitfields in CMDR */ -+#define MCI_CMDNB_OFFSET 0 -+#define MCI_CMDNB_SIZE 6 -+#define MCI_RSPTYP_OFFSET 6 -+#define MCI_RSPTYP_SIZE 2 -+#define MCI_SPCMD_OFFSET 8 -+#define MCI_SPCMD_SIZE 3 -+#define MCI_OPDCMD_OFFSET 11 -+#define MCI_OPDCMD_SIZE 1 -+#define MCI_MAXLAT_OFFSET 12 -+#define MCI_MAXLAT_SIZE 1 -+#define MCI_TRCMD_OFFSET 16 -+#define MCI_TRCMD_SIZE 2 -+#define MCI_TRDIR_OFFSET 18 -+#define MCI_TRDIR_SIZE 1 -+#define MCI_TRTYP_OFFSET 19 -+#define MCI_TRTYP_SIZE 2 -+ -+/* Bitfields in BLKR */ -+#define MCI_BCNT_OFFSET 0 -+#define MCI_BCNT_SIZE 16 -+ -+/* Bitfields in RSPRn */ -+#define MCI_RSP_OFFSET 0 -+#define MCI_RSP_SIZE 32 -+ -+/* Bitfields in SR/IER/IDR/IMR */ -+#define MCI_CMDRDY_OFFSET 0 -+#define MCI_CMDRDY_SIZE 1 -+#define MCI_RXRDY_OFFSET 1 -+#define MCI_RXRDY_SIZE 1 -+#define MCI_TXRDY_OFFSET 2 -+#define MCI_TXRDY_SIZE 1 -+#define MCI_BLKE_OFFSET 3 -+#define MCI_BLKE_SIZE 1 -+#define MCI_DTIP_OFFSET 4 -+#define MCI_DTIP_SIZE 1 -+#define MCI_NOTBUSY_OFFSET 5 -+#define MCI_NOTBUSY_SIZE 1 -+#define MCI_ENDRX_OFFSET 6 -+#define MCI_ENDRX_SIZE 1 -+#define MCI_ENDTX_OFFSET 7 -+#define MCI_ENDTX_SIZE 1 -+#define MCI_RXBUFF_OFFSET 14 -+#define MCI_RXBUFF_SIZE 1 -+#define MCI_TXBUFE_OFFSET 15 -+#define MCI_TXBUFE_SIZE 1 -+#define MCI_RINDE_OFFSET 16 -+#define MCI_RINDE_SIZE 1 -+#define MCI_RDIRE_OFFSET 17 -+#define MCI_RDIRE_SIZE 1 -+#define MCI_RCRCE_OFFSET 18 -+#define MCI_RCRCE_SIZE 1 -+#define MCI_RENDE_OFFSET 19 -+#define MCI_RENDE_SIZE 1 -+#define MCI_RTOE_OFFSET 20 -+#define MCI_RTOE_SIZE 1 -+#define MCI_DCRCE_OFFSET 21 -+#define MCI_DCRCE_SIZE 1 -+#define MCI_DTOE_OFFSET 22 -+#define MCI_DTOE_SIZE 1 -+#define MCI_OVRE_OFFSET 30 -+#define MCI_OVRE_SIZE 1 -+#define MCI_UNRE_OFFSET 31 -+#define MCI_UNRE_SIZE 1 -+ -+/* Constants for DTOMUL */ -+#define MCI_DTOMUL_1_CYCLE 0 -+#define MCI_DTOMUL_16_CYCLES 1 -+#define MCI_DTOMUL_128_CYCLES 2 -+#define MCI_DTOMUL_256_CYCLES 3 -+#define MCI_DTOMUL_1024_CYCLES 4 -+#define MCI_DTOMUL_4096_CYCLES 5 -+#define MCI_DTOMUL_65536_CYCLES 6 -+#define MCI_DTOMUL_1048576_CYCLES 7 -+ -+/* Constants for RSPTYP */ -+#define MCI_RSPTYP_NO_RESP 0 -+#define MCI_RSPTYP_48_BIT 1 -+#define MCI_RSPTYP_136_BIT 2 -+ -+/* Constants for SPCMD */ -+#define MCI_SPCMD_NO_SPEC_CMD 0 -+#define MCI_SPCMD_INIT_CMD 1 -+#define MCI_SPCMD_SYNC_CMD 2 -+#define MCI_SPCMD_INT_CMD 4 -+#define MCI_SPCMD_INT_RESP 5 -+ -+/* Constants for TRCMD */ -+#define MCI_TRCMD_NO_TRANS 0 -+#define MCI_TRCMD_START_TRANS 1 -+#define MCI_TRCMD_STOP_TRANS 2 -+ -+/* Constants for TRTYP */ -+#define MCI_TRTYP_BLOCK 0 -+#define MCI_TRTYP_MULTI_BLOCK 1 -+#define MCI_TRTYP_STREAM 2 -+ -+/* Bit manipulation macros */ -+#define MCI_BIT(name) \ -+ (1 << MCI_##name##_OFFSET) -+#define MCI_BF(name,value) \ -+ (((value) & ((1 << MCI_##name##_SIZE) - 1)) \ -+ << MCI_##name##_OFFSET) -+#define MCI_BFEXT(name,value) \ -+ (((value) >> MCI_##name##_OFFSET) \ -+ & ((1 << MCI_##name##_SIZE) - 1)) -+#define MCI_BFINS(name,value,old) \ -+ (((old) & ~(((1 << MCI_##name##_SIZE) - 1) \ -+ << MCI_##name##_OFFSET)) \ -+ | MCI_BF(name,value)) -+ -+/* Register access macros */ -+#define mci_readl(port,reg) \ -+ __raw_readl((port)->regs + MCI_##reg) -+#define mci_writel(port,reg,value) \ -+ __raw_writel((value), (port)->regs + MCI_##reg) -+ -+#endif /* __DRIVERS_MMC_ATMEL_MCI_H__ */ -diff -urN linux-2.6.20.4-0rig/drivers/mmc/Kconfig linux-2.6.20.4-atmel/drivers/mmc/Kconfig ---- linux-2.6.20.4-0rig/drivers/mmc/Kconfig 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/mmc/Kconfig 2007-03-24 16:42:29.000000000 +0100 -@@ -71,6 +71,16 @@ - - If unsure, say N. - -+config MMC_ATMELMCI -+ tristate "Atmel Multimedia Card Interface support" -+ depends on AVR32 && MMC -+ help -+ This selects the Atmel Multimedia Card Interface. If you have -+ a AT91 (ARM) or AT32 (AVR32) platform with a Multimedia Card -+ slot, say Y or M here. -+ -+ If unsure, say N. -+ - config MMC_WBSD - tristate "Winbond W83L51xD SD/MMC Card Interface support" - depends on MMC && ISA_DMA_API -diff -urN linux-2.6.20.4-0rig/drivers/mmc/Makefile linux-2.6.20.4-atmel/drivers/mmc/Makefile ---- linux-2.6.20.4-0rig/drivers/mmc/Makefile 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/mmc/Makefile 2007-03-24 16:42:29.000000000 +0100 -@@ -23,6 +23,7 @@ - obj-$(CONFIG_MMC_AU1X) += au1xmmc.o - obj-$(CONFIG_MMC_OMAP) += omap.o - obj-$(CONFIG_MMC_AT91) += at91_mci.o -+obj-$(CONFIG_MMC_ATMELMCI) += atmel-mci.o - obj-$(CONFIG_MMC_TIFM_SD) += tifm_sd.o - - mmc_core-y := mmc.o mmc_sysfs.o -diff -urN linux-2.6.20.4-0rig/drivers/mtd/chips/cfi_cmdset_0001.c linux-2.6.20.4-atmel/drivers/mtd/chips/cfi_cmdset_0001.c ---- linux-2.6.20.4-0rig/drivers/mtd/chips/cfi_cmdset_0001.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/mtd/chips/cfi_cmdset_0001.c 2007-03-24 16:42:29.000000000 +0100 -@@ -47,6 +47,7 @@ - #define I82802AC 0x00ac - #define MANUFACTURER_ST 0x0020 - #define M50LPW080 0x002F -+#define AT49BV640D 0x02de - - static int cfi_intelext_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); - static int cfi_intelext_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); -@@ -153,6 +154,47 @@ - } - #endif - -+/* Atmel chips don't use the same PRI format as Intel chips */ -+static void fixup_convert_atmel_pri(struct mtd_info *mtd, void *param) -+{ -+ struct map_info *map = mtd->priv; -+ struct cfi_private *cfi = map->fldrv_priv; -+ struct cfi_pri_intelext *extp = cfi->cmdset_priv; -+ struct cfi_pri_atmel atmel_pri; -+ uint32_t features = 0; -+ -+ /* Reverse byteswapping */ -+ extp->FeatureSupport = cpu_to_le32(extp->FeatureSupport); -+ extp->BlkStatusRegMask = cpu_to_le16(extp->BlkStatusRegMask); -+ extp->ProtRegAddr = cpu_to_le16(extp->ProtRegAddr); -+ -+ memcpy(&atmel_pri, extp, sizeof(atmel_pri)); -+ memset((char *)extp + 5, 0, sizeof(*extp) - 5); -+ -+ printk(KERN_ERR "atmel Features: %02x\n", atmel_pri.Features); -+ -+ if (atmel_pri.Features & 0x01) /* chip erase supported */ -+ features |= (1<<0); -+ if (atmel_pri.Features & 0x02) /* erase suspend supported */ -+ features |= (1<<1); -+ if (atmel_pri.Features & 0x04) /* program suspend supported */ -+ features |= (1<<2); -+ if (atmel_pri.Features & 0x08) /* simultaneous operations supported */ -+ features |= (1<<9); -+ if (atmel_pri.Features & 0x20) /* page mode read supported */ -+ features |= (1<<7); -+ if (atmel_pri.Features & 0x40) /* queued erase supported */ -+ features |= (1<<4); -+ if (atmel_pri.Features & 0x80) /* Protection bits supported */ -+ features |= (1<<6); -+ -+ extp->FeatureSupport = features; -+ -+ /* burst write mode not supported */ -+ cfi->cfiq->BufWriteTimeoutTyp = 0; -+ cfi->cfiq->BufWriteTimeoutMax = 0; -+} -+ - #ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE - /* Some Intel Strata Flash prior to FPO revision C has bugs in this area */ - static void fixup_intel_strataflash(struct mtd_info *mtd, void* param) -@@ -221,6 +263,7 @@ - } - - static struct cfi_fixup cfi_fixup_table[] = { -+ { CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri, NULL }, - #ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE - { CFI_MFR_ANY, CFI_ID_ANY, fixup_intel_strataflash, NULL }, - #endif -diff -urN linux-2.6.20.4-0rig/drivers/mtd/chips/cfi_cmdset_0002.c linux-2.6.20.4-atmel/drivers/mtd/chips/cfi_cmdset_0002.c ---- linux-2.6.20.4-0rig/drivers/mtd/chips/cfi_cmdset_0002.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/mtd/chips/cfi_cmdset_0002.c 2007-03-24 16:42:29.000000000 +0100 -@@ -185,6 +185,10 @@ - extp->TopBottom = 2; - else - extp->TopBottom = 3; -+ -+ /* burst write mode not supported */ -+ cfi->cfiq->BufWriteTimeoutTyp = 0; -+ cfi->cfiq->BufWriteTimeoutMax = 0; - } - - static void fixup_use_secsi(struct mtd_info *mtd, void *param) -@@ -217,6 +221,7 @@ - } - - static struct cfi_fixup cfi_fixup_table[] = { -+ { CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri, NULL }, - #ifdef AMD_BOOTLOC_BUG - { CFI_MFR_AMD, CFI_ID_ANY, fixup_amd_bootblock, NULL }, - #endif -@@ -229,7 +234,6 @@ - #if !FORCE_WORD_WRITE - { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL, }, - #endif -- { CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri, NULL }, - { 0, 0, NULL, NULL } - }; - static struct cfi_fixup jedec_fixup_table[] = { -diff -urN linux-2.6.20.4-0rig/drivers/mtd/devices/at91_dataflash.c linux-2.6.20.4-atmel/drivers/mtd/devices/at91_dataflash.c ---- linux-2.6.20.4-0rig/drivers/mtd/devices/at91_dataflash.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/mtd/devices/at91_dataflash.c 2007-03-24 16:39:15.000000000 +0100 -@@ -0,0 +1,640 @@ -+/* -+ * Atmel DataFlash driver for 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/module.h> -+#include <linux/init.h> -+#include <linux/slab.h> -+#include <linux/pci.h> -+#include <linux/mtd/mtd.h> -+#include <linux/mtd/partitions.h> -+ -+#include <asm/arch/spi.h> -+ -+#undef DEBUG_DATAFLASH -+ -+#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, -+ } -+}; -+ -+#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; -+ -+/* -+ * Perform a SPI transfer to access the DataFlash device. -+ */ -+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) -+{ -+ struct spi_transfer_list* list = spi_transfer_desc; -+ -+ list->tx[0] = tx; list->txlen[0] = tx_len; -+ list->rx[0] = rx; list->rxlen[0] = rx_len; -+ -+ list->tx[1] = txnext; list->txlen[1] = txnext_len; -+ list->rx[1] = rxnext; list->rxlen[1] = rxnext_len; -+ -+ list->nr_transfers = nr; -+ -+ return spi_transfer(list); -+} -+ -+/* ......................................................................... */ -+ -+/* -+ * Poll the DataFlash device until it is READY. -+ */ -+static void at91_dataflash_waitready(void) -+{ -+ char* command = kmalloc(2, GFP_KERNEL); -+ -+ if (!command) -+ return; -+ -+ do { -+ command[0] = OP_READ_STATUS; -+ command[1] = 0; -+ -+ do_spi_transfer(1, command, 2, command, 2, NULL, 0, NULL, 0); -+ } while ((command[1] & 0x80) == 0); -+ -+ kfree(command); -+} -+ -+/* -+ * 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; -+} -+ -+/* -+ * 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 at91_dataflash_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) -+{ -+ struct dataflash_local *priv = (struct dataflash_local *) mtd->priv; -+ unsigned int addr; -+ char* command; -+ -+#ifdef DEBUG_DATAFLASH -+ printk("dataflash_read: %lli .. %lli\n", from, from+len); -+#endif -+ -+ *retlen = 0; -+ -+ /* Sanity checks */ -+ if (!len) -+ return 0; -+ if (from + len > mtd->size) -+ return -EINVAL; -+ -+ /* Calculate flash page/byte address */ -+ addr = (((unsigned)from / priv->page_size) << priv->page_offset) + ((unsigned)from % priv->page_size); -+ -+ command = kmalloc(8, GFP_KERNEL); -+ if (!command) -+ return -ENOMEM; -+ -+ 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 -+ -+ /* 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); -+ -+ *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(); -+ } -+ -+ /* (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; -+ } -+ -+ remaining = remaining - writelen; -+ pageaddr++; -+ offset = 0; -+ writebuf += writelen; -+ *retlen += writelen; -+ -+ 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; -+} -+ -+/* ......................................................................... */ -+ -+/* -+ * 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 -+ -+ if (nr_devices >= DATAFLASH_MAX_DEVICES) { -+ printk(KERN_ERR "at91_dataflash: Too many devices detected\n"); -+ return 0; -+ } -+ -+ 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)); -+ -+ priv->spi = channel; -+ priv->page_size = pagesize; -+ priv->page_offset = pageoffset; -+ device->priv = priv; -+ -+ mtd_devices[nr_devices] = device; -+ nr_devices++; -+ printk("at91_dataflash: %s detected [spi%i] (%i bytes)\n", name, channel, device->size); -+ -+#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 (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); -+ } -+ } -+ -+ return res; -+} -+ -+static int __init at91_dataflash_init(void) -+{ -+ spi_transfer_desc = kmalloc(sizeof(struct spi_transfer_list), GFP_KERNEL); -+ if (!spi_transfer_desc) -+ return -ENOMEM; -+ -+ /* DataFlash (SPI chip select 0) */ -+ at91_dataflash_detect(0); -+ -+#ifdef CONFIG_MTD_AT91_DATAFLASH_CARD -+ /* DataFlash card (SPI chip select 3) */ -+ at91_dataflash_detect(3); -+#endif -+ -+ return 0; -+} -+ -+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); -+} -+ -+ -+module_init(at91_dataflash_init); -+module_exit(at91_dataflash_exit); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Andrew Victor"); -+MODULE_DESCRIPTION("DataFlash driver for Atmel AT91RM9200"); -diff -urN linux-2.6.20.4-0rig/drivers/mtd/devices/Kconfig linux-2.6.20.4-atmel/drivers/mtd/devices/Kconfig ---- linux-2.6.20.4-0rig/drivers/mtd/devices/Kconfig 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/mtd/devices/Kconfig 2007-03-24 16:39:15.000000000 +0100 -@@ -267,5 +267,11 @@ - LinuxBIOS or if you need to recover a DiskOnChip Millennium on which - you have managed to wipe the first block. - --endmenu -+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 -diff -urN linux-2.6.20.4-0rig/drivers/mtd/devices/Makefile linux-2.6.20.4-atmel/drivers/mtd/devices/Makefile ---- linux-2.6.20.4-0rig/drivers/mtd/devices/Makefile 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/mtd/devices/Makefile 2007-03-24 16:39:15.000000000 +0100 -@@ -17,3 +17,4 @@ - obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o - obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o - obj-$(CONFIG_MTD_M25P80) += m25p80.o -+obj-$(CONFIG_MTD_AT91_DATAFLASH)+= at91_dataflash.o -diff -urN linux-2.6.20.4-0rig/drivers/mtd/nand/at91_nand.c linux-2.6.20.4-atmel/drivers/mtd/nand/at91_nand.c ---- linux-2.6.20.4-0rig/drivers/mtd/nand/at91_nand.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/mtd/nand/at91_nand.c 2007-03-24 16:39:15.000000000 +0100 -@@ -82,6 +82,10 @@ - at91_set_gpio_value(host->board->enable_pin, 1); - } - -+#ifdef CONFIG_MTD_PARTITIONS -+const char *part_probes[] = { "cmdlinepart", NULL }; -+#endif -+ - /* - * Probe for the NAND device. - */ -@@ -151,6 +155,12 @@ - #ifdef CONFIG_MTD_PARTITIONS - if (host->board->partition_info) - partitions = host->board->partition_info(mtd->size, &num_partitions); -+#ifdef CONFIG_MTD_CMDLINE_PARTS -+ else { -+ mtd->name = "at91_nand"; -+ num_partitions = parse_mtd_partitions(mtd, part_probes, &partitions, 0); -+ } -+#endif - - if ((!partitions) || (num_partitions == 0)) { - printk(KERN_ERR "at91_nand: No parititions defined, or unsupported device.\n"); -diff -urN linux-2.6.20.4-0rig/drivers/net/arm/at91_ether.c linux-2.6.20.4-atmel/drivers/net/arm/at91_ether.c ---- linux-2.6.20.4-0rig/drivers/net/arm/at91_ether.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/net/arm/at91_ether.c 2007-03-24 16:39:15.000000000 +0100 -@@ -943,14 +943,22 @@ - struct net_device *dev; - struct at91_private *lp; - unsigned int val; -- int res; -+ struct resource *res; -+ int ret; - - 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 */ -@@ -1023,12 +1031,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 */ -@@ -1103,7 +1111,7 @@ - case MII_LXT971A_ID: /* Intel LXT971A: PHY_ID1 = 0x13, PHY_ID2 = 78E0 */ - case MII_RTL8201_ID: /* Realtek RTL8201: PHY_ID1 = 0, PHY_ID2 = 0x8201 */ - case MII_BCM5221_ID: /* Broadcom BCM5221: PHY_ID1 = 0x40, PHY_ID2 = 0x61e0 */ -- case MII_DP83847_ID: /* National Semiconductor DP83847: */ -+ case MII_DP83847_ID: /* National Semiconductor DP83847: */ - case MII_AC101L_ID: /* Altima AC101L: PHY_ID1 = 0x22, PHY_ID2 = 0x5520 */ - case MII_KS8721_ID: /* Micrel KS8721: PHY_ID1 = 0x22, PHY_ID2 = 0x1610 */ - detected = at91ether_setup(phy_id, phy_address, pdev, ether_clk); -diff -urN linux-2.6.20.4-0rig/drivers/net/Kconfig linux-2.6.20.4-atmel/drivers/net/Kconfig ---- linux-2.6.20.4-0rig/drivers/net/Kconfig 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/net/Kconfig 2007-03-24 16:39:15.000000000 +0100 -@@ -190,7 +190,7 @@ - - config MACB - tristate "Atmel MACB support" -- depends on NET_ETHERNET && AVR32 -+ depends on NET_ETHERNET && (AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263) - select MII - help - The Atmel MACB ethernet interface is found on many AT32 and AT91 -diff -urN linux-2.6.20.4-0rig/drivers/net/macb.c linux-2.6.20.4-atmel/drivers/net/macb.c ---- linux-2.6.20.4-0rig/drivers/net/macb.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/net/macb.c 2007-03-24 16:42:28.000000000 +0100 -@@ -883,27 +883,15 @@ - static int macb_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) - { - struct macb *bp = netdev_priv(dev); -- int ret; -- unsigned long flags; -- -- spin_lock_irqsave(&bp->lock, flags); -- ret = mii_ethtool_gset(&bp->mii, cmd); -- spin_unlock_irqrestore(&bp->lock, flags); - -- return ret; -+ return mii_ethtool_gset(&bp->mii, cmd); - } - - static int macb_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) - { - struct macb *bp = netdev_priv(dev); -- int ret; -- unsigned long flags; -- -- spin_lock_irqsave(&bp->lock, flags); -- ret = mii_ethtool_sset(&bp->mii, cmd); -- spin_unlock_irqrestore(&bp->lock, flags); - -- return ret; -+ return mii_ethtool_sset(&bp->mii, cmd); - } - - static void macb_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -@@ -932,17 +920,11 @@ - static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) - { - struct macb *bp = netdev_priv(dev); -- int ret; -- unsigned long flags; - - if (!netif_running(dev)) - return -EINVAL; - -- spin_lock_irqsave(&bp->lock, flags); -- ret = generic_mii_ioctl(&bp->mii, if_mii(rq), cmd, NULL); -- spin_unlock_irqrestore(&bp->lock, flags); -- -- return ret; -+ return generic_mii_ioctl(&bp->mii, if_mii(rq), cmd, NULL); - } - - static ssize_t macb_mii_show(const struct class_device *cd, char *buf, -@@ -1046,6 +1028,14 @@ - - spin_lock_init(&bp->lock); - -+#if defined(CONFIG_ARCH_AT91) -+ bp->pclk = clk_get(&pdev->dev, "macb_clk"); -+ if (IS_ERR(bp->pclk)) { -+ dev_err(&pdev->dev, "failed to get macb_clk\n"); -+ goto err_out_free_dev; -+ } -+ clk_enable(bp->pclk); -+#else - bp->pclk = clk_get(&pdev->dev, "pclk"); - if (IS_ERR(bp->pclk)) { - dev_err(&pdev->dev, "failed to get pclk\n"); -@@ -1059,6 +1049,7 @@ - - clk_enable(bp->pclk); - clk_enable(bp->hclk); -+#endif - - bp->regs = ioremap(regs->start, regs->end - regs->start + 1); - if (!bp->regs) { -@@ -1119,9 +1110,17 @@ - - 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)) ); -+#else - macb_writel(bp, USRIO, 0); -+#endif - else -+#if defined(CONFIG_ARCH_AT91) -+ macb_writel(bp, USRIO, MACB_BIT(CLKEN)); -+#else - macb_writel(bp, USRIO, MACB_BIT(MII)); -+#endif - - bp->tx_pending = DEF_TX_RING_PENDING; - -@@ -1148,9 +1147,11 @@ - err_out_iounmap: - iounmap(bp->regs); - err_out_disable_clocks: -+#ifndef CONFIG_ARCH_AT91 - clk_disable(bp->hclk); -- clk_disable(bp->pclk); - clk_put(bp->hclk); -+#endif -+ clk_disable(bp->pclk); - err_out_put_pclk: - clk_put(bp->pclk); - err_out_free_dev: -@@ -1173,9 +1174,11 @@ - unregister_netdev(dev); - free_irq(dev->irq, dev); - iounmap(bp->regs); -+#ifndef CONFIG_ARCH_AT91 - clk_disable(bp->hclk); -- clk_disable(bp->pclk); - clk_put(bp->hclk); -+#endif -+ clk_disable(bp->pclk); - clk_put(bp->pclk); - free_netdev(dev); - platform_set_drvdata(pdev, NULL); -diff -urN linux-2.6.20.4-0rig/drivers/net/macb.h linux-2.6.20.4-atmel/drivers/net/macb.h ---- linux-2.6.20.4-0rig/drivers/net/macb.h 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/net/macb.h 2007-03-24 16:39:15.000000000 +0100 -@@ -200,7 +200,7 @@ - #define MACB_SOF_OFFSET 30 - #define MACB_SOF_SIZE 2 - --/* Bitfields in USRIO */ -+/* Bitfields in USRIO (AVR32) */ - #define MACB_MII_OFFSET 0 - #define MACB_MII_SIZE 1 - #define MACB_EAM_OFFSET 1 -@@ -210,6 +210,12 @@ - #define MACB_TX_PAUSE_ZERO_OFFSET 3 - #define MACB_TX_PAUSE_ZERO_SIZE 1 - -+/* Bitfields in USRIO (AT91) */ -+#define MACB_RMII_OFFSET 0 -+#define MACB_RMII_SIZE 1 -+#define MACB_CLKEN_OFFSET 1 -+#define MACB_CLKEN_SIZE 1 -+ - /* Bitfields in WOL */ - #define MACB_IP_OFFSET 0 - #define MACB_IP_SIZE 16 -diff -urN linux-2.6.20.4-0rig/drivers/pcmcia/at91_cf.c linux-2.6.20.4-atmel/drivers/pcmcia/at91_cf.c ---- linux-2.6.20.4-0rig/drivers/pcmcia/at91_cf.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/pcmcia/at91_cf.c 2007-03-24 16:39:15.000000000 +0100 -@@ -333,20 +333,27 @@ - struct at91_cf_data *board = cf->board; - - pcmcia_socket_dev_suspend(&pdev->dev, mesg); -+ - if (device_may_wakeup(&pdev->dev)) { - enable_irq_wake(board->det_pin); - if (board->irq_pin) - enable_irq_wake(board->irq_pin); -- } else { -- disable_irq_wake(board->det_pin); -- if (board->irq_pin) -- disable_irq_wake(board->irq_pin); - } -+ - return 0; - } - - static int at91_cf_resume(struct platform_device *pdev) - { -+ struct at91_cf_socket *cf = platform_get_drvdata(pdev); -+ struct at91_cf_data *board = cf->board; -+ -+ if (device_may_wakeup(&pdev->dev)) { -+ disable_irq_wake(board->det_pin); -+ if (board->irq_pin) -+ disable_irq_wake(board->irq_pin); -+ } -+ - pcmcia_socket_dev_resume(&pdev->dev); - return 0; - } -diff -urN linux-2.6.20.4-0rig/drivers/serial/atmel_serial.c linux-2.6.20.4-atmel/drivers/serial/atmel_serial.c ---- linux-2.6.20.4-0rig/drivers/serial/atmel_serial.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/serial/atmel_serial.c 2007-03-24 16:42:29.000000000 +0100 -@@ -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,12 +35,14 @@ - #include <linux/sysrq.h> - #include <linux/tty_flip.h> - #include <linux/platform_device.h> -+#include <linux/dma-mapping.h> -+#include <linux/atmel_pdc.h> - - #include <asm/io.h> - - #include <asm/mach/serial_at91.h> - #include <asm/arch/board.h> --#include <asm/arch/at91_pdc.h> -+ - #ifdef CONFIG_ARM - #include <asm/arch/cpu.h> - #include <asm/arch/gpio.h> -@@ -46,6 +50,11 @@ - - #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 */ -+ - #if defined(CONFIG_SERIAL_ATMEL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) - #define SUPPORT_SYSRQ - #endif -@@ -73,39 +82,46 @@ - - #define ATMEL_ISR_PASS_LIMIT 256 - --#define UART_PUT_CR(port,v) writel(v, (port)->membase + ATMEL_US_CR) --#define UART_GET_MR(port) readl((port)->membase + ATMEL_US_MR) --#define UART_PUT_MR(port,v) writel(v, (port)->membase + ATMEL_US_MR) --#define UART_PUT_IER(port,v) writel(v, (port)->membase + ATMEL_US_IER) --#define UART_PUT_IDR(port,v) writel(v, (port)->membase + ATMEL_US_IDR) --#define UART_GET_IMR(port) readl((port)->membase + ATMEL_US_IMR) --#define UART_GET_CSR(port) readl((port)->membase + ATMEL_US_CSR) --#define UART_GET_CHAR(port) readl((port)->membase + ATMEL_US_RHR) --#define UART_PUT_CHAR(port,v) writel(v, (port)->membase + ATMEL_US_THR) --#define UART_GET_BRGR(port) readl((port)->membase + ATMEL_US_BRGR) --#define UART_PUT_BRGR(port,v) writel(v, (port)->membase + ATMEL_US_BRGR) --#define UART_PUT_RTOR(port,v) writel(v, (port)->membase + ATMEL_US_RTOR) -+#define UART_PUT_CR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_CR) -+#define UART_GET_MR(port) __raw_readl((port)->membase + ATMEL_US_MR) -+#define UART_PUT_MR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_MR) -+#define UART_PUT_IER(port,v) __raw_writel(v, (port)->membase + ATMEL_US_IER) -+#define UART_PUT_IDR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_IDR) -+#define UART_GET_IMR(port) __raw_readl((port)->membase + ATMEL_US_IMR) -+#define UART_GET_CSR(port) __raw_readl((port)->membase + ATMEL_US_CSR) -+#define UART_GET_CHAR(port) __raw_readl((port)->membase + ATMEL_US_RHR) -+#define UART_PUT_CHAR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_THR) -+#define UART_GET_BRGR(port) __raw_readl((port)->membase + ATMEL_US_BRGR) -+#define UART_PUT_BRGR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_BRGR) -+#define UART_PUT_RTOR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_RTOR) - --// #define UART_GET_CR(port) readl((port)->membase + ATMEL_US_CR) // is write-only -+// #define UART_GET_CR(port) __raw_readl((port)->membase + ATMEL_US_CR) // is write-only - - /* PDC registers */ --#define UART_PUT_PTCR(port,v) writel(v, (port)->membase + ATMEL_PDC_PTCR) --#define UART_GET_PTSR(port) readl((port)->membase + ATMEL_PDC_PTSR) -+#define UART_PUT_PTCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_PTCR) -+#define UART_GET_PTSR(port) __raw_readl((port)->membase + ATMEL_PDC_PTSR) - --#define UART_PUT_RPR(port,v) writel(v, (port)->membase + ATMEL_PDC_RPR) --#define UART_GET_RPR(port) readl((port)->membase + ATMEL_PDC_RPR) --#define UART_PUT_RCR(port,v) writel(v, (port)->membase + ATMEL_PDC_RCR) --#define UART_PUT_RNPR(port,v) writel(v, (port)->membase + ATMEL_PDC_RNPR) --#define UART_PUT_RNCR(port,v) writel(v, (port)->membase + ATMEL_PDC_RNCR) -- --#define UART_PUT_TPR(port,v) writel(v, (port)->membase + ATMEL_PDC_TPR) --#define UART_PUT_TCR(port,v) writel(v, (port)->membase + ATMEL_PDC_TCR) --//#define UART_PUT_TNPR(port,v) writel(v, (port)->membase + ATMEL_PDC_TNPR) --//#define UART_PUT_TNCR(port,v) writel(v, (port)->membase + ATMEL_PDC_TNCR) -+#define UART_PUT_RPR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_RPR) -+#define UART_GET_RPR(port) __raw_readl((port)->membase + ATMEL_PDC_RPR) -+#define UART_PUT_RCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_RCR) -+#define UART_PUT_RNPR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_RNPR) -+#define UART_PUT_RNCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_RNCR) -+ -+#define UART_PUT_TPR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_TPR) -+#define UART_PUT_TCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_TCR) -+//#define UART_PUT_TNPR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_TNPR) -+//#define UART_PUT_TNCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_TNCR) - - 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; -+}; -+ - /* - * We wrap our port structure around the generic uart_port. - */ -@@ -113,10 +129,20 @@ - struct uart_port uart; /* uart */ - struct clk *clk; /* uart clock */ - unsigned short suspended; /* is port suspended? */ -+ -+ 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 */ - }; - - 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 -@@ -204,7 +230,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); - } - - /* -@@ -214,7 +245,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); - } - - /* -@@ -224,7 +265,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); - } - - /* -@@ -247,6 +293,134 @@ - } - - /* -+ * 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 */ -+} -+ -+/* -+ * 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; -+ -+ ofs = UART_GET_RPR(port) - pdc->dma_addr; /* current DMA adress */ -+ count = ofs - 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); -+ -+ pdc->ofs = ofs; -+ port->icount.rx += count; -+ } -+ -+ /* reset the UART timeout */ -+ UART_PUT_CR(port, ATMEL_US_STTTO); -+} -+ -+/* -+ * 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); -+ -+ 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++; -+} -+ -+/* -+ * 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; -+ -+ xmit->tail += pdc->ofs; -+ if (xmit->tail >= SERIAL_XMIT_SIZE) -+ xmit->tail -= SERIAL_XMIT_SIZE; -+ -+ port->icount.tx += pdc->ofs; -+ pdc->ofs = 0; -+ -+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) -+ uart_write_wakeup(port); -+} -+ -+/* -+ * 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; -+ -+ 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); -+ -+ 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); -+ } -+} -+ -+/* - * Characters received (called from interrupt handler) - */ - static void atmel_rx_chars(struct uart_port *port) -@@ -348,6 +522,14 @@ - 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); -@@ -362,6 +544,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); -@@ -400,6 +588,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) - */ -@@ -417,7 +646,15 @@ - 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; - } -@@ -430,6 +667,25 @@ - struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) 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); -@@ -480,6 +736,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; - -@@ -533,6 +790,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 - */ -@@ -711,6 +971,11 @@ - 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; -+#endif - } - - /* -diff -urN linux-2.6.20.4-0rig/drivers/spi/atmel_spi.c linux-2.6.20.4-atmel/drivers/spi/atmel_spi.c ---- linux-2.6.20.4-0rig/drivers/spi/atmel_spi.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/spi/atmel_spi.c 2007-03-24 16:39:15.000000000 +0100 -@@ -0,0 +1,699 @@ -+/* -+ * Driver for Atmel AT32 and AT91 SPI Controllers -+ * -+ * 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. -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/init.h> -+#include <linux/clk.h> -+#include <linux/module.h> -+#include <linux/platform_device.h> -+#include <linux/delay.h> -+#include <linux/dma-mapping.h> -+#include <linux/err.h> -+#include <linux/interrupt.h> -+#include <linux/spi/spi.h> -+ -+#include <asm/io.h> -+#include <asm/arch/board.h> -+#include <asm/arch/gpio.h> -+ -+#ifdef CONFIG_ARCH_AT91 -+#include <asm/arch/cpu.h> -+#endif -+ -+#include "atmel_spi.h" -+ -+/* -+ * The core SPI transfer engine just talks to a register bank to set up -+ * DMA transfers; transfer queue progress is driven by IRQs. The clock -+ * framework provides the base clock, subdivided for each spi_device. -+ * -+ * Newer controllers, marked with "new_1" flag, have: -+ * - CR.LASTXFER -+ * - SPI_MR.DIV32 may become FDIV or must-be-zero (here: always zero) -+ * - SPI_SR.TXEMPTY, SPI_SR.NSSR (and corresponding irqs) -+ * - SPI_CSRx.CSAAT -+ * - SPI_CSRx.SBCR allows faster clocking -+ */ -+struct atmel_spi { -+ spinlock_t lock; -+ -+ void __iomem *regs; -+ int irq; -+ struct clk *clk; -+ struct platform_device *pdev; -+ unsigned new_1:1; -+ -+ u8 stopping; -+ struct list_head queue; -+ struct spi_transfer *current_transfer; -+ unsigned long remaining_bytes; -+ -+ void *buffer; -+ dma_addr_t buffer_dma; -+}; -+ -+#define BUFFER_SIZE PAGE_SIZE -+#define INVALID_DMA_ADDRESS 0xffffffff -+ -+/* -+ * Earlier SPI controllers (e.g. on at91rm9200) have a design bug whereby -+ * they assume that spi slave device state will not change on deselect, so -+ * that automagic deselection is OK. Not so! Workaround uses nCSx pins -+ * as GPIOs; or newer controllers have CSAAT and friends. -+ * -+ * Since the CSAAT functionality is a bit weird on newer controllers -+ * as well, we use GPIO to control nCSx pins on all controllers. -+ */ -+ -+static inline void cs_activate(struct spi_device *spi) -+{ -+ unsigned gpio = (unsigned) spi->controller_data; -+ unsigned active = spi->mode & SPI_CS_HIGH; -+ -+ dev_dbg(&spi->dev, "activate %u%s\n", gpio, active ? " (high)" : ""); -+#ifdef CONFIG_ARCH_AT91 -+ at91_set_gpio_value(gpio, active); -+#else -+ gpio_set_value(gpio, active); -+#endif -+} -+ -+static inline void cs_deactivate(struct spi_device *spi) -+{ -+ unsigned gpio = (unsigned) spi->controller_data; -+ unsigned active = spi->mode & SPI_CS_HIGH; -+ -+ dev_dbg(&spi->dev, "DEactivate %u%s\n", gpio, active ? " (low)" : ""); -+#ifdef CONFIG_ARCH_AT91 -+ at91_set_gpio_value(gpio, !active); -+#else -+ gpio_set_value(gpio, !active); -+#endif -+} -+ -+/* -+ * Submit next transfer for DMA. -+ * lock is held, spi irq is blocked -+ */ -+static void atmel_spi_next_xfer(struct spi_master *master, -+ struct spi_message *msg) -+{ -+ struct atmel_spi *as = spi_master_get_devdata(master); -+ struct spi_transfer *xfer; -+ u32 len; -+ dma_addr_t tx_dma, rx_dma; -+ -+ xfer = as->current_transfer; -+ if (!xfer || as->remaining_bytes == 0) { -+ if (xfer) -+ xfer = list_entry(xfer->transfer_list.next, -+ struct spi_transfer, transfer_list); -+ else -+ xfer = list_entry(msg->transfers.next, -+ struct spi_transfer, transfer_list); -+ as->remaining_bytes = xfer->len; -+ as->current_transfer = xfer; -+ } -+ -+ len = as->remaining_bytes; -+ -+ tx_dma = xfer->tx_dma; -+ rx_dma = xfer->rx_dma; -+ -+ /* use scratch buffer only when rx or tx data is unspecified */ -+ if (rx_dma == INVALID_DMA_ADDRESS) { -+ rx_dma = as->buffer_dma; -+ if (len > BUFFER_SIZE) -+ len = BUFFER_SIZE; -+ } -+ if (tx_dma == INVALID_DMA_ADDRESS) { -+ tx_dma = as->buffer_dma; -+ if (len > BUFFER_SIZE) -+ len = BUFFER_SIZE; -+ memset(as->buffer, 0, len); -+ dma_sync_single_for_device(&as->pdev->dev, -+ as->buffer_dma, len, DMA_TO_DEVICE); -+ } -+ -+ spi_writel(as, RPR, rx_dma); -+ spi_writel(as, TPR, tx_dma); -+ -+ as->remaining_bytes -= len; -+ if (msg->spi->bits_per_word > 8) -+ len >>= 1; -+ -+ /* REVISIT: when xfer->delay_usecs == 0, the PDC "next transfer" -+ * mechanism might help avoid the IRQ latency between transfers -+ * -+ * We're also waiting for ENDRX before we start the next -+ * transfer because we need to handle some difficult timing -+ * issues otherwise. If we wait for ENDTX in one transfer and -+ * then starts waiting for ENDRX in the next, it's difficult -+ * to tell the difference between the ENDRX interrupt we're -+ * actually waiting for and the ENDRX interrupt of the -+ * previous transfer. -+ * -+ * It should be doable, though. Just not now... -+ */ -+ spi_writel(as, TNCR, 0); -+ spi_writel(as, RNCR, 0); -+ spi_writel(as, IER, SPI_BIT(ENDRX) | SPI_BIT(OVRES)); -+ -+ dev_dbg(&msg->spi->dev, -+ " start xfer %p: len %u tx %p/%08x rx %p/%08x imr %03x\n", -+ xfer, xfer->len, xfer->tx_buf, xfer->tx_dma, -+ xfer->rx_buf, xfer->rx_dma, spi_readl(as, IMR)); -+ -+ wmb(); -+ spi_writel(as, TCR, len); -+ spi_writel(as, RCR, len); -+ spi_writel(as, PTCR, SPI_BIT(TXTEN) | SPI_BIT(RXTEN)); -+} -+ -+static void atmel_spi_next_message(struct spi_master *master) -+{ -+ struct atmel_spi *as = spi_master_get_devdata(master); -+ struct spi_message *msg; -+ u32 mr; -+ -+ BUG_ON(as->current_transfer); -+ -+ msg = list_entry(as->queue.next, struct spi_message, queue); -+ -+ /* Select the chip */ -+ mr = spi_readl(as, MR); -+ mr = SPI_BFINS(PCS, ~(1 << msg->spi->chip_select), mr); -+ spi_writel(as, MR, mr); -+ cs_activate(msg->spi); -+ -+ atmel_spi_next_xfer(master, msg); -+} -+ -+static void -+atmel_spi_dma_map_xfer(struct atmel_spi *as, struct spi_transfer *xfer) -+{ -+ xfer->tx_dma = xfer->rx_dma = INVALID_DMA_ADDRESS; -+ if (xfer->tx_buf) -+ xfer->tx_dma = dma_map_single(&as->pdev->dev, -+ (void *) xfer->tx_buf, xfer->len, -+ DMA_TO_DEVICE); -+ if (xfer->rx_buf) -+ xfer->rx_dma = dma_map_single(&as->pdev->dev, -+ xfer->rx_buf, xfer->len, -+ DMA_FROM_DEVICE); -+} -+ -+static void atmel_spi_dma_unmap_xfer(struct spi_master *master, -+ struct spi_transfer *xfer) -+{ -+ if (xfer->tx_dma != INVALID_DMA_ADDRESS) -+ dma_unmap_single(master->cdev.dev, xfer->tx_dma, -+ xfer->len, DMA_TO_DEVICE); -+ if (xfer->rx_dma != INVALID_DMA_ADDRESS) -+ dma_unmap_single(master->cdev.dev, xfer->rx_dma, -+ xfer->len, DMA_FROM_DEVICE); -+} -+ -+static void -+atmel_spi_msg_done(struct spi_master *master, struct atmel_spi *as, -+ struct spi_message *msg, int status) -+{ -+ cs_deactivate(msg->spi); -+ list_del(&msg->queue); -+ msg->status = status; -+ -+ dev_dbg(master->cdev.dev, -+ "xfer complete: %u bytes transferred\n", -+ msg->actual_length); -+ -+ spin_unlock(&as->lock); -+ msg->complete(msg->context); -+ spin_lock(&as->lock); -+ -+ as->current_transfer = NULL; -+ -+ /* continue if needed */ -+ if (list_empty(&as->queue) || as->stopping) -+ spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS)); -+ else -+ atmel_spi_next_message(master); -+} -+ -+static irqreturn_t -+atmel_spi_interrupt(int irq, void *dev_id) -+{ -+ struct spi_master *master = dev_id; -+ struct atmel_spi *as = spi_master_get_devdata(master); -+ struct spi_message *msg; -+ struct spi_transfer *xfer; -+ u32 status, pending, imr; -+ int ret = IRQ_NONE; -+ -+ spin_lock(&as->lock); -+ -+ xfer = as->current_transfer; -+ msg = list_entry(as->queue.next, struct spi_message, queue); -+ -+ imr = spi_readl(as, IMR); -+ status = spi_readl(as, SR); -+ pending = status & imr; -+ -+ if (pending & SPI_BIT(OVRES)) { -+ int timeout; -+ -+ ret = IRQ_HANDLED; -+ -+ spi_writel(as, IDR, (SPI_BIT(ENDTX) | SPI_BIT(ENDRX) -+ | SPI_BIT(OVRES))); -+ -+ /* -+ * When we get an overrun, we disregard the current -+ * transfer. Data will not be copied back from any -+ * bounce buffer and msg->actual_len will not be -+ * updated with the last xfer. -+ * -+ * We will also not process any remaning transfers in -+ * the message. -+ * -+ * First, stop the transfer and unmap the DMA buffers. -+ */ -+ spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS)); -+ if (!msg->is_dma_mapped) -+ atmel_spi_dma_unmap_xfer(master, xfer); -+ -+ /* REVISIT: udelay in irq is unfriendly */ -+ if (xfer->delay_usecs) -+ udelay(xfer->delay_usecs); -+ -+ dev_warn(master->cdev.dev, "fifo overrun (%u/%u remaining)\n", -+ spi_readl(as, TCR), spi_readl(as, RCR)); -+ -+ /* -+ * Clean up DMA registers and make sure the data -+ * registers are empty. -+ */ -+ spi_writel(as, RNCR, 0); -+ spi_writel(as, TNCR, 0); -+ spi_writel(as, RCR, 0); -+ spi_writel(as, TCR, 0); -+ for (timeout = 1000; timeout; timeout--) -+ if (spi_readl(as, SR) & SPI_BIT(TXEMPTY)) -+ break; -+ if (!timeout) -+ dev_warn(master->cdev.dev, -+ "timeout waiting for TXEMPTY"); -+ while (spi_readl(as, SR) & SPI_BIT(RDRF)) -+ spi_readl(as, RDR); -+ -+ /* Clear any overrun happening while cleaning up */ -+ spi_readl(as, SR); -+ -+ atmel_spi_msg_done(master, as, msg, -EIO); -+ } else if (pending & SPI_BIT(ENDRX)) { -+ ret = IRQ_HANDLED; -+ -+ spi_writel(as, IDR, pending); -+ -+ if (as->remaining_bytes == 0) { -+ msg->actual_length += xfer->len; -+ -+ if (!msg->is_dma_mapped) -+ atmel_spi_dma_unmap_xfer(master, xfer); -+ -+ /* REVISIT: udelay in irq is unfriendly */ -+ if (xfer->delay_usecs) -+ udelay(xfer->delay_usecs); -+ -+ if (msg->transfers.prev == &xfer->transfer_list) { -+ /* report completed message */ -+ atmel_spi_msg_done(master, as, msg, 0); -+ } else { -+ if (xfer->cs_change) { -+ cs_deactivate(msg->spi); -+ udelay(1); -+ cs_activate(msg->spi); -+ } -+ -+ /* -+ * Not done yet. Submit the next transfer. -+ * -+ * FIXME handle protocol options for xfer -+ */ -+ atmel_spi_next_xfer(master, msg); -+ } -+ } else { -+ /* -+ * Keep going, we still have data to send in -+ * the current transfer. -+ */ -+ atmel_spi_next_xfer(master, msg); -+ } -+ } -+ -+ spin_unlock(&as->lock); -+ -+ return ret; -+} -+ -+#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH) -+ -+static int atmel_spi_setup(struct spi_device *spi) -+{ -+ struct atmel_spi *as; -+ u32 scbr, csr; -+ unsigned int bits = spi->bits_per_word; -+ unsigned long bus_hz, sck_hz; -+ unsigned int npcs_pin; -+ int ret; -+ -+ as = spi_master_get_devdata(spi->master); -+ -+ if (as->stopping) -+ return -ESHUTDOWN; -+ -+ if (spi->chip_select > spi->master->num_chipselect) { -+ dev_dbg(&spi->dev, -+ "setup: invalid chipselect %u (%u defined)\n", -+ spi->chip_select, spi->master->num_chipselect); -+ return -EINVAL; -+ } -+ -+ if (bits == 0) -+ bits = 8; -+ if (bits < 8 || bits > 16) { -+ dev_dbg(&spi->dev, -+ "setup: invalid bits_per_word %u (8 to 16)\n", -+ bits); -+ return -EINVAL; -+ } -+ -+ if (spi->mode & ~MODEBITS) { -+ dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n", -+ spi->mode & ~MODEBITS); -+ return -EINVAL; -+ } -+ -+ /* speed zero convention is used by some upper layers */ -+ bus_hz = clk_get_rate(as->clk); -+ if (spi->max_speed_hz) { -+ /* assume div32/fdiv/mbz == 0 */ -+ if (!as->new_1) -+ bus_hz /= 2; -+ scbr = ((bus_hz + spi->max_speed_hz - 1) -+ / spi->max_speed_hz); -+ if (scbr >= (1 << SPI_SCBR_SIZE)) { -+ dev_dbg(&spi->dev, "setup: %d Hz too slow, scbr %u\n", -+ spi->max_speed_hz, scbr); -+ return -EINVAL; -+ } -+ } else -+ scbr = 0xff; -+ sck_hz = bus_hz / scbr; -+ -+ csr = SPI_BF(SCBR, scbr) | SPI_BF(BITS, bits - 8); -+ if (spi->mode & SPI_CPOL) -+ csr |= SPI_BIT(CPOL); -+ if (!(spi->mode & SPI_CPHA)) -+ csr |= SPI_BIT(NCPHA); -+ -+ /* TODO: DLYBS and DLYBCT */ -+ csr |= SPI_BF(DLYBS, 10); -+ csr |= SPI_BF(DLYBCT, 10); -+ -+ /* chipselect must have been muxed as GPIO (e.g. in board setup) */ -+ npcs_pin = (unsigned int)spi->controller_data; -+ if (!spi->controller_state) { -+#ifndef CONFIG_ARCH_AT91 -+ ret = gpio_request(npcs_pin, "spi_npcs"); -+ if (ret) -+ return ret; -+#endif -+ spi->controller_state = (void *)npcs_pin; -+#ifdef CONFIG_ARCH_AT91 -+ at91_set_gpio_output(npcs_pin, 0); -+#else -+ gpio_direction_output(npcs_pin); -+#endif -+ } -+ -+ dev_dbg(&spi->dev, -+ "setup: %lu Hz bpw %u mode 0x%x -> csr%d %08x\n", -+ sck_hz, bits, spi->mode, spi->chip_select, csr); -+ -+ spi_writel(as, CSR0 + 4 * spi->chip_select, csr); -+ -+ return 0; -+} -+ -+static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg) -+{ -+ struct atmel_spi *as; -+ struct spi_transfer *xfer; -+ unsigned long flags; -+ struct device *controller = spi->master->cdev.dev; -+ -+ as = spi_master_get_devdata(spi->master); -+ -+ dev_dbg(controller, "new message %p submitted for %s\n", -+ msg, spi->dev.bus_id); -+ -+ if (unlikely(list_empty(&msg->transfers) -+ || !spi->max_speed_hz)) -+ return -EINVAL; -+ -+ if (as->stopping) -+ return -ESHUTDOWN; -+ -+ list_for_each_entry(xfer, &msg->transfers, transfer_list) { -+ if (!(xfer->tx_buf || xfer->rx_buf)) { -+ dev_dbg(&spi->dev, "missing rx or tx buf\n"); -+ return -EINVAL; -+ } -+ -+ /* FIXME implement these protocol options!! */ -+ if (xfer->bits_per_word || xfer->speed_hz) { -+ dev_dbg(&spi->dev, "no protocol options yet\n"); -+ return -ENOPROTOOPT; -+ } -+ } -+ -+ /* scrub dcache "early" */ -+ if (!msg->is_dma_mapped) { -+ list_for_each_entry(xfer, &msg->transfers, transfer_list) -+ atmel_spi_dma_map_xfer(as, xfer); -+ } -+ -+ list_for_each_entry(xfer, &msg->transfers, transfer_list) { -+ dev_dbg(controller, -+ " xfer %p: len %u tx %p/%08x rx %p/%08x\n", -+ xfer, xfer->len, -+ xfer->tx_buf, xfer->tx_dma, -+ xfer->rx_buf, xfer->rx_dma); -+ } -+ -+ msg->status = -EINPROGRESS; -+ msg->actual_length = 0; -+ -+ spin_lock_irqsave(&as->lock, flags); -+ list_add_tail(&msg->queue, &as->queue); -+ if (!as->current_transfer) -+ atmel_spi_next_message(spi->master); -+ spin_unlock_irqrestore(&as->lock, flags); -+ -+ return 0; -+} -+ -+static void atmel_spi_cleanup(const struct spi_device *spi) -+{ -+#ifndef CONFIG_ARCH_AT91 -+ if (spi->controller_state) -+ gpio_free((unsigned int)spi->controller_data); -+#endif -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+static int __init atmel_spi_probe(struct platform_device *pdev) -+{ -+ struct resource *regs; -+ int irq; -+ struct clk *clk; -+ int ret; -+ struct spi_master *master; -+ struct atmel_spi *as; -+ -+ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!regs) -+ return -ENXIO; -+ -+ irq = platform_get_irq(pdev, 0); -+ if (irq < 0) -+ return irq; -+ -+ clk = clk_get(&pdev->dev, "spi_clk"); -+ if (IS_ERR(clk)) -+ return PTR_ERR(clk); -+ -+ /* setup spi core then atmel-specific driver state */ -+ ret = -ENOMEM; -+ master = spi_alloc_master(&pdev->dev, sizeof *as); -+ if (!master) -+ goto out_free; -+ -+ master->bus_num = pdev->id; -+ master->num_chipselect = 4; -+ master->setup = atmel_spi_setup; -+ master->transfer = atmel_spi_transfer; -+ master->cleanup = atmel_spi_cleanup; -+ platform_set_drvdata(pdev, master); -+ -+ as = spi_master_get_devdata(master); -+ -+ as->buffer = dma_alloc_coherent(&pdev->dev, BUFFER_SIZE, -+ &as->buffer_dma, GFP_KERNEL); -+ if (!as->buffer) -+ goto out_free; -+ -+ spin_lock_init(&as->lock); -+ INIT_LIST_HEAD(&as->queue); -+ as->pdev = pdev; -+ as->regs = ioremap(regs->start, (regs->end - regs->start) + 1); -+ if (!as->regs) -+ goto out_free_buffer; -+ as->irq = irq; -+ as->clk = clk; -+#ifdef CONFIG_ARCH_AT91 -+ if (!cpu_is_at91rm9200()) -+ as->new_1 = 1; -+#endif -+ -+ ret = request_irq(irq, atmel_spi_interrupt, 0, -+ pdev->dev.bus_id, master); -+ if (ret) -+ goto out_unmap_regs; -+ -+ /* Initialize the hardware */ -+ clk_enable(clk); -+ spi_writel(as, CR, SPI_BIT(SWRST)); -+ spi_writel(as, MR, SPI_BIT(MSTR) | SPI_BIT(MODFDIS)); -+ spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS)); -+ spi_writel(as, CR, SPI_BIT(SPIEN)); -+ -+ /* go! */ -+ dev_info(&pdev->dev, "Atmel SPI Controller at 0x%08lx (irq %d)\n", -+ (unsigned long)regs->start, irq); -+ -+ ret = spi_register_master(master); -+ if (ret) -+ goto out_reset_hw; -+ -+ return 0; -+ -+out_reset_hw: -+ spi_writel(as, CR, SPI_BIT(SWRST)); -+ clk_disable(clk); -+ free_irq(irq, master); -+out_unmap_regs: -+ iounmap(as->regs); -+out_free_buffer: -+ dma_free_coherent(&pdev->dev, BUFFER_SIZE, as->buffer, -+ as->buffer_dma); -+out_free: -+ clk_put(clk); -+ spi_master_put(master); -+ return ret; -+} -+ -+static int __exit atmel_spi_remove(struct platform_device *pdev) -+{ -+ struct spi_master *master = platform_get_drvdata(pdev); -+ struct atmel_spi *as = spi_master_get_devdata(master); -+ struct spi_message *msg; -+ -+ /* reset the hardware and block queue progress */ -+ spin_lock_irq(&as->lock); -+ as->stopping = 1; -+ spi_writel(as, CR, SPI_BIT(SWRST)); -+ spi_readl(as, SR); -+ spin_unlock_irq(&as->lock); -+ -+ /* Terminate remaining queued transfers */ -+ list_for_each_entry(msg, &as->queue, queue) { -+ /* REVISIT unmapping the dma is a NOP on ARM and AVR32 -+ * but we shouldn't depend on that... -+ */ -+ msg->status = -ESHUTDOWN; -+ msg->complete(msg->context); -+ } -+ -+ dma_free_coherent(&pdev->dev, BUFFER_SIZE, as->buffer, -+ as->buffer_dma); -+ -+ clk_disable(as->clk); -+ clk_put(as->clk); -+ free_irq(as->irq, master); -+ iounmap(as->regs); -+ -+ spi_unregister_master(master); -+ -+ return 0; -+} -+ -+#ifdef CONFIG_PM -+ -+static int atmel_spi_suspend(struct platform_device *pdev, pm_message_t mesg) -+{ -+ struct spi_master *master = platform_get_drvdata(pdev); -+ struct atmel_spi *as = spi_master_get_devdata(master); -+ -+ clk_disable(as->clk); -+ return 0; -+} -+ -+static int atmel_spi_resume(struct platform_device *pdev) -+{ -+ struct spi_master *master = platform_get_drvdata(pdev); -+ struct atmel_spi *as = spi_master_get_devdata(master); -+ -+ clk_enable(as->clk); -+ return 0; -+} -+ -+#else -+#define atmel_spi_suspend NULL -+#define atmel_spi_resume NULL -+#endif -+ -+ -+static struct platform_driver atmel_spi_driver = { -+ .driver = { -+ .name = "atmel_spi", -+ .owner = THIS_MODULE, -+ }, -+ .suspend = atmel_spi_suspend, -+ .resume = atmel_spi_resume, -+ .remove = __exit_p(atmel_spi_remove), -+}; -+ -+static int __init atmel_spi_init(void) -+{ -+ return platform_driver_probe(&atmel_spi_driver, atmel_spi_probe); -+} -+module_init(atmel_spi_init); -+ -+static void __exit atmel_spi_exit(void) -+{ -+ platform_driver_unregister(&atmel_spi_driver); -+} -+module_exit(atmel_spi_exit); -+ -+MODULE_DESCRIPTION("Atmel AT32/AT91 SPI Controller driver"); -+MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>"); -+MODULE_LICENSE("GPL"); -diff -urN linux-2.6.20.4-0rig/drivers/spi/atmel_spi.h linux-2.6.20.4-atmel/drivers/spi/atmel_spi.h ---- linux-2.6.20.4-0rig/drivers/spi/atmel_spi.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/spi/atmel_spi.h 2007-03-24 16:43:57.000000000 +0100 -@@ -0,0 +1,167 @@ -+/* -+ * Register definitions for Atmel Serial Peripheral Interface (SPI) -+ * -+ * 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 __ATMEL_SPI_H__ -+#define __ATMEL_SPI_H__ -+ -+/* SPI register offsets */ -+#define SPI_CR 0x0000 -+#define SPI_MR 0x0004 -+#define SPI_RDR 0x0008 -+#define SPI_TDR 0x000c -+#define SPI_SR 0x0010 -+#define SPI_IER 0x0014 -+#define SPI_IDR 0x0018 -+#define SPI_IMR 0x001c -+#define SPI_CSR0 0x0030 -+#define SPI_CSR1 0x0034 -+#define SPI_CSR2 0x0038 -+#define SPI_CSR3 0x003c -+#define SPI_RPR 0x0100 -+#define SPI_RCR 0x0104 -+#define SPI_TPR 0x0108 -+#define SPI_TCR 0x010c -+#define SPI_RNPR 0x0110 -+#define SPI_RNCR 0x0114 -+#define SPI_TNPR 0x0118 -+#define SPI_TNCR 0x011c -+#define SPI_PTCR 0x0120 -+#define SPI_PTSR 0x0124 -+ -+/* Bitfields in CR */ -+#define SPI_SPIEN_OFFSET 0 -+#define SPI_SPIEN_SIZE 1 -+#define SPI_SPIDIS_OFFSET 1 -+#define SPI_SPIDIS_SIZE 1 -+#define SPI_SWRST_OFFSET 7 -+#define SPI_SWRST_SIZE 1 -+#define SPI_LASTXFER_OFFSET 24 -+#define SPI_LASTXFER_SIZE 1 -+ -+/* Bitfields in MR */ -+#define SPI_MSTR_OFFSET 0 -+#define SPI_MSTR_SIZE 1 -+#define SPI_PS_OFFSET 1 -+#define SPI_PS_SIZE 1 -+#define SPI_PCSDEC_OFFSET 2 -+#define SPI_PCSDEC_SIZE 1 -+#define SPI_FDIV_OFFSET 3 -+#define SPI_FDIV_SIZE 1 -+#define SPI_MODFDIS_OFFSET 4 -+#define SPI_MODFDIS_SIZE 1 -+#define SPI_LLB_OFFSET 7 -+#define SPI_LLB_SIZE 1 -+#define SPI_PCS_OFFSET 16 -+#define SPI_PCS_SIZE 4 -+#define SPI_DLYBCS_OFFSET 24 -+#define SPI_DLYBCS_SIZE 8 -+ -+/* Bitfields in RDR */ -+#define SPI_RD_OFFSET 0 -+#define SPI_RD_SIZE 16 -+ -+/* Bitfields in TDR */ -+#define SPI_TD_OFFSET 0 -+#define SPI_TD_SIZE 16 -+ -+/* Bitfields in SR */ -+#define SPI_RDRF_OFFSET 0 -+#define SPI_RDRF_SIZE 1 -+#define SPI_TDRE_OFFSET 1 -+#define SPI_TDRE_SIZE 1 -+#define SPI_MODF_OFFSET 2 -+#define SPI_MODF_SIZE 1 -+#define SPI_OVRES_OFFSET 3 -+#define SPI_OVRES_SIZE 1 -+#define SPI_ENDRX_OFFSET 4 -+#define SPI_ENDRX_SIZE 1 -+#define SPI_ENDTX_OFFSET 5 -+#define SPI_ENDTX_SIZE 1 -+#define SPI_RXBUFF_OFFSET 6 -+#define SPI_RXBUFF_SIZE 1 -+#define SPI_TXBUFE_OFFSET 7 -+#define SPI_TXBUFE_SIZE 1 -+#define SPI_NSSR_OFFSET 8 -+#define SPI_NSSR_SIZE 1 -+#define SPI_TXEMPTY_OFFSET 9 -+#define SPI_TXEMPTY_SIZE 1 -+#define SPI_SPIENS_OFFSET 16 -+#define SPI_SPIENS_SIZE 1 -+ -+/* Bitfields in CSR0 */ -+#define SPI_CPOL_OFFSET 0 -+#define SPI_CPOL_SIZE 1 -+#define SPI_NCPHA_OFFSET 1 -+#define SPI_NCPHA_SIZE 1 -+#define SPI_CSAAT_OFFSET 3 -+#define SPI_CSAAT_SIZE 1 -+#define SPI_BITS_OFFSET 4 -+#define SPI_BITS_SIZE 4 -+#define SPI_SCBR_OFFSET 8 -+#define SPI_SCBR_SIZE 8 -+#define SPI_DLYBS_OFFSET 16 -+#define SPI_DLYBS_SIZE 8 -+#define SPI_DLYBCT_OFFSET 24 -+#define SPI_DLYBCT_SIZE 8 -+ -+/* Bitfields in RCR */ -+#define SPI_RXCTR_OFFSET 0 -+#define SPI_RXCTR_SIZE 16 -+ -+/* Bitfields in TCR */ -+#define SPI_TXCTR_OFFSET 0 -+#define SPI_TXCTR_SIZE 16 -+ -+/* Bitfields in RNCR */ -+#define SPI_RXNCR_OFFSET 0 -+#define SPI_RXNCR_SIZE 16 -+ -+/* Bitfields in TNCR */ -+#define SPI_TXNCR_OFFSET 0 -+#define SPI_TXNCR_SIZE 16 -+ -+/* Bitfields in PTCR */ -+#define SPI_RXTEN_OFFSET 0 -+#define SPI_RXTEN_SIZE 1 -+#define SPI_RXTDIS_OFFSET 1 -+#define SPI_RXTDIS_SIZE 1 -+#define SPI_TXTEN_OFFSET 8 -+#define SPI_TXTEN_SIZE 1 -+#define SPI_TXTDIS_OFFSET 9 -+#define SPI_TXTDIS_SIZE 1 -+ -+/* Constants for BITS */ -+#define SPI_BITS_8_BPT 0 -+#define SPI_BITS_9_BPT 1 -+#define SPI_BITS_10_BPT 2 -+#define SPI_BITS_11_BPT 3 -+#define SPI_BITS_12_BPT 4 -+#define SPI_BITS_13_BPT 5 -+#define SPI_BITS_14_BPT 6 -+#define SPI_BITS_15_BPT 7 -+#define SPI_BITS_16_BPT 8 -+ -+/* Bit manipulation macros */ -+#define SPI_BIT(name) \ -+ (1 << SPI_##name##_OFFSET) -+#define SPI_BF(name,value) \ -+ (((value) & ((1 << SPI_##name##_SIZE) - 1)) << SPI_##name##_OFFSET) -+#define SPI_BFEXT(name,value) \ -+ (((value) >> SPI_##name##_OFFSET) & ((1 << SPI_##name##_SIZE) - 1)) -+#define SPI_BFINS(name,value,old) \ -+ ( ((old) & ~(((1 << SPI_##name##_SIZE) - 1) << SPI_##name##_OFFSET)) \ -+ | SPI_BF(name,value)) -+ -+/* Register access macros */ -+#define spi_readl(port,reg) \ -+ __raw_readl((port)->regs + SPI_##reg) -+#define spi_writel(port,reg,value) \ -+ __raw_writel((value), (port)->regs + SPI_##reg) -+ -+#endif /* __ATMEL_SPI_H__ */ -diff -urN linux-2.6.20.4-0rig/drivers/spi/Kconfig linux-2.6.20.4-atmel/drivers/spi/Kconfig ---- linux-2.6.20.4-0rig/drivers/spi/Kconfig 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/spi/Kconfig 2007-03-24 16:43:49.000000000 +0100 -@@ -51,6 +51,21 @@ - comment "SPI Master Controller Drivers" - depends on SPI_MASTER - -+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. -+ -+config SPI_ATMEL -+ tristate "Atmel SPI Controller" -+ depends on (ARCH_AT91 || AVR32) && SPI_MASTER -+ help -+ This selects a driver for the Atmel SPI Controller, present on -+ many AT32 (AVR32) and AT91 (ARM) chips. -+ - config SPI_BITBANG - tristate "Bitbanging SPI master" - depends on SPI_MASTER && EXPERIMENTAL -@@ -75,6 +90,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_MPC83xx - tristate "Freescale MPC83xx SPI controller" - depends on SPI_MASTER && PPC_83xx && EXPERIMENTAL -diff -urN linux-2.6.20.4-0rig/drivers/spi/Makefile linux-2.6.20.4-atmel/drivers/spi/Makefile ---- linux-2.6.20.4-0rig/drivers/spi/Makefile 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/spi/Makefile 2007-03-24 16:39:15.000000000 +0100 -@@ -12,11 +12,14 @@ - - # SPI master controller drivers (bus) - obj-$(CONFIG_SPI_BITBANG) += spi_bitbang.o -+obj-$(CONFIG_SPI_ATMEL) += atmel_spi.o - obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o - obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o - 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 -+obj-$(CONFIG_SPI_ATMEL) += atmel_spi.o - # ... add above this line ... - - # SPI protocol drivers (device/link on bus) -diff -urN linux-2.6.20.4-0rig/drivers/spi/spi_at91_bitbang.c linux-2.6.20.4-atmel/drivers/spi/spi_at91_bitbang.c ---- linux-2.6.20.4-0rig/drivers/spi/spi_at91_bitbang.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/spi/spi_at91_bitbang.c 2007-03-24 16:39:15.000000000 +0100 -@@ -0,0 +1,207 @@ -+/* -+ * 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. -+ */ -+#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) -+{ -+ at91_set_gpio_value(spi_sck_bit, is_on); -+} -+ -+static inline void setmosi(struct spi_device *spi, int is_on) -+{ -+ at91_set_gpio_value(spi_mosi_bit, is_on); -+} -+ -+static inline int getmiso(struct spi_device *spi) -+{ -+ return at91_get_gpio_value(spi_miso_bit); -+} -+ -+static void at91_spi_chipselect(struct spi_device *spi, int is_active) -+{ -+ unsigned long cs = (unsigned long) spi->controller_data; -+ -+ /* set default clock polarity */ -+ if (is_active) -+ setsck(spi, spi->mode & SPI_CPOL); -+ -+ /* only support active-low (default) */ -+ at91_set_gpio_value(cs, !is_active); -+} -+ -+/* -+ * NOTE: this is "as fast as we can"; it should be a function of -+ * the device clock ... -+ */ -+#define spidelay(X) do{} while(0) -+ -+#define EXPAND_BITBANG_TXRX -+#include <linux/spi/spi_bitbang.h> -+ -+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); -+} -+ -+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); -+} -+ -+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); -+} -+ -+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); -+} -+ -+/*----------------------------------------------------------------------*/ -+ -+static int __init at91_spi_probe(struct platform_device *pdev) -+{ -+ int status; -+ struct spi_master *master; -+ struct at91_spi *at91_spi; -+ -+ if (pdev->id != 0) /* SPI0 bus */ -+ return -EINVAL; -+ -+ master = spi_alloc_master(&pdev->dev, sizeof *at91_spi); -+ if (!master) -+ return -ENOMEM; -+ -+ at91_spi = spi_master_get_devdata(master); -+ at91_spi->pdev = pdev; -+ platform_set_drvdata(pdev, at91_spi); -+ -+ /* SPI and bitbang hookup */ -+ master->bus_num = 0; -+ master->num_chipselect = 4; -+ -+ 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 __exit at91_spi_remove(struct platform_device *pdev) -+{ -+ struct at91_spi *at91_spi = platform_get_drvdata(pdev); -+ int status; -+ -+ /* stop() unregisters child devices too */ -+ status = spi_bitbang_stop(&at91_spi->bitbang); -+ (void) spi_master_put(at91_spi->bitbang.master); -+ -+ platform_set_drvdata(pdev, NULL); -+ return status; -+} -+ -+static struct platform_driver at91_spi_driver = { -+ .probe = at91_spi_probe, -+ .remove = __exit_p(at91_spi_remove), -+ .driver = { -+ .name = "at91_spi", -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+static int __init at91_spi_init(void) -+{ -+ 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 at91_spi_exit(void) -+{ -+ platform_driver_unregister(&at91_spi_driver); -+} -+ -+device_initcall(at91_spi_init); -+module_exit(at91_spi_exit); -+ -+MODULE_ALIAS("at91_spi.0"); -+ -+MODULE_DESCRIPTION("AT91 SPI support (BOOTSTRAP/BITBANG VERSION)"); -+MODULE_AUTHOR("David Brownell"); -+MODULE_LICENSE("GPL"); -diff -urN linux-2.6.20.4-0rig/drivers/usb/gadget/at91_udc.c linux-2.6.20.4-atmel/drivers/usb/gadget/at91_udc.c ---- linux-2.6.20.4-0rig/drivers/usb/gadget/at91_udc.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/usb/gadget/at91_udc.c 2007-03-24 16:39:15.000000000 +0100 -@@ -287,8 +287,8 @@ - ep->stopped = stopped; - - /* ep0 is always ready; other endpoints need a non-empty queue */ -- if (list_empty(&ep->queue) && ep->int_mask != (1 << 0)) -- at91_udp_write(udc, AT91_UDP_IDR, ep->int_mask); -+ if (list_empty(&ep->queue) && (ep->id != 0)) -+ at91_udp_write(udc, AT91_UDP_IDR, 1 << ep->id); - } - - /*-------------------------------------------------------------------------*/ -@@ -541,7 +541,7 @@ - * reset/init endpoint fifo. NOTE: leaves fifo_bank alone, - * since endpoint resets don't reset hw pingpong state. - */ -- at91_udp_write(dev, AT91_UDP_RST_EP, ep->int_mask); -+ at91_udp_write(dev, AT91_UDP_RST_EP, 1 << ep->id); - at91_udp_write(dev, AT91_UDP_RST_EP, 0); - - local_irq_restore(flags); -@@ -567,7 +567,7 @@ - - /* reset fifos and endpoint */ - if (ep->udc->clocked) { -- at91_udp_write(udc, AT91_UDP_RST_EP, ep->int_mask); -+ at91_udp_write(udc, AT91_UDP_RST_EP, 1 << ep->id); - at91_udp_write(udc, AT91_UDP_RST_EP, 0); - __raw_writel(0, ep->creg); - } -@@ -715,7 +715,7 @@ - - if (req && !status) { - list_add_tail (&req->queue, &ep->queue); -- at91_udp_write(dev, AT91_UDP_IER, ep->int_mask); -+ at91_udp_write(dev, AT91_UDP_IER, 1 << ep->id); - } - done: - local_irq_restore(flags); -@@ -774,7 +774,7 @@ - csr |= AT91_UDP_FORCESTALL; - VDBG("halt %s\n", ep->ep.name); - } else { -- at91_udp_write(udc, AT91_UDP_RST_EP, ep->int_mask); -+ at91_udp_write(udc, AT91_UDP_RST_EP, 1 << ep->id); - at91_udp_write(udc, AT91_UDP_RST_EP, 0); - csr &= ~AT91_UDP_FORCESTALL; - } -@@ -913,14 +913,15 @@ - at91_udp_write(udc, AT91_UDP_TXVC, 0); - if (cpu_is_at91rm9200()) - at91_set_gpio_value(udc->board.pullup_pin, 1); -- else if (cpu_is_at91sam9260()) { -+ else if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) { - u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC); -- -+ - txvc |= AT91_UDP_TXVC_PUON; - at91_udp_write(udc, AT91_UDP_TXVC, txvc); -- } else if (cpu_is_at91sam9261()) { -+ } -+ else if (cpu_is_at91sam9261()) { - u32 usbpucr; -- -+ - usbpucr = at91_sys_read(AT91_MATRIX_USBPUCR); - usbpucr |= AT91_MATRIX_USBPUCR_PUON; - at91_sys_write(AT91_MATRIX_USBPUCR, usbpucr); -@@ -928,20 +929,20 @@ - } else { - stop_activity(udc); - at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS); -- if (cpu_is_at91rm9200()) -- at91_set_gpio_value(udc->board.pullup_pin, 0); -- else if (cpu_is_at91sam9260()) { -- u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC); -- -- txvc &= ~AT91_UDP_TXVC_PUON; -- at91_udp_write(udc, AT91_UDP_TXVC, txvc); -- } else if (cpu_is_at91sam9261()) { -- u32 usbpucr; -- -- usbpucr = at91_sys_read(AT91_MATRIX_USBPUCR); -- usbpucr &= ~AT91_MATRIX_USBPUCR_PUON; -- at91_sys_write(AT91_MATRIX_USBPUCR, usbpucr); -- } -+ if (cpu_is_at91rm9200()) -+ at91_set_gpio_value(udc->board.pullup_pin, 0); -+ else if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) { -+ u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC); -+ -+ txvc &= ~AT91_UDP_TXVC_PUON; -+ at91_udp_write(udc, AT91_UDP_TXVC, txvc); -+ } else if (cpu_is_at91sam9261()) { -+ u32 usbpucr; -+ -+ usbpucr = at91_sys_read(AT91_MATRIX_USBPUCR); -+ usbpucr &= ~AT91_MATRIX_USBPUCR_PUON; -+ at91_sys_write(AT91_MATRIX_USBPUCR, usbpucr); -+ } - clk_off(udc); - } - } -@@ -1228,7 +1229,7 @@ - } else if (ep->is_in) - goto stall; - -- at91_udp_write(udc, AT91_UDP_RST_EP, ep->int_mask); -+ at91_udp_write(udc, AT91_UDP_RST_EP, 1 << ep->id); - at91_udp_write(udc, AT91_UDP_RST_EP, 0); - tmp = __raw_readl(ep->creg); - tmp |= CLR_FX; -@@ -1504,15 +1505,16 @@ - } - }, - .ep[0] = { -+ .id = 0, - .ep = { - .name = ep0name, - .ops = &at91_ep_ops, - }, - .udc = &controller, - .maxpacket = 8, -- .int_mask = 1 << 0, - }, - .ep[1] = { -+ .id = 1, - .ep = { - .name = "ep1", - .ops = &at91_ep_ops, -@@ -1520,9 +1522,9 @@ - .udc = &controller, - .is_pingpong = 1, - .maxpacket = 64, -- .int_mask = 1 << 1, - }, - .ep[2] = { -+ .id = 2, - .ep = { - .name = "ep2", - .ops = &at91_ep_ops, -@@ -1530,9 +1532,9 @@ - .udc = &controller, - .is_pingpong = 1, - .maxpacket = 64, -- .int_mask = 1 << 2, - }, - .ep[3] = { -+ .id = 3, - .ep = { - /* could actually do bulk too */ - .name = "ep3-int", -@@ -1540,9 +1542,9 @@ - }, - .udc = &controller, - .maxpacket = 8, -- .int_mask = 1 << 3, - }, - .ep[4] = { -+ .id = 4, - .ep = { - .name = "ep4", - .ops = &at91_ep_ops, -@@ -1550,9 +1552,9 @@ - .udc = &controller, - .is_pingpong = 1, - .maxpacket = 256, -- .int_mask = 1 << 4, - }, - .ep[5] = { -+ .id = 5, - .ep = { - .name = "ep5", - .ops = &at91_ep_ops, -@@ -1560,7 +1562,6 @@ - .udc = &controller, - .is_pingpong = 1, - .maxpacket = 256, -- .int_mask = 1 << 5, - }, - /* ep6 and ep7 are also reserved (custom silicon might use them) */ - }; -@@ -1679,9 +1680,7 @@ - if (!res) - return -ENXIO; - -- if (!request_mem_region(res->start, -- res->end - res->start + 1, -- driver_name)) { -+ if (!request_mem_region(res->start, res->end - res->start + 1, driver_name)) { - DBG("someone's using UDC memory\n"); - return -EBUSY; - } -@@ -1807,16 +1806,13 @@ - || !wake - || at91_suspend_entering_slow_clock()) { - pullup(udc, 0); -- disable_irq_wake(udc->udp_irq); -+ wake = 0; - } else - enable_irq_wake(udc->udp_irq); - -- if (udc->board.vbus_pin > 0) { -- if (wake) -- enable_irq_wake(udc->board.vbus_pin); -- else -- disable_irq_wake(udc->board.vbus_pin); -- } -+ udc->active_suspend = wake; -+ if (udc->board.vbus_pin > 0 && wake) -+ enable_irq_wake(udc->board.vbus_pin); - return 0; - } - -@@ -1824,8 +1820,14 @@ - { - struct at91_udc *udc = platform_get_drvdata(pdev); - -+ if (udc->board.vbus_pin > 0 && udc->active_suspend) -+ disable_irq_wake(udc->board.vbus_pin); -+ - /* maybe reconnect to host; if so, clocks on */ -- pullup(udc, 1); -+ if (udc->active_suspend) -+ disable_irq_wake(udc->udp_irq); -+ else -+ pullup(udc, 1); - return 0; - } - #else -diff -urN linux-2.6.20.4-0rig/drivers/usb/gadget/at91_udc.h linux-2.6.20.4-atmel/drivers/usb/gadget/at91_udc.h ---- linux-2.6.20.4-0rig/drivers/usb/gadget/at91_udc.h 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/usb/gadget/at91_udc.h 2007-03-24 16:39:15.000000000 +0100 -@@ -105,10 +105,10 @@ - struct usb_ep ep; - struct list_head queue; - struct at91_udc *udc; -+ u8 id; - void __iomem *creg; - - unsigned maxpacket:16; -- u8 int_mask; - unsigned is_pingpong:1; - - unsigned stopped:1; -@@ -136,6 +136,7 @@ - unsigned wait_for_addr_ack:1; - unsigned wait_for_config_ack:1; - unsigned selfpowered:1; -+ unsigned active_suspend:1; - u8 addr; - struct at91_udc_data board; - struct clk *iclk, *fclk; -diff -urN linux-2.6.20.4-0rig/drivers/usb/gadget/ether.c linux-2.6.20.4-atmel/drivers/usb/gadget/ether.c ---- linux-2.6.20.4-0rig/drivers/usb/gadget/ether.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/usb/gadget/ether.c 2007-03-24 16:42:28.000000000 +0100 -@@ -266,6 +266,10 @@ - #define DEV_CONFIG_CDC - #endif - -+#ifdef CONFIG_USB_GADGET_HUSB2DEV -+#define DEV_CONFIG_CDC -+#endif -+ - - /* For CDC-incapable hardware, choose the simple cdc subset. - * Anything that talks bulk (without notable bugs) can do this. -@@ -428,7 +432,7 @@ - #define DEV_RNDIS_CONFIG_VALUE 2 /* rndis; optional */ - - static struct usb_device_descriptor --device_desc = { -+device_desc __attribute__((aligned(2))) = { - .bLength = sizeof device_desc, - .bDescriptorType = USB_DT_DEVICE, - -@@ -454,7 +458,7 @@ - }; - - static struct usb_config_descriptor --eth_config = { -+eth_config __attribute__((aligned(2))) = { - .bLength = sizeof eth_config, - .bDescriptorType = USB_DT_CONFIG, - -@@ -468,7 +472,7 @@ - - #ifdef CONFIG_USB_ETH_RNDIS - static struct usb_config_descriptor --rndis_config = { -+rndis_config __attribute__((aligned(2))) = { - .bLength = sizeof rndis_config, - .bDescriptorType = USB_DT_CONFIG, - -@@ -493,7 +497,7 @@ - - #ifdef DEV_CONFIG_CDC - static struct usb_interface_descriptor --control_intf = { -+control_intf __attribute__((aligned(2))) = { - .bLength = sizeof control_intf, - .bDescriptorType = USB_DT_INTERFACE, - -@@ -509,7 +513,7 @@ - - #ifdef CONFIG_USB_ETH_RNDIS - static const struct usb_interface_descriptor --rndis_control_intf = { -+rndis_control_intf __attribute__((aligned(2))) = { - .bLength = sizeof rndis_control_intf, - .bDescriptorType = USB_DT_INTERFACE, - -@@ -524,7 +528,7 @@ - - #if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS) - --static const struct usb_cdc_header_desc header_desc = { -+static const struct usb_cdc_header_desc __attribute__((aligned(2))) header_desc = { - .bLength = sizeof header_desc, - .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = USB_CDC_HEADER_TYPE, -@@ -566,7 +570,8 @@ - - #ifdef DEV_CONFIG_CDC - --static const struct usb_cdc_ether_desc ether_desc = { -+static const struct usb_cdc_ether_desc -+ether_desc __attribute__((aligned(2))) = { - .bLength = sizeof ether_desc, - .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = USB_CDC_ETHERNET_TYPE, -@@ -601,7 +606,7 @@ - #define STATUS_BYTECOUNT 16 /* 8 byte header + data */ - - static struct usb_endpoint_descriptor --fs_status_desc = { -+fs_status_desc __attribute__((aligned(2))) = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - -@@ -632,7 +637,7 @@ - /* ... but the "real" data interface has two bulk endpoints */ - - static const struct usb_interface_descriptor --data_intf = { -+data_intf __attribute__((aligned(2))) = { - .bLength = sizeof data_intf, - .bDescriptorType = USB_DT_INTERFACE, - -@@ -652,7 +657,7 @@ - /* RNDIS doesn't activate by changing to the "real" altsetting */ - - static const struct usb_interface_descriptor --rndis_data_intf = { -+rndis_data_intf __attribute__((aligned(2))) = { - .bLength = sizeof rndis_data_intf, - .bDescriptorType = USB_DT_INTERFACE, - -@@ -675,7 +680,7 @@ - */ - - static const struct usb_interface_descriptor --subset_data_intf = { -+subset_data_intf __attribute__((aligned(2))) = { - .bLength = sizeof subset_data_intf, - .bDescriptorType = USB_DT_INTERFACE, - -@@ -692,7 +697,7 @@ - - - static struct usb_endpoint_descriptor --fs_source_desc = { -+fs_source_desc __attribute__((aligned(2))) = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - -@@ -701,7 +706,7 @@ - }; - - static struct usb_endpoint_descriptor --fs_sink_desc = { -+fs_sink_desc __attribute__((aligned(2))) = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - -@@ -767,7 +772,7 @@ - - #if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS) - static struct usb_endpoint_descriptor --hs_status_desc = { -+hs_status_desc __attribute__((aligned(2))) = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - -@@ -778,7 +783,7 @@ - #endif /* DEV_CONFIG_CDC */ - - static struct usb_endpoint_descriptor --hs_source_desc = { -+hs_source_desc __attribute__((aligned(2))) = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - -@@ -787,7 +792,7 @@ - }; - - static struct usb_endpoint_descriptor --hs_sink_desc = { -+hs_sink_desc __attribute__((aligned(2))) = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - -@@ -796,7 +801,7 @@ - }; - - static struct usb_qualifier_descriptor --dev_qualifier = { -+dev_qualifier __attribute__((aligned(2))) = { - .bLength = sizeof dev_qualifier, - .bDescriptorType = USB_DT_DEVICE_QUALIFIER, - -diff -urN linux-2.6.20.4-0rig/drivers/usb/gadget/file_storage.c linux-2.6.20.4-atmel/drivers/usb/gadget/file_storage.c ---- linux-2.6.20.4-0rig/drivers/usb/gadget/file_storage.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/usb/gadget/file_storage.c 2007-03-24 16:42:28.000000000 +0100 -@@ -854,7 +854,7 @@ - #define CONFIG_VALUE 1 - - static struct usb_device_descriptor --device_desc = { -+device_desc __attribute__((aligned(2))) = { - .bLength = sizeof device_desc, - .bDescriptorType = USB_DT_DEVICE, - -@@ -873,7 +873,7 @@ - }; - - static struct usb_config_descriptor --config_desc = { -+config_desc __attribute__((aligned(2))) = { - .bLength = sizeof config_desc, - .bDescriptorType = USB_DT_CONFIG, - -@@ -896,7 +896,7 @@ - /* There is only one interface. */ - - static struct usb_interface_descriptor --intf_desc = { -+intf_desc __attribute__((aligned(2))) = { - .bLength = sizeof intf_desc, - .bDescriptorType = USB_DT_INTERFACE, - -@@ -911,7 +911,7 @@ - * and interrupt-in. */ - - static struct usb_endpoint_descriptor --fs_bulk_in_desc = { -+fs_bulk_in_desc __attribute__((aligned(2))) = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - -@@ -921,7 +921,7 @@ - }; - - static struct usb_endpoint_descriptor --fs_bulk_out_desc = { -+fs_bulk_out_desc __attribute__((aligned(2))) = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - -@@ -931,7 +931,7 @@ - }; - - static struct usb_endpoint_descriptor --fs_intr_in_desc = { -+fs_intr_in_desc __attribute__((aligned(2))) = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - -@@ -963,7 +963,7 @@ - * for the config descriptor. - */ - static struct usb_qualifier_descriptor --dev_qualifier = { -+dev_qualifier __attribute__((aligned(2))) = { - .bLength = sizeof dev_qualifier, - .bDescriptorType = USB_DT_DEVICE_QUALIFIER, - -@@ -974,7 +974,7 @@ - }; - - static struct usb_endpoint_descriptor --hs_bulk_in_desc = { -+hs_bulk_in_desc __attribute__((aligned(2))) = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - -@@ -984,7 +984,7 @@ - }; - - static struct usb_endpoint_descriptor --hs_bulk_out_desc = { -+hs_bulk_out_desc __attribute__((aligned(2))) = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - -@@ -995,7 +995,7 @@ - }; - - static struct usb_endpoint_descriptor --hs_intr_in_desc = { -+hs_intr_in_desc __attribute__((aligned(2))) = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - -diff -urN linux-2.6.20.4-0rig/drivers/usb/gadget/gadget_chips.h linux-2.6.20.4-atmel/drivers/usb/gadget/gadget_chips.h ---- linux-2.6.20.4-0rig/drivers/usb/gadget/gadget_chips.h 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/usb/gadget/gadget_chips.h 2007-03-24 16:42:29.000000000 +0100 -@@ -75,6 +75,12 @@ - #define gadget_is_pxa27x(g) 0 - #endif - -+#ifdef CONFIG_USB_GADGET_HUSB2DEV -+#define gadget_is_husb2dev(g) !strcmp("husb2_udc", (g)->name) -+#else -+#define gadget_is_husb2dev(g) 0 -+#endif -+ - #ifdef CONFIG_USB_GADGET_S3C2410 - #define gadget_is_s3c2410(g) !strcmp("s3c2410_udc", (g)->name) - #else -@@ -169,5 +175,7 @@ - return 0x16; - else if (gadget_is_mpc8272(gadget)) - return 0x17; -+ else if (gadget_is_husb2dev(gadget)) -+ return 0x80; - return -ENOENT; - } -diff -urN linux-2.6.20.4-0rig/drivers/usb/gadget/husb2_udc.c linux-2.6.20.4-atmel/drivers/usb/gadget/husb2_udc.c ---- linux-2.6.20.4-0rig/drivers/usb/gadget/husb2_udc.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/usb/gadget/husb2_udc.c 2007-03-24 16:42:29.000000000 +0100 -@@ -0,0 +1,1997 @@ -+/* -+ * Driver for the Atmel HUSB2device high speed USB device 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. -+ */ -+#undef DEBUG -+ -+#include <linux/clk.h> -+#include <linux/module.h> -+#include <linux/init.h> -+#include <linux/interrupt.h> -+#include <linux/device.h> -+#include <linux/dma-mapping.h> -+#include <linux/list.h> -+#include <linux/platform_device.h> -+#include <linux/usb_ch9.h> -+#include <linux/usb_gadget.h> -+#include <linux/dmapool.h> -+#include <linux/delay.h> -+ -+#include <asm/io.h> -+ -+#include "husb2_udc.h" -+ -+#define DRIVER_VERSION "0.9" -+ -+#define DMA_ADDR_INVALID (~(dma_addr_t)0) -+ -+#define FIFO_IOMEM_ID 0 -+#define CTRL_IOMEM_ID 1 -+ -+#ifdef DEBUG -+#define DBG_ERR 0x0001 /* report all error returns */ -+#define DBG_HW 0x0002 /* debug hardware initialization */ -+#define DBG_GADGET 0x0004 /* calls to/from gadget driver */ -+#define DBG_INT 0x0008 /* interrupts */ -+#define DBG_BUS 0x0010 /* report changes in bus state */ -+#define DBG_QUEUE 0x0020 /* debug request queue processing */ -+#define DBG_FIFO 0x0040 /* debug FIFO contents */ -+#define DBG_DMA 0x0080 /* debug DMA handling */ -+#define DBG_REQ 0x0100 /* print out queued request length */ -+#define DBG_ALL 0xffff -+#define DBG_NONE 0x0000 -+ -+#define DEBUG_LEVEL (DBG_ERR|DBG_REQ) -+#define DBG(level, fmt, ...) \ -+ do { \ -+ if ((level) & DEBUG_LEVEL) \ -+ printk(KERN_DEBUG "udc: " fmt, ## __VA_ARGS__); \ -+ } while (0) -+#else -+#define DBG(level, fmt...) -+#endif -+ -+static struct husb2_udc the_udc; -+ -+#ifdef CONFIG_DEBUG_FS -+#include <linux/debugfs.h> -+#include <asm/uaccess.h> -+ -+static int queue_dbg_open(struct inode *inode, struct file *file) -+{ -+ struct husb2_ep *ep = inode->i_private; -+ struct husb2_request *req, *req_copy; -+ struct list_head *queue_data; -+ -+ queue_data = kmalloc(sizeof(*queue_data), GFP_KERNEL); -+ if (!queue_data) -+ return -ENOMEM; -+ INIT_LIST_HEAD(queue_data); -+ -+ spin_lock_irq(&ep->udc->lock); -+ list_for_each_entry(req, &ep->queue, queue) { -+ req_copy = kmalloc(sizeof(*req_copy), GFP_ATOMIC); -+ if (!req_copy) -+ goto fail; -+ memcpy(req_copy, req, sizeof(*req_copy)); -+ list_add_tail(&req_copy->queue, queue_data); -+ } -+ spin_unlock_irq(&ep->udc->lock); -+ -+ file->private_data = queue_data; -+ return 0; -+ -+fail: -+ spin_unlock_irq(&ep->udc->lock); -+ list_for_each_entry_safe(req, req_copy, queue_data, queue) { -+ list_del(&req->queue); -+ kfree(req); -+ } -+ kfree(queue_data); -+ return -ENOMEM; -+} -+ -+/* -+ * bbbbbbbb llllllll IZS sssss nnnn FDL\n\0 -+ * -+ * b: buffer address -+ * l: buffer length -+ * I/i: interrupt/no interrupt -+ * Z/z: zero/no zero -+ * S/s: short ok/short not ok -+ * s: status -+ * n: nr_packets -+ * F/f: submitted/not submitted to FIFO -+ * D/d: using/not using DMA -+ * L/l: last transaction/not last transaction -+ */ -+static ssize_t queue_dbg_read(struct file *file, char __user *buf, -+ size_t nbytes, loff_t *ppos) -+{ -+ struct list_head *queue = file->private_data; -+ struct husb2_request *req, *tmp_req; -+ size_t len, remaining, actual = 0; -+ char tmpbuf[38]; -+ -+ if (!access_ok(VERIFY_WRITE, buf, nbytes)) -+ return -EFAULT; -+ -+ mutex_lock(&file->f_dentry->d_inode->i_mutex); -+ list_for_each_entry_safe(req, tmp_req, queue, queue) { -+ len = snprintf(tmpbuf, sizeof(tmpbuf), -+ "%8p %08x %c%c%c %5d %4u %c%c%c\n", -+ req->req.buf, req->req.length, -+ req->req.no_interrupt ? 'i' : 'I', -+ req->req.zero ? 'Z' : 'z', -+ req->req.short_not_ok ? 's' : 'S', -+ req->req.status, -+ req->nr_pkts, -+ req->submitted ? 'F' : 'f', -+ req->using_dma ? 'D' : 'd', -+ req->last_transaction ? 'L' : 'l'); -+ len = min(len, sizeof(tmpbuf)); -+ if (len > nbytes) -+ break; -+ -+ list_del(&req->queue); -+ kfree(req); -+ -+ remaining = __copy_to_user(buf, tmpbuf, len); -+ actual += len - remaining; -+ if (remaining) -+ break; -+ -+ nbytes -= len; -+ buf += len; -+ } -+ mutex_unlock(&file->f_dentry->d_inode->i_mutex); -+ -+ return actual; -+} -+ -+static int queue_dbg_release(struct inode *inode, struct file *file) -+{ -+ struct list_head *queue_data = file->private_data; -+ struct husb2_request *req, *tmp_req; -+ -+ list_for_each_entry_safe(req, tmp_req, queue_data, queue) { -+ list_del(&req->queue); -+ kfree(req); -+ } -+ kfree(queue_data); -+ return 0; -+} -+ -+static int regs_dbg_open(struct inode *inode, struct file *file) -+{ -+ struct husb2_udc *udc; -+ unsigned int i; -+ u32 *data; -+ int ret = -ENOMEM; -+ -+ mutex_lock(&inode->i_mutex); -+ udc = inode->i_private; -+ data = kmalloc(inode->i_size, GFP_KERNEL); -+ if (!data) -+ goto out; -+ -+ spin_lock_irq(&udc->lock); -+ for (i = 0; i < inode->i_size / 4; i++) -+ data[i] = __raw_readl(udc->regs + i * 4); -+ spin_unlock_irq(&udc->lock); -+ -+ file->private_data = data; -+ ret = 0; -+ -+out: -+ mutex_unlock(&inode->i_mutex); -+ -+ return ret; -+} -+ -+static ssize_t regs_dbg_read(struct file *file, char __user *buf, -+ size_t nbytes, loff_t *ppos) -+{ -+ struct inode *inode = file->f_dentry->d_inode; -+ int ret; -+ -+ mutex_lock(&inode->i_mutex); -+ ret = simple_read_from_buffer(buf, nbytes, ppos, -+ file->private_data, -+ file->f_dentry->d_inode->i_size); -+ mutex_unlock(&inode->i_mutex); -+ -+ return ret; -+} -+ -+static int regs_dbg_release(struct inode *inode, struct file *file) -+{ -+ kfree(file->private_data); -+ return 0; -+} -+ -+const struct file_operations queue_dbg_fops = { -+ .owner = THIS_MODULE, -+ .open = queue_dbg_open, -+ .llseek = no_llseek, -+ .read = queue_dbg_read, -+ .release = queue_dbg_release, -+}; -+ -+const struct file_operations regs_dbg_fops = { -+ .owner = THIS_MODULE, -+ .open = regs_dbg_open, -+ .llseek = generic_file_llseek, -+ .read = regs_dbg_read, -+ .release = regs_dbg_release, -+}; -+ -+static void husb2_ep_init_debugfs(struct husb2_udc *udc, -+ struct husb2_ep *ep) -+{ -+ struct dentry *ep_root; -+ -+ ep_root = debugfs_create_dir(ep_name(ep), udc->debugfs_root); -+ if (!ep_root) -+ goto err_root; -+ ep->debugfs_dir = ep_root; -+ -+ ep->debugfs_queue = debugfs_create_file("queue", 0400, ep_root, -+ ep, &queue_dbg_fops); -+ if (!ep->debugfs_queue) -+ goto err_queue; -+ -+ if (ep_can_dma(ep)) { -+ ep->debugfs_dma_status -+ = debugfs_create_u32("dma_status", 0400, ep_root, -+ &ep->last_dma_status); -+ if (!ep->debugfs_dma_status) -+ goto err_dma_status; -+ } -+ -+ return; -+ -+err_dma_status: -+ debugfs_remove(ep->debugfs_queue); -+err_queue: -+ debugfs_remove(ep_root); -+err_root: -+ dev_err(&ep->udc->pdev->dev, -+ "failed to create debugfs directory for %s\n", ep_name(ep)); -+} -+ -+static void husb2_ep_cleanup_debugfs(struct husb2_ep *ep) -+{ -+ debugfs_remove(ep->debugfs_queue); -+ debugfs_remove(ep->debugfs_dma_status); -+ debugfs_remove(ep->debugfs_dir); -+ ep->debugfs_dma_status = NULL; -+ ep->debugfs_dir = NULL; -+} -+ -+static void husb2_init_debugfs(struct husb2_udc *udc) -+{ -+ struct dentry *root, *regs; -+ struct resource *regs_resource; -+ -+ root = debugfs_create_dir(udc->gadget.name, NULL); -+ if (IS_ERR(root) || !root) -+ goto err_root; -+ udc->debugfs_root = root; -+ -+ regs = debugfs_create_file("regs", 0400, root, udc, ®s_dbg_fops); -+ if (!regs) -+ goto err_regs; -+ -+ regs_resource = platform_get_resource(udc->pdev, IORESOURCE_MEM, -+ CTRL_IOMEM_ID); -+ regs->d_inode->i_size = regs_resource->end - regs_resource->start + 1; -+ udc->debugfs_regs = regs; -+ -+ husb2_ep_init_debugfs(udc, to_husb2_ep(udc->gadget.ep0)); -+ -+ return; -+ -+err_regs: -+ debugfs_remove(root); -+err_root: -+ udc->debugfs_root = NULL; -+ dev_err(&udc->pdev->dev, "debugfs is not available\n"); -+} -+ -+static void husb2_cleanup_debugfs(struct husb2_udc *udc) -+{ -+ husb2_ep_cleanup_debugfs(to_husb2_ep(udc->gadget.ep0)); -+ debugfs_remove(udc->debugfs_regs); -+ debugfs_remove(udc->debugfs_root); -+ udc->debugfs_regs = NULL; -+ udc->debugfs_root = NULL; -+} -+#else -+static inline void husb2_ep_init_debugfs(struct husb2_udc *udc, -+ struct husb2_ep *ep) -+{ -+ -+} -+ -+static inline void husb2_ep_cleanup_debugfs(struct husb2_ep *ep) -+{ -+ -+} -+ -+static inline void husb2_init_debugfs(struct husb2_udc *udc) -+{ -+ -+} -+ -+static inline void husb2_cleanup_debugfs(struct husb2_udc *udc) -+{ -+ -+} -+#endif -+ -+static void copy_to_fifo(void __iomem *fifo, void *buf, int len) -+{ -+ unsigned long tmp; -+ -+ DBG(DBG_FIFO, "copy to FIFO (len %d):\n", len); -+ for (; len > 0; len -= 4, buf += 4, fifo += 4) { -+ tmp = *(unsigned long *)buf; -+ if (len >= 4) { -+ DBG(DBG_FIFO, " -> %08lx\n", tmp); -+ __raw_writel(tmp, fifo); -+ } else { -+ do { -+ DBG(DBG_FIFO, " -> %02lx\n", tmp >> 24); -+ __raw_writeb(tmp >> 24, fifo); -+ fifo++; -+ tmp <<= 8; -+ } while (--len); -+ break; -+ } -+ } -+} -+ -+static void copy_from_fifo(void *buf, void __iomem *fifo, int len) -+{ -+ union { -+ unsigned long *w; -+ unsigned char *b; -+ } p; -+ unsigned long tmp; -+ -+ DBG(DBG_FIFO, "copy from FIFO (len %d):\n", len); -+ for (p.w = buf; len > 0; len -= 4, p.w++, fifo += 4) { -+ if (len >= 4) { -+ tmp = __raw_readl(fifo); -+ *p.w = tmp; -+ DBG(DBG_FIFO, " -> %08lx\n", tmp); -+ } else { -+ do { -+ tmp = __raw_readb(fifo); -+ *p.b = tmp; -+ DBG(DBG_FIFO, " -> %02lx\n", tmp); -+ fifo++, p.b++; -+ } while (--len); -+ } -+ } -+} -+ -+static void next_fifo_transaction(struct husb2_ep *ep, -+ struct husb2_request *req) -+{ -+ unsigned int transaction_len; -+ -+ transaction_len = req->req.length - req->req.actual; -+ req->last_transaction = 1; -+ if (transaction_len > ep->ep.maxpacket) { -+ transaction_len = ep->ep.maxpacket; -+ req->last_transaction = 0; -+ } else if (transaction_len == ep->ep.maxpacket -+ && req->req.zero) { -+ req->last_transaction = 0; -+ } -+ DBG(DBG_QUEUE, "%s: submit_transaction, req %p (length %d)%s\n", -+ ep_name(ep), req, transaction_len, -+ req->last_transaction ? ", done" : ""); -+ -+ copy_to_fifo(ep->fifo, req->req.buf + req->req.actual, transaction_len); -+ husb2_ep_writel(ep, SET_STA, HUSB2_BIT(TX_PK_RDY)); -+ req->req.actual += transaction_len; -+} -+ -+static void submit_request(struct husb2_ep *ep, struct husb2_request *req) -+{ -+ DBG(DBG_QUEUE, "%s: submit_request: req %p (length %d)\n", -+ ep_name(ep), req, req->req.length); -+ -+ req->req.actual = 0; -+ req->submitted = 1; -+ -+ if (req->using_dma) { -+ if (req->req.length == 0) { -+ husb2_ep_writel(ep, CTL_ENB, HUSB2_BIT(TX_PK_RDY)); -+ } else { -+ husb2_ep_writel(ep, CTL_DIS, HUSB2_BIT(TX_PK_RDY)); -+ husb2_dma_writel(ep, NXT_DSC, -+ req->packet[0].desc_dma); -+ husb2_dma_writel(ep, CONTROL, HUSB2_BIT(DMA_LINK)); -+ } -+ } else { -+ next_fifo_transaction(ep, req); -+ if (req->last_transaction) -+ husb2_ep_writel(ep, CTL_ENB, HUSB2_BIT(TX_COMPLETE)); -+ else -+ husb2_ep_writel(ep, CTL_ENB, HUSB2_BIT(TX_PK_RDY)); -+ } -+} -+ -+static void submit_next_request(struct husb2_ep *ep) -+{ -+ struct husb2_request *req; -+ -+ if (list_empty(&ep->queue)) { -+ husb2_ep_writel(ep, CTL_DIS, (HUSB2_BIT(TX_PK_RDY) -+ | HUSB2_BIT(RX_BK_RDY))); -+ return; -+ } -+ -+ req = list_entry(ep->queue.next, struct husb2_request, queue); -+ if (!req->submitted) -+ submit_request(ep, req); -+} -+ -+static void send_status(struct husb2_udc *udc, struct husb2_ep *ep) -+{ -+ ep->state = STATUS_STAGE_IN; -+ husb2_ep_writel(ep, SET_STA, HUSB2_BIT(TX_PK_RDY)); -+ husb2_ep_writel(ep, CTL_ENB, HUSB2_BIT(TX_COMPLETE)); -+} -+ -+static void receive_data(struct husb2_ep *ep) -+{ -+ struct husb2_udc *udc = ep->udc; -+ struct husb2_request *req; -+ unsigned long status; -+ unsigned int bytecount, nr_busy; -+ int is_complete = 0; -+ -+ status = husb2_ep_readl(ep, STA); -+ nr_busy = HUSB2_BFEXT(BUSY_BANKS, status); -+ -+ DBG(DBG_QUEUE, "receive data: nr_busy=%u\n", nr_busy); -+ -+ while (nr_busy > 0) { -+ if (list_empty(&ep->queue)) { -+ husb2_ep_writel(ep, CTL_DIS, HUSB2_BIT(RX_BK_RDY)); -+ break; -+ } -+ req = list_entry(ep->queue.next, -+ struct husb2_request, queue); -+ -+ bytecount = HUSB2_BFEXT(BYTE_COUNT, status); -+ -+ if (status & (1 << 31)) -+ is_complete = 1; -+ if (req->req.actual + bytecount >= req->req.length) { -+ is_complete = 1; -+ bytecount = req->req.length - req->req.actual; -+ } -+ -+ copy_from_fifo(req->req.buf + req->req.actual, -+ ep->fifo, bytecount); -+ req->req.actual += bytecount; -+ -+ husb2_ep_writel(ep, CLR_STA, HUSB2_BIT(RX_BK_RDY)); -+ -+ if (is_complete) { -+ DBG(DBG_QUEUE, "%s: request done\n", ep_name(ep)); -+ req->req.status = 0; -+ list_del_init(&req->queue); -+ req->req.complete(&ep->ep, &req->req); -+ } -+ -+ status = husb2_ep_readl(ep, STA); -+ nr_busy = HUSB2_BFEXT(BUSY_BANKS, status); -+ -+ if (is_complete && ep_is_control(ep)) { -+ BUG_ON(nr_busy != 0); -+ send_status(udc, ep); -+ break; -+ } -+ } -+} -+ -+static void request_complete(struct husb2_ep *ep, -+ struct husb2_request *req, -+ int status) -+{ -+ struct husb2_udc *udc = ep->udc; -+ int i; -+ -+ BUG_ON(!list_empty(&req->queue)); -+ -+ if (req->req.status == -EINPROGRESS) -+ req->req.status = status; -+ -+ if (req->packet) { -+ for (i = 0; i < req->nr_pkts; i++) -+ dma_pool_free(udc->desc_pool, req->packet[i].desc, -+ req->packet[i].desc_dma); -+ kfree(req->packet); -+ req->packet = NULL; -+ dma_unmap_single(&udc->pdev->dev, -+ req->req.dma, req->req.length, -+ (ep_is_in(ep) -+ ? DMA_TO_DEVICE : DMA_FROM_DEVICE)); -+ req->req.dma = DMA_ADDR_INVALID; -+ } -+ -+ DBG(DBG_GADGET | DBG_REQ, -+ "%s: req %p complete: status %d, actual %u\n", -+ ep_name(ep), req, req->req.status, req->req.actual); -+ req->req.complete(&ep->ep, &req->req); -+} -+ -+static void request_complete_list(struct husb2_ep *ep, -+ struct list_head *list, -+ int status) -+{ -+ struct husb2_request *req, *tmp_req; -+ -+ list_for_each_entry_safe(req, tmp_req, list, queue) { -+ list_del_init(&req->queue); -+ request_complete(ep, req, status); -+ } -+} -+ -+static int husb2_ep_enable(struct usb_ep *_ep, -+ const struct usb_endpoint_descriptor *desc) -+{ -+ struct husb2_ep *ep = to_husb2_ep(_ep); -+ struct husb2_udc *udc = ep->udc; -+ unsigned long flags, ept_cfg, maxpacket; -+ -+ DBG(DBG_GADGET, "%s: ep_enable: desc=%p\n", ep_name(ep), desc); -+ -+ maxpacket = le16_to_cpu(desc->wMaxPacketSize); -+ -+ if (ep->index == 0 -+ || desc->bDescriptorType != USB_DT_ENDPOINT -+ || ((desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) -+ != ep->index) -+ || maxpacket == 0 -+ || maxpacket > ep->fifo_size) { -+ DBG(DBG_ERR, "ep_enable: Invalid argument"); -+ return -EINVAL; -+ } -+ -+ if (((desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) -+ == USB_ENDPOINT_XFER_ISOC) -+ && !(ep->capabilities & HUSB2_EP_CAP_ISOC)) { -+ DBG(DBG_ERR, "ep_enable: %s is not isoc capable\n", -+ ep_name(ep)); -+ return -EINVAL; -+ } -+ -+ if (maxpacket <= 8) -+ ept_cfg = HUSB2_BF(EPT_SIZE, HUSB2_EPT_SIZE_8); -+ else -+ /* LSB is bit 1, not 0 */ -+ ept_cfg = HUSB2_BF(EPT_SIZE, fls(maxpacket - 1) - 3); -+ DBG(DBG_HW, "%s: EPT_SIZE = %lu (maxpacket = %lu)\n", -+ ep_name(ep), ept_cfg, maxpacket); -+ -+ if ((desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) -+ ept_cfg |= HUSB2_BIT(EPT_DIR); -+ -+ switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { -+ case USB_ENDPOINT_XFER_CONTROL: -+ ept_cfg |= HUSB2_BF(EPT_TYPE, HUSB2_EPT_TYPE_CONTROL); -+ break; -+ case USB_ENDPOINT_XFER_ISOC: -+ ept_cfg |= HUSB2_BF(EPT_TYPE, HUSB2_EPT_TYPE_ISO); -+ break; -+ case USB_ENDPOINT_XFER_BULK: -+ ept_cfg |= HUSB2_BF(EPT_TYPE, HUSB2_EPT_TYPE_BULK); -+ break; -+ case USB_ENDPOINT_XFER_INT: -+ ept_cfg |= HUSB2_BF(EPT_TYPE, HUSB2_EPT_TYPE_INT); -+ break; -+ } -+ ept_cfg |= HUSB2_BF(BK_NUMBER, ep->nr_banks); -+ -+ spin_lock_irqsave(&ep->udc->lock, flags); -+ -+ if (ep->desc) { -+ spin_unlock_irqrestore(&ep->udc->lock, flags); -+ DBG(DBG_ERR, "ep%d already enabled\n", ep->index); -+ return -EBUSY; -+ } -+ -+ ep->desc = desc; -+ ep->ep.maxpacket = maxpacket; -+ -+ husb2_ep_writel(ep, CFG, ept_cfg); -+ husb2_ep_writel(ep, CTL_ENB, HUSB2_BIT(EPT_ENABLE)); -+ -+ if (ep_can_dma(ep)) { -+ husb2_writel(udc, INT_ENB, -+ (husb2_readl(udc, INT_ENB) -+ | HUSB2_BF(EPT_INT, 1 << ep->index) -+ | HUSB2_BF(DMA_INT, 1 << ep->index))); -+ husb2_ep_writel(ep, CTL_ENB, HUSB2_BIT(AUTO_VALID)); -+ } else { -+ husb2_writel(udc, INT_ENB, -+ (husb2_readl(udc, INT_ENB) -+ | HUSB2_BF(EPT_INT, 1 << ep->index))); -+ } -+ -+ spin_unlock_irqrestore(&udc->lock, flags); -+ -+ DBG(DBG_HW, "EPT_CFG%d after init: %#08lx\n", ep->index, -+ (unsigned long)husb2_ep_readl(ep, CFG)); -+ DBG(DBG_HW, "INT_ENB after init: %#08lx\n", -+ (unsigned long)husb2_readl(udc, INT_ENB)); -+ -+ husb2_ep_init_debugfs(udc, ep); -+ -+ return 0; -+} -+ -+static int husb2_ep_disable(struct usb_ep *_ep) -+{ -+ struct husb2_ep *ep = to_husb2_ep(_ep); -+ struct husb2_udc *udc = ep->udc; -+ LIST_HEAD(req_list); -+ unsigned long flags; -+ -+ DBG(DBG_GADGET, "ep_disable: %s\n", ep_name(ep)); -+ -+ husb2_ep_cleanup_debugfs(ep); -+ -+ spin_lock_irqsave(&udc->lock, flags); -+ -+ if (!ep->desc) { -+ spin_unlock_irqrestore(&udc->lock, flags); -+ DBG(DBG_ERR, "ep_disable: %s not enabled\n", -+ ep_name(ep)); -+ return -EINVAL; -+ } -+ ep->desc = NULL; -+ -+ list_splice_init(&ep->queue, &req_list); -+ if (ep_can_dma(ep)) { -+ husb2_dma_writel(ep, CONTROL, 0); -+ husb2_dma_writel(ep, ADDRESS, 0); -+ husb2_dma_readl(ep, STATUS); -+ } -+ husb2_ep_writel(ep, CTL_DIS, HUSB2_BIT(EPT_ENABLE)); -+ husb2_writel(udc, INT_ENB, (husb2_readl(udc, INT_ENB) -+ & ~HUSB2_BF(EPT_INT, 1 << ep->index))); -+ -+ spin_unlock_irqrestore(&udc->lock, flags); -+ -+ request_complete_list(ep, &req_list, -ESHUTDOWN); -+ -+ return 0; -+} -+ -+static struct usb_request * -+husb2_ep_alloc_request(struct usb_ep *_ep, unsigned gfp_flags) -+{ -+ struct husb2_request *req; -+ -+ DBG(DBG_GADGET, "ep_alloc_request: %p, 0x%x\n", _ep, gfp_flags); -+ -+ req = kzalloc(sizeof(*req), gfp_flags); -+ if (!req) -+ return NULL; -+ -+ INIT_LIST_HEAD(&req->queue); -+ req->req.dma = DMA_ADDR_INVALID; -+ -+ return &req->req; -+} -+ -+static void -+husb2_ep_free_request(struct usb_ep *_ep, struct usb_request *_req) -+{ -+ struct husb2_request *req = to_husb2_req(_req); -+ -+ DBG(DBG_GADGET, "ep_free_request: %p, %p\n", _ep, _req); -+ -+ kfree(req); -+} -+ -+static void *husb2_ep_alloc_buffer(struct usb_ep *_ep, unsigned bytes, -+ dma_addr_t *dma, unsigned gfp_flags) -+{ -+ struct husb2_ep *ep = to_husb2_ep(_ep); -+ void *buf; -+ -+ /* -+ * We depend on kmalloc() returning cache-aligned memory. This -+ * is normally guaranteed as long as we allocate a whole -+ * cacheline or more. -+ * -+ * When CONFIG_DEBUG_SLAB is enabled, however, the slab -+ * allocator inserts red zones and ownership information, -+ * causing the slab objects to be misaligned. -+ * -+ * One alternative would be to use dma_alloc_coherent, but -+ * that would make us unable to allocate anything less than a -+ * page at a time. -+ */ -+#ifdef CONFIG_DEBUG_SLAB -+# error The HUSB2 UDC driver breaks with SLAB debugging enabled -+#endif -+ -+ if (bytes < L1_CACHE_BYTES) -+ bytes = L1_CACHE_BYTES; -+ -+ buf = kmalloc(bytes, gfp_flags); -+ -+ /* -+ * Seems like we have to map the buffer any chance we get. -+ * ether.c wants us to initialize the dma member of a -+ * different request than the one receiving the buffer, so one -+ * never knows... -+ * -+ * Ah, screw it. The ether driver is probably wrong, and this -+ * is not the right place to do the mapping. The driver -+ * shouldn't mess with our DMA mappings anyway. -+ */ -+ *dma = DMA_ADDR_INVALID; -+ -+ DBG(DBG_GADGET, "ep_alloc_buffer: %s, %u, 0x%x -> %p\n", -+ ep_name(ep), bytes, gfp_flags, buf); -+ -+ return buf; -+} -+ -+static void husb2_ep_free_buffer(struct usb_ep *_ep, void *buf, -+ dma_addr_t dma, unsigned bytes) -+{ -+ DBG(DBG_GADGET, "ep_free_buffer: %s, buf %p (size %u)\n", -+ _ep->name, buf, bytes); -+ kfree(buf); -+} -+ -+static int queue_dma(struct husb2_udc *udc, struct husb2_ep *ep, -+ struct husb2_request *req, unsigned int direction, -+ gfp_t gfp_flags) -+{ -+ struct husb2_packet *pkt, *prev_pkt; -+ unsigned int pkt_size, nr_pkts, i; -+ unsigned int residue; -+ dma_addr_t addr; -+ unsigned long flags; -+ u32 ctrl; -+ -+ req->using_dma = 1; -+ -+ if (req->req.length == 0) { -+ if (!req->req.zero) -+ return -EINVAL; -+ req->send_zlp = 1; -+ -+ spin_lock_irqsave(&udc->lock, flags); -+ husb2_ep_writel(ep, CTL_ENB, HUSB2_BIT(TX_PK_RDY)); -+ list_add_tail(&req->queue, &ep->queue); -+ spin_unlock_irqrestore(&udc->lock, flags); -+ -+ return 0; -+ } -+ -+ if (req->req.dma == DMA_ADDR_INVALID) -+ req->req.dma = dma_map_single(&udc->pdev->dev, -+ req->req.buf, -+ req->req.length, -+ direction); -+ else -+ dma_sync_single_for_device(&udc->pdev->dev, -+ req->req.dma, -+ req->req.length, -+ direction); -+ -+ pkt_size = ep->ep.maxpacket; -+ nr_pkts = req->req.length / pkt_size; -+ residue = req->req.length % pkt_size; -+ if (residue != 0) -+ nr_pkts++; -+ else if (req->req.zero && ep_is_in(ep)) -+ /* ensure last packet is short */ -+ req->send_zlp = 1; -+ -+ req->nr_pkts = nr_pkts; -+ -+ req->packet = kzalloc(sizeof(*req->packet) * nr_pkts, gfp_flags); -+ if (!req->packet) -+ goto out_of_memory; -+ -+ addr = req->req.dma; -+ ctrl = (HUSB2_BF(DMA_BUF_LEN, pkt_size) -+ | HUSB2_BIT(DMA_CH_EN) | HUSB2_BIT(DMA_LINK) -+ | HUSB2_BIT(DMA_END_TR_EN) | HUSB2_BIT(DMA_END_TR_IE)); -+ prev_pkt = NULL; -+ pkt = NULL; -+ DBG(DBG_DMA, "DMA descriptors:\n"); -+ for (i = 0; i < nr_pkts; i++) { -+ pkt = &req->packet[i]; -+ pkt->desc = dma_pool_alloc(udc->desc_pool, gfp_flags, -+ &pkt->desc_dma); -+ if (!pkt->desc) -+ goto out_of_memory; -+ -+ if (prev_pkt) { -+ prev_pkt->desc->next = pkt->desc_dma; -+ DBG(DBG_DMA, "[%d] n%08x a%08x c%08x\n", -+ i - 1, prev_pkt->desc->next, prev_pkt->desc->addr, -+ prev_pkt->desc->ctrl); -+ } -+ prev_pkt = pkt; -+ -+ pkt->desc->addr = addr; -+ pkt->desc->ctrl = ctrl; -+ addr += pkt_size; -+ } -+ -+ /* special care is needed for the last packet... */ -+ ctrl = (HUSB2_BIT(DMA_CH_EN) -+ | HUSB2_BIT(DMA_END_TR_EN) | HUSB2_BIT(DMA_END_TR_IE) -+ | HUSB2_BIT(DMA_END_BUF_IE)); -+ if (ep_is_in(ep)) -+ ctrl |= HUSB2_BIT(DMA_END_BUF_EN); -+ if (req->req.zero || residue) -+ ctrl |= HUSB2_BF(DMA_BUF_LEN, residue); -+ else -+ ctrl |= HUSB2_BF(DMA_BUF_LEN, pkt_size); -+ pkt->desc->ctrl = ctrl; -+ -+ DBG(DBG_DMA, "[%d] n%08x a%08x c%08x\n", -+ i - 1, prev_pkt->desc->next, prev_pkt->desc->addr, -+ prev_pkt->desc->ctrl); -+ -+ /* Add this request to the queue and try to chain the DMA descriptors */ -+ spin_lock_irqsave(&udc->lock, flags); -+ -+ /* If the DMA controller is idle, start it */ -+ if (list_empty(&ep->queue)) { -+ husb2_dma_writel(ep, NXT_DSC, req->packet[0].desc_dma); -+ husb2_dma_writel(ep, CONTROL, HUSB2_BIT(DMA_LINK)); -+ } -+ -+ list_add_tail(&req->queue, &ep->queue); -+ -+ spin_unlock_irqrestore(&udc->lock, flags); -+ -+ return 0; -+ -+out_of_memory: -+ printk(KERN_ERR "ERROR: Could not allocate DMA memory for endpoint %s\n", -+ ep_name(ep)); -+ if (req->packet) { -+ for (i = 0; i < nr_pkts; i++) -+ if (req->packet[i].desc) -+ dma_pool_free(udc->desc_pool, -+ req->packet[i].desc, -+ req->packet[i].desc_dma); -+ kfree(req->packet); -+ } -+ -+ return -ENOMEM; -+} -+ -+static int husb2_ep_queue(struct usb_ep *_ep, struct usb_request *_req, -+ gfp_t gfp_flags) -+{ -+ struct husb2_request *req = to_husb2_req(_req); -+ struct husb2_ep *ep = to_husb2_ep(_ep); -+ struct husb2_udc *udc = ep->udc; -+ unsigned long flags; -+ int direction_in = 0; -+ -+ DBG(DBG_GADGET | DBG_QUEUE | DBG_REQ, -+ "%s: queue req %p, len %u\n", ep_name(ep), req, _req->length); -+ -+ if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) -+ return -ESHUTDOWN; -+ if (!ep->desc) -+ return -ENODEV; -+ -+ req->nr_pkts = 0; -+ req->submitted = 0; -+ req->using_dma = 0; -+ req->last_transaction = 0; -+ req->send_zlp = 0; -+ -+ BUG_ON(req->packet); -+ -+ if (ep_is_in(ep) -+ || (ep_is_control(ep) && (ep->state == DATA_STAGE_IN -+ || ep->state == STATUS_STAGE_IN))) -+ direction_in = 1; -+ -+ _req->status = -EINPROGRESS; -+ _req->actual = 0; -+ -+ if (ep_can_dma(ep)) { -+ return queue_dma(udc, ep, req, (direction_in -+ ? DMA_TO_DEVICE -+ : DMA_FROM_DEVICE), -+ gfp_flags); -+ } else { -+ spin_lock_irqsave(&udc->lock, flags); -+ list_add_tail(&req->queue, &ep->queue); -+ -+ if (direction_in) -+ husb2_ep_writel(ep, CTL_ENB, HUSB2_BIT(TX_PK_RDY)); -+ else -+ husb2_ep_writel(ep, CTL_ENB, HUSB2_BIT(RX_BK_RDY)); -+ spin_unlock_irqrestore(&udc->lock, flags); -+ } -+ -+ return 0; -+} -+ -+static void husb2_update_req(struct husb2_ep *ep, struct husb2_request *req, -+ u32 status) -+{ -+ struct husb2_dma_desc *desc; -+ dma_addr_t from; -+ dma_addr_t addr; -+ size_t size; -+ unsigned int i; -+ -+ addr = husb2_dma_readl(ep, ADDRESS); -+ req->req.actual = 0; -+ -+ for (i = 0; i < req->nr_pkts; i++) { -+ desc = req->packet[i].desc; -+ from = desc->addr; -+ size = HUSB2_BFEXT(DMA_BUF_LEN, desc->ctrl); -+ -+ req->req.actual += size; -+ -+ DBG(DBG_DMA, " from=%#08x, size=%#zx\n", from, size); -+ -+ if (from <= addr && (from + size) >= addr) -+ break; -+ } -+ -+ req->req.actual -= HUSB2_BFEXT(DMA_BUF_LEN, status); -+} -+ -+static int stop_dma(struct husb2_ep *ep, u32 *pstatus) -+{ -+ unsigned int timeout; -+ u32 status; -+ -+ /* -+ * Stop the DMA controller. When writing both CH_EN -+ * and LINK to 0, the other bits are not affected. -+ */ -+ husb2_dma_writel(ep, CONTROL, 0); -+ -+ /* Wait for the FIFO to empty */ -+ for (timeout = 40; timeout; --timeout) { -+ status = husb2_dma_readl(ep, STATUS); -+ if (!(status & HUSB2_BIT(DMA_CH_EN))) -+ break; -+ udelay(1); -+ } -+ -+ if (pstatus) -+ *pstatus = status; -+ -+ if (timeout == 0) { -+ dev_err(&ep->udc->pdev->dev, -+ "%s: timed out waiting for DMA FIFO to empty\n", -+ ep_name(ep)); -+ return -ETIMEDOUT; -+ } -+ -+ return 0; -+} -+ -+static int husb2_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) -+{ -+ struct husb2_ep *ep = to_husb2_ep(_ep); -+ struct husb2_udc *udc = ep->udc; -+ struct husb2_request *req = to_husb2_req(_req); -+ unsigned long flags; -+ u32 status; -+ -+ DBG(DBG_GADGET | DBG_QUEUE, "ep_dequeue: %s, req %p\n", ep_name(ep), req); -+ -+ spin_lock_irqsave(&udc->lock, flags); -+ -+ if (req->using_dma) { -+ /* -+ * If this request is currently being transferred, -+ * stop the DMA controller and reset the FIFO. -+ */ -+ if (ep->queue.next == &req->queue) { -+ status = husb2_dma_readl(ep, STATUS); -+ if (status & HUSB2_BIT(DMA_CH_EN)) -+ stop_dma(ep, &status); -+ -+#ifdef CONFIG_DEBUG_FS -+ ep->last_dma_status = status; -+#endif -+ -+ husb2_writel(udc, EPT_RST, -+ 1 << ep_index(ep)); -+ -+ husb2_update_req(ep, req, status); -+ } -+ } -+ -+ /* -+ * Errors should stop the queue from advancing until the -+ * completion function returns. -+ */ -+ list_del_init(&req->queue); -+ spin_unlock_irqrestore(&udc->lock, flags); -+ -+ request_complete(ep, req, -ECONNRESET); -+ -+ /* Process the next request if any */ -+ spin_lock_irqsave(&udc->lock, flags); -+ submit_next_request(ep); -+ spin_unlock_irqrestore(&udc->lock, flags); -+ -+ return 0; -+} -+ -+static int husb2_ep_set_halt(struct usb_ep *_ep, int value) -+{ -+ struct husb2_ep *ep = to_husb2_ep(_ep); -+ struct husb2_udc *udc = ep->udc; -+ unsigned long flags; -+ int ret = 0; -+ -+ DBG(DBG_GADGET, "endpoint %s: %s HALT\n", ep_name(ep), -+ value ? "set" : "clear"); -+ -+ if (!ep->desc) { -+ DBG(DBG_ERR, "Attempted to halt uninitialized ep %s\n", -+ ep_name(ep)); -+ return -ENODEV; -+ } -+ if (ep_is_isochronous(ep)) { -+ DBG(DBG_ERR, "Attempted to halt isochronous ep %s\n", -+ ep_name(ep)); -+ return -ENOTTY; -+ } -+ -+ spin_lock_irqsave(&udc->lock, flags); -+ -+ /* -+ * We can't halt IN endpoints while there are still data to be -+ * transferred -+ */ -+ if (!list_empty(&ep->queue) -+ || ((value && ep_is_in(ep) -+ && (husb2_ep_readl(ep, STA) -+ & HUSB2_BF(BUSY_BANKS, -1L))))) { -+ ret = -EAGAIN; -+ } else { -+ if (value) -+ husb2_ep_writel(ep, SET_STA, HUSB2_BIT(FORCE_STALL)); -+ else -+ husb2_ep_writel(ep, CLR_STA, (HUSB2_BIT(FORCE_STALL) -+ | HUSB2_BIT(TOGGLE_SEQ))); -+ husb2_ep_readl(ep, STA); -+ } -+ -+ spin_unlock_irqrestore(&udc->lock, flags); -+ -+ return ret; -+} -+ -+static int husb2_ep_fifo_status(struct usb_ep *_ep) -+{ -+ struct husb2_ep *ep = to_husb2_ep(_ep); -+ -+ return HUSB2_BFEXT(BYTE_COUNT, husb2_ep_readl(ep, STA)); -+} -+ -+static void husb2_ep_fifo_flush(struct usb_ep *_ep) -+{ -+ struct husb2_ep *ep = to_husb2_ep(_ep); -+ struct husb2_udc *udc = ep->udc; -+ -+ husb2_writel(udc, EPT_RST, 1 << ep->index); -+} -+ -+struct usb_ep_ops husb2_ep_ops = { -+ .enable = husb2_ep_enable, -+ .disable = husb2_ep_disable, -+ .alloc_request = husb2_ep_alloc_request, -+ .free_request = husb2_ep_free_request, -+ .alloc_buffer = husb2_ep_alloc_buffer, -+ .free_buffer = husb2_ep_free_buffer, -+ .queue = husb2_ep_queue, -+ .dequeue = husb2_ep_dequeue, -+ .set_halt = husb2_ep_set_halt, -+ .fifo_status = husb2_ep_fifo_status, -+ .fifo_flush = husb2_ep_fifo_flush, -+}; -+ -+static int husb2_udc_get_frame(struct usb_gadget *gadget) -+{ -+ struct husb2_udc *udc = to_husb2_udc(gadget); -+ -+ return HUSB2_BFEXT(FRAME_NUMBER, husb2_readl(udc, FNUM)); -+} -+ -+struct usb_gadget_ops husb2_udc_ops = { -+ .get_frame = husb2_udc_get_frame, -+}; -+ -+#define EP(nam, type, idx, caps) { \ -+ .ep = { \ -+ .ops = &husb2_ep_ops, \ -+ .name = nam, \ -+ .maxpacket = type##_FIFO_SIZE, \ -+ }, \ -+ .udc = &the_udc, \ -+ .queue = LIST_HEAD_INIT(husb2_ep[idx].queue), \ -+ .fifo_size = type##_FIFO_SIZE, \ -+ .nr_banks = type##_NR_BANKS, \ -+ .index = idx, \ -+ .capabilities = caps, \ -+} -+ -+static struct husb2_ep husb2_ep[] = { -+ EP("ep0", EP0, 0, 0), -+ EP("ep1in-bulk", BULK, 1, HUSB2_EP_CAP_DMA), -+ EP("ep2out-bulk", BULK, 2, HUSB2_EP_CAP_DMA), -+ EP("ep3in-iso", ISO, 3, HUSB2_EP_CAP_DMA | HUSB2_EP_CAP_ISOC), -+ EP("ep4out-iso", ISO, 4, HUSB2_EP_CAP_DMA | HUSB2_EP_CAP_ISOC), -+ EP("ep5in-int", INT, 5, HUSB2_EP_CAP_DMA), -+ EP("ep6out-int", INT, 6, HUSB2_EP_CAP_DMA), -+}; -+#undef EP -+ -+static struct usb_endpoint_descriptor husb2_ep0_desc = { -+ .bLength = USB_DT_ENDPOINT_SIZE, -+ .bDescriptorType = USB_DT_ENDPOINT, -+ .bEndpointAddress = 0, -+ .bmAttributes = USB_ENDPOINT_XFER_CONTROL, -+ .wMaxPacketSize = __constant_cpu_to_le16(64), -+ /* FIXME: I have no idea what to put here */ -+ .bInterval = 1, -+}; -+ -+static void nop_release(struct device *dev) -+{ -+ -+} -+ -+static struct husb2_udc the_udc = { -+ .gadget = { -+ .ops = &husb2_udc_ops, -+ .ep0 = &husb2_ep[0].ep, -+ .ep_list = LIST_HEAD_INIT(the_udc.gadget.ep_list), -+ .is_dualspeed = 1, -+ .name = "husb2_udc", -+ .dev = { -+ .bus_id = "gadget", -+ .release = nop_release, -+ }, -+ }, -+ -+ .lock = SPIN_LOCK_UNLOCKED, -+}; -+ -+static void udc_enable(struct husb2_udc *udc) -+{ -+ struct husb2_ep *ep0 = &husb2_ep[0]; -+ -+ /* Enable the controller */ -+ husb2_writel(udc, CTRL, HUSB2_BIT(EN_HUSB2)); -+ -+ /* Reset all endpoints and enable basic interrupts */ -+ husb2_writel(udc, EPT_RST, ~0UL); -+ husb2_writel(udc, INT_ENB, (HUSB2_BIT(DET_SUSPEND) -+ | HUSB2_BIT(END_OF_RESET) -+ | HUSB2_BIT(END_OF_RESUME))); -+ -+ /* Configure endpoint 0 */ -+ ep0->desc = &husb2_ep0_desc; -+ -+ husb2_writel(udc, EPT_RST, 1 << 0); -+ husb2_ep_writel(ep0, CTL_ENB, HUSB2_BIT(EPT_ENABLE)); -+ husb2_ep_writel(ep0, CFG, (HUSB2_BF(EPT_SIZE, EP0_EPT_SIZE) -+ | HUSB2_BF(EPT_TYPE, HUSB2_EPT_TYPE_CONTROL) -+ | HUSB2_BF(BK_NUMBER, HUSB2_BK_NUMBER_ONE))); -+ -+ husb2_ep_writel(ep0, CTL_ENB, HUSB2_BIT(RX_SETUP)); -+ husb2_writel(udc, INT_ENB, (husb2_readl(udc, INT_ENB) -+ | HUSB2_BF(EPT_INT, 1))); -+ -+ if (!(husb2_ep_readl(ep0, CFG) & HUSB2_BIT(EPT_MAPPED))) -+ dev_warn(&udc->pdev->dev, -+ "WARNING: EP0 configuration is invalid!\n"); -+} -+ -+static void udc_disable(struct husb2_udc *udc) -+{ -+ udc->gadget.speed = USB_SPEED_UNKNOWN; -+ -+ husb2_writel(udc, CTRL, 0); -+} -+ -+/* -+ * Called with interrupts disabled and udc->lock held. -+ */ -+static void reset_all_endpoints(struct husb2_udc *udc) -+{ -+ struct husb2_ep *ep; -+ struct husb2_request *req, *tmp_req; -+ -+ husb2_writel(udc, EPT_RST, ~0UL); -+ -+ ep = to_husb2_ep(udc->gadget.ep0); -+ list_for_each_entry_safe(req, tmp_req, &ep->queue, queue) { -+ list_del_init(&req->queue); -+ request_complete(ep, req, -ECONNRESET); -+ } -+ BUG_ON(!list_empty(&ep->queue)); -+ -+ list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) { -+ if (ep->desc) -+ husb2_ep_disable(&ep->ep); -+ } -+} -+ -+static struct husb2_ep *get_ep_by_addr(struct husb2_udc *udc, u16 wIndex) -+{ -+ struct husb2_ep *ep; -+ -+ if ((wIndex & USB_ENDPOINT_NUMBER_MASK) == 0) -+ return to_husb2_ep(udc->gadget.ep0); -+ -+ list_for_each_entry (ep, &udc->gadget.ep_list, ep.ep_list) { -+ u8 bEndpointAddress; -+ -+ if (!ep->desc) -+ continue; -+ bEndpointAddress = ep->desc->bEndpointAddress; -+ if ((wIndex ^ bEndpointAddress) & USB_DIR_IN) -+ continue; -+ if ((wIndex & USB_ENDPOINT_NUMBER_MASK) -+ == (bEndpointAddress & USB_ENDPOINT_NUMBER_MASK)) -+ return ep; -+ } -+ -+ return NULL; -+} -+ -+/* Called with interrupts disabled and udc->lock held */ -+static inline void set_protocol_stall(struct husb2_udc *udc, -+ struct husb2_ep *ep) -+{ -+ husb2_ep_writel(ep, SET_STA, HUSB2_BIT(FORCE_STALL)); -+ ep->state = WAIT_FOR_SETUP; -+} -+ -+static inline int is_stalled(struct husb2_udc *udc, struct husb2_ep *ep) -+{ -+ if (husb2_ep_readl(ep, STA) & HUSB2_BIT(FORCE_STALL)) -+ return 1; -+ return 0; -+} -+ -+static inline void set_address(struct husb2_udc *udc, unsigned int addr) -+{ -+ u32 regval; -+ -+ DBG(DBG_BUS, "setting address %u...\n", addr); -+ regval = husb2_readl(udc, CTRL); -+ regval = HUSB2_BFINS(DEV_ADDR, addr, regval); -+ husb2_writel(udc, CTRL, regval); -+} -+ -+static int handle_ep0_setup(struct husb2_udc *udc, struct husb2_ep *ep, -+ struct usb_ctrlrequest *crq) -+{ -+ switch (crq->bRequest) { -+ case USB_REQ_GET_STATUS: { -+ u16 status; -+ -+ if (crq->bRequestType == (USB_DIR_IN | USB_RECIP_DEVICE)) { -+ /* Self-powered, no remote wakeup */ -+ status = __constant_cpu_to_le16(1 << 0); -+ } else if (crq->bRequestType -+ == (USB_DIR_IN | USB_RECIP_INTERFACE)) { -+ status = __constant_cpu_to_le16(0); -+ } else if (crq->bRequestType -+ == (USB_DIR_IN | USB_RECIP_ENDPOINT)) { -+ struct husb2_ep *target; -+ -+ target = get_ep_by_addr(udc, le16_to_cpu(crq->wIndex)); -+ if (!target) -+ goto stall; -+ -+ status = 0; -+ if (is_stalled(udc, target)) -+ status |= __constant_cpu_to_le16(1); -+ } else { -+ goto delegate; -+ } -+ -+ /* Write directly to the FIFO. No queueing is done. */ -+ if(crq->wLength != __constant_cpu_to_le16(sizeof(status))) -+ goto stall; -+ ep->state = DATA_STAGE_IN; -+ __raw_writew(status, ep->fifo); -+ husb2_ep_writel(ep, SET_STA, HUSB2_BIT(TX_PK_RDY)); -+ break; -+ } -+ -+ case USB_REQ_CLEAR_FEATURE: { -+ if (crq->bRequestType == USB_RECIP_DEVICE) { -+ /* We don't support TEST_MODE */ -+ goto stall; -+ } else if (crq->bRequestType == USB_RECIP_ENDPOINT) { -+ struct husb2_ep *target; -+ -+ if (crq->wValue != __constant_cpu_to_le16(USB_ENDPOINT_HALT) -+ || crq->wLength != __constant_cpu_to_le16(0)) -+ goto stall; -+ target = get_ep_by_addr(udc, le16_to_cpu(crq->wIndex)); -+ if (!target) -+ goto stall; -+ -+ husb2_ep_writel(target, CLR_STA, (HUSB2_BIT(FORCE_STALL) -+ | HUSB2_BIT(TOGGLE_SEQ))); -+ } else { -+ goto delegate; -+ } -+ -+ send_status(udc, ep); -+ break; -+ } -+ -+ case USB_REQ_SET_FEATURE: { -+ if (crq->bRequestType == USB_RECIP_DEVICE) { -+ /* We don't support TEST_MODE */ -+ goto stall; -+ } else if (crq->bRequestType == USB_RECIP_ENDPOINT) { -+ struct husb2_ep *target; -+ -+ if (crq->wValue != __constant_cpu_to_le16(USB_ENDPOINT_HALT) -+ || crq->wLength != __constant_cpu_to_le16(0)) -+ goto stall; -+ -+ target = get_ep_by_addr(udc, le16_to_cpu(crq->wIndex)); -+ if (!target) -+ goto stall; -+ -+ husb2_ep_writel(target, SET_STA, HUSB2_BIT(FORCE_STALL)); -+ } else -+ goto delegate; -+ -+ send_status(udc, ep); -+ break; -+ } -+ -+ case USB_REQ_SET_ADDRESS: -+ if (crq->bRequestType != (USB_DIR_OUT | USB_RECIP_DEVICE)) -+ goto delegate; -+ -+ set_address(udc, le16_to_cpu(crq->wValue)); -+ send_status(udc, ep); -+ ep->state = STATUS_STAGE_ADDR; -+ break; -+ -+ default: -+ delegate: -+ return udc->driver->setup(&udc->gadget, crq); -+ } -+ -+ return 0; -+ -+stall: -+ printk(KERN_ERR -+ "udc: %s: Invalid setup request: %02x.%02x v%04x i%04x l%d, " -+ "halting endpoint...\n", -+ ep_name(ep), crq->bRequestType, crq->bRequest, -+ le16_to_cpu(crq->wValue), le16_to_cpu(crq->wIndex), -+ le16_to_cpu(crq->wLength)); -+ set_protocol_stall(udc, ep); -+ return -1; -+} -+ -+static void husb2_control_irq(struct husb2_udc *udc, struct husb2_ep *ep) -+{ -+ struct husb2_request *req; -+ u32 epstatus; -+ u32 epctrl; -+ -+restart: -+ epstatus = husb2_ep_readl(ep, STA); -+ epctrl = husb2_ep_readl(ep, CTL); -+ -+ DBG(DBG_INT, "%s: interrupt, status: 0x%08x\n", -+ ep_name(ep), epstatus); -+ -+ req = NULL; -+ if (!list_empty(&ep->queue)) -+ req = list_entry(ep->queue.next, -+ struct husb2_request, queue); -+ -+ if ((epctrl & HUSB2_BIT(TX_PK_RDY)) -+ && !(epstatus & HUSB2_BIT(TX_PK_RDY))) { -+ DBG(DBG_BUS, "tx pk rdy: %d\n", ep->state); -+ -+ if (req->submitted) -+ next_fifo_transaction(ep, req); -+ else -+ submit_request(ep, req); -+ -+ if (req->last_transaction) { -+ husb2_ep_writel(ep, CTL_DIS, HUSB2_BIT(TX_PK_RDY)); -+ husb2_ep_writel(ep, CTL_ENB, HUSB2_BIT(TX_COMPLETE)); -+ } -+ goto restart; -+ } -+ if ((epstatus & epctrl) & HUSB2_BIT(TX_COMPLETE)) { -+ husb2_ep_writel(ep, CLR_STA, HUSB2_BIT(TX_COMPLETE)); -+ DBG(DBG_BUS, "txc: %d\n", ep->state); -+ -+ switch (ep->state) { -+ case DATA_STAGE_IN: -+ husb2_ep_writel(ep, CTL_ENB, HUSB2_BIT(RX_BK_RDY)); -+ husb2_ep_writel(ep, CTL_DIS, -+ HUSB2_BIT(TX_COMPLETE)); -+ ep->state = STATUS_STAGE_OUT; -+ break; -+ case STATUS_STAGE_ADDR: -+ /* Activate our new address */ -+ husb2_writel(udc, CTRL, (husb2_readl(udc, CTRL) -+ | HUSB2_BIT(FADDR_EN))); -+ husb2_ep_writel(ep, CTL_DIS, -+ HUSB2_BIT(TX_COMPLETE)); -+ ep->state = WAIT_FOR_SETUP; -+ break; -+ case STATUS_STAGE_IN: -+ if (req) { -+ list_del_init(&req->queue); -+ request_complete(ep, req, 0); -+ submit_next_request(ep); -+ } -+ BUG_ON(!list_empty(&ep->queue)); -+ husb2_ep_writel(ep, CTL_DIS, -+ HUSB2_BIT(TX_COMPLETE)); -+ ep->state = WAIT_FOR_SETUP; -+ break; -+ default: -+ printk(KERN_ERR -+ "udc: %s: TXCOMP: Invalid endpoint state %d, " -+ "halting endpoint...\n", -+ ep_name(ep), ep->state); -+ set_protocol_stall(udc, ep); -+ break; -+ } -+ -+ goto restart; -+ } -+ if ((epstatus & epctrl) & HUSB2_BIT(RX_BK_RDY)) { -+ DBG(DBG_BUS, "rxc: %d\n", ep->state); -+ -+ switch (ep->state) { -+ case STATUS_STAGE_OUT: -+ husb2_ep_writel(ep, CLR_STA, HUSB2_BIT(RX_BK_RDY)); -+ -+ if (req) { -+ list_del_init(&req->queue); -+ request_complete(ep, req, 0); -+ } -+ husb2_ep_writel(ep, CTL_DIS, HUSB2_BIT(RX_BK_RDY)); -+ ep->state = WAIT_FOR_SETUP; -+ break; -+ -+ case DATA_STAGE_OUT: -+ receive_data(ep); -+ break; -+ -+ default: -+ husb2_ep_writel(ep, CLR_STA, HUSB2_BIT(RX_BK_RDY)); -+ set_protocol_stall(udc, ep); -+ printk(KERN_ERR -+ "udc: %s: RXRDY: Invalid endpoint state %d, " -+ "halting endpoint...\n", -+ ep_name(ep), ep->state); -+ break; -+ } -+ -+ goto restart; -+ } -+ if (epstatus & HUSB2_BIT(RX_SETUP)) { -+ union { -+ struct usb_ctrlrequest crq; -+ unsigned long data[2]; -+ } crq; -+ unsigned int pkt_len; -+ int ret; -+ -+ if (ep->state != WAIT_FOR_SETUP) { -+ /* -+ * Didn't expect a SETUP packet at this -+ * point. Clean up any pending requests (which -+ * may be successful). -+ */ -+ int status = -EPROTO; -+ -+ /* -+ * RXRDY is dropped when SETUP packets arrive. -+ * Just pretend we received the status packet. -+ */ -+ if (ep->state == STATUS_STAGE_OUT) -+ status = 0; -+ -+ if (req) { -+ list_del_init(&req->queue); -+ request_complete(ep, req, status); -+ } -+ BUG_ON(!list_empty(&ep->queue)); -+ } -+ -+ pkt_len = HUSB2_BFEXT(BYTE_COUNT, husb2_ep_readl(ep, STA)); -+ DBG(DBG_HW, "Packet length: %u\n", pkt_len); -+ BUG_ON(pkt_len != sizeof(crq)); -+ -+ DBG(DBG_FIFO, "Copying ctrl request from 0x%p:\n", ep->fifo); -+ copy_from_fifo(crq.data, ep->fifo, sizeof(crq)); -+ -+ /* Free up one bank in the FIFO so that we can -+ * generate or receive a reply right away. */ -+ husb2_ep_writel(ep, CLR_STA, HUSB2_BIT(RX_SETUP)); -+ -+ /* printk(KERN_DEBUG "setup: %d: %02x.%02x\n", -+ ep->state, crq.crq.bRequestType, -+ crq.crq.bRequest); */ -+ -+ if (crq.crq.bRequestType & USB_DIR_IN) { -+ /* -+ * The USB 2.0 spec states that "if wLength is -+ * zero, there is no data transfer phase." -+ * However, testusb #14 seems to actually -+ * expect a data phase even if wLength = 0... -+ */ -+ ep->state = DATA_STAGE_IN; -+ } else { -+ if (crq.crq.wLength != __constant_cpu_to_le16(0)) -+ ep->state = DATA_STAGE_OUT; -+ else -+ ep->state = STATUS_STAGE_IN; -+ } -+ -+ ret = -1; -+ if (ep->index == 0) -+ ret = handle_ep0_setup(udc, ep, &crq.crq); -+ else -+ ret = udc->driver->setup(&udc->gadget, &crq.crq); -+ -+ DBG(DBG_BUS, "req %02x.%02x, length %d, state %d, ret %d\n", -+ crq.crq.bRequestType, crq.crq.bRequest, -+ le16_to_cpu(crq.crq.wLength), ep->state, ret); -+ -+ if (ret < 0) { -+ /* Let the host know that we failed */ -+ set_protocol_stall(udc, ep); -+ } -+ } -+} -+ -+static void husb2_ep_irq(struct husb2_udc *udc, struct husb2_ep *ep) -+{ -+ struct husb2_request *req; -+ u32 epstatus; -+ u32 epctrl; -+ -+ epstatus = husb2_ep_readl(ep, STA); -+ epctrl = husb2_ep_readl(ep, CTL); -+ -+ DBG(DBG_INT, "%s: interrupt, status: 0x%08x\n", -+ ep_name(ep), epstatus); -+ -+ while ((epctrl & HUSB2_BIT(TX_PK_RDY)) -+ && !(epstatus & HUSB2_BIT(TX_PK_RDY))) { -+ BUG_ON(!ep_is_in(ep)); -+ -+ DBG(DBG_BUS, "%s: TX PK ready\n", ep_name(ep)); -+ -+ if (list_empty(&ep->queue)) { -+ dev_warn(&udc->pdev->dev, "ep_irq: queue empty\n"); -+ husb2_ep_writel(ep, CTL_DIS, HUSB2_BIT(TX_PK_RDY)); -+ return; -+ } -+ -+ req = list_entry(ep->queue.next, struct husb2_request, queue); -+ -+ if (req->using_dma) { -+ BUG_ON(!req->send_zlp); -+ -+ /* Send a zero-length packet */ -+ husb2_ep_writel(ep, SET_STA, -+ HUSB2_BIT(TX_PK_RDY)); -+ husb2_ep_writel(ep, CTL_DIS, -+ HUSB2_BIT(TX_PK_RDY)); -+ list_del_init(&req->queue); -+ submit_next_request(ep); -+ request_complete(ep, req, 0); -+ } else { -+ if (req->submitted) -+ next_fifo_transaction(ep, req); -+ else -+ submit_request(ep, req); -+ -+ if (req->last_transaction) { -+ list_del_init(&req->queue); -+ submit_next_request(ep); -+ request_complete(ep, req, 0); -+ } -+ } -+ -+ epstatus = husb2_ep_readl(ep, STA); -+ epctrl = husb2_ep_readl(ep, CTL); -+ } -+ if ((epstatus & epctrl) & HUSB2_BIT(RX_BK_RDY)) { -+ BUG_ON(ep_is_in(ep)); -+ -+ DBG(DBG_BUS, "%s: RX data ready\n", ep_name(ep)); -+ receive_data(ep); -+ husb2_ep_writel(ep, CLR_STA, HUSB2_BIT(RX_BK_RDY)); -+ } -+} -+ -+static void husb2_dma_irq(struct husb2_udc *udc, struct husb2_ep *ep) -+{ -+ struct husb2_request *req; -+ u32 status, control, pending; -+ -+ status = husb2_dma_readl(ep, STATUS); -+ control = husb2_dma_readl(ep, CONTROL); -+#ifdef CONFIG_DEBUG_FS -+ ep->last_dma_status = status; -+#endif -+ pending = status & control; -+ DBG(DBG_INT, "dma irq, status=%#08x, pending=%#08x, control=%#08x\n", -+ status, pending, control); -+ -+ BUG_ON(status & HUSB2_BIT(DMA_CH_EN)); -+ -+ if (list_empty(&ep->queue)) -+ /* Might happen if a reset comes along at the right moment */ -+ return; -+ -+ if (pending & (HUSB2_BIT(DMA_END_TR_ST) | HUSB2_BIT(DMA_END_BUF_ST))) { -+ req = list_entry(ep->queue.next, struct husb2_request, queue); -+ husb2_update_req(ep, req, status); -+ -+ if (req->send_zlp) { -+ husb2_ep_writel(ep, CTL_ENB, HUSB2_BIT(TX_PK_RDY)); -+ } else { -+ list_del_init(&req->queue); -+ submit_next_request(ep); -+ request_complete(ep, req, 0); -+ } -+ } -+} -+ -+static irqreturn_t husb2_udc_irq(int irq, void *devid) -+{ -+ struct husb2_udc *udc = devid; -+ u32 status; -+ u32 dma_status; -+ u32 ep_status; -+ -+ spin_lock(&udc->lock); -+ -+ status = husb2_readl(udc, INT_STA); -+ DBG(DBG_INT, "irq, status=%#08x\n", status); -+ -+ if (status & HUSB2_BIT(DET_SUSPEND)) { -+ husb2_writel(udc, INT_CLR, HUSB2_BIT(DET_SUSPEND)); -+ //DBG(DBG_BUS, "Suspend detected\n"); -+ if (udc->gadget.speed != USB_SPEED_UNKNOWN -+ && udc->driver && udc->driver->suspend) -+ udc->driver->suspend(&udc->gadget); -+ } -+ -+ if (status & HUSB2_BIT(WAKE_UP)) { -+ husb2_writel(udc, INT_CLR, HUSB2_BIT(WAKE_UP)); -+ //DBG(DBG_BUS, "Wake Up CPU detected\n"); -+ } -+ -+ if (status & HUSB2_BIT(END_OF_RESUME)) { -+ husb2_writel(udc, INT_CLR, HUSB2_BIT(END_OF_RESUME)); -+ DBG(DBG_BUS, "Resume detected\n"); -+ if (udc->gadget.speed != USB_SPEED_UNKNOWN -+ && udc->driver && udc->driver->resume) -+ udc->driver->resume(&udc->gadget); -+ } -+ -+ dma_status = HUSB2_BFEXT(DMA_INT, status); -+ if (dma_status) { -+ int i; -+ -+ for (i = 1; i < HUSB2_NR_ENDPOINTS; i++) -+ if (dma_status & (1 << i)) -+ husb2_dma_irq(udc, &husb2_ep[i]); -+ } -+ -+ ep_status = HUSB2_BFEXT(EPT_INT, status); -+ if (ep_status) { -+ int i; -+ -+ for (i = 0; i < HUSB2_NR_ENDPOINTS; i++) -+ if (ep_status & (1 << i)) { -+ if (ep_is_control(&husb2_ep[i])) -+ husb2_control_irq(udc, &husb2_ep[i]); -+ else -+ husb2_ep_irq(udc, &husb2_ep[i]); -+ } -+ } -+ -+ if (status & HUSB2_BIT(END_OF_RESET)) { -+ husb2_writel(udc, INT_CLR, HUSB2_BIT(END_OF_RESET)); -+ if (status & HUSB2_BIT(HIGH_SPEED)) { -+ DBG(DBG_BUS, "High-speed bus reset detected\n"); -+ udc->gadget.speed = USB_SPEED_HIGH; -+ } else { -+ DBG(DBG_BUS, "Full-speed bus reset detected\n"); -+ udc->gadget.speed = USB_SPEED_FULL; -+ } -+ /* Better start from scratch... */ -+ reset_all_endpoints(udc); -+ husb2_ep[0].state = WAIT_FOR_SETUP; -+ udc_enable(udc); -+ } -+ -+ spin_unlock(&udc->lock); -+ -+ return IRQ_HANDLED; -+} -+ -+int usb_gadget_register_driver(struct usb_gadget_driver *driver) -+{ -+ struct husb2_udc *udc = &the_udc; -+ int ret; -+ -+ spin_lock(&udc->lock); -+ -+ ret = -ENODEV; -+ if (!udc->pdev) -+ goto out; -+ ret = -EBUSY; -+ if (udc->driver) -+ goto out; -+ -+ udc->driver = driver; -+ udc->gadget.dev.driver = &driver->driver; -+ -+ device_add(&udc->gadget.dev); -+ ret = driver->bind(&udc->gadget); -+ if (ret) { -+ DBG(DBG_ERR, "Could not bind to driver %s: error %d\n", -+ driver->driver.name, ret); -+ device_del(&udc->gadget.dev); -+ -+ udc->driver = NULL; -+ udc->gadget.dev.driver = NULL; -+ goto out; -+ } -+ -+ /* TODO: Create sysfs files */ -+ -+ DBG(DBG_GADGET, "registered driver `%s'\n", driver->driver.name); -+ udc_enable(udc); -+ -+out: -+ spin_unlock(&udc->lock); -+ return ret; -+} -+EXPORT_SYMBOL(usb_gadget_register_driver); -+ -+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) -+{ -+ struct husb2_udc *udc = &the_udc; -+ int ret; -+ -+ spin_lock(&udc->lock); -+ -+ ret = -ENODEV; -+ if (!udc->pdev) -+ goto out; -+ ret = -EINVAL; -+ if (driver != udc->driver) -+ goto out; -+ -+ local_irq_disable(); -+ udc_disable(udc); -+ local_irq_enable(); -+ -+ driver->unbind(&udc->gadget); -+ udc->driver = NULL; -+ -+ device_del(&udc->gadget.dev); -+ -+ /* TODO: Remove sysfs files */ -+ -+ DBG(DBG_GADGET, "unregistered driver `%s'\n", driver->driver.name); -+ -+out: -+ spin_unlock(&udc->lock); -+ return ret; -+} -+EXPORT_SYMBOL(usb_gadget_unregister_driver); -+ -+static int __devinit husb2_udc_probe(struct platform_device *pdev) -+{ -+ struct resource *regs, *fifo; -+ struct clk *pclk, *hclk; -+ struct husb2_udc *udc = &the_udc; -+ int irq, ret, i; -+ -+ regs = platform_get_resource(pdev, IORESOURCE_MEM, CTRL_IOMEM_ID); -+ fifo = platform_get_resource(pdev, IORESOURCE_MEM, FIFO_IOMEM_ID); -+ if (!regs || !fifo) -+ return -ENXIO; -+ -+ irq = platform_get_irq(pdev, 0); -+ if (irq < 0) -+ return irq; -+ -+ pclk = clk_get(&pdev->dev, "pclk"); -+ if (IS_ERR(pclk)) -+ return PTR_ERR(pclk); -+ hclk = clk_get(&pdev->dev, "hclk"); -+ if (IS_ERR(hclk)) { -+ ret = PTR_ERR(hclk); -+ goto out_put_pclk; -+ } -+ -+ clk_enable(pclk); -+ clk_enable(hclk); -+ -+ udc->pdev = pdev; -+ udc->pclk = pclk; -+ udc->hclk = hclk; -+ -+ ret = -ENOMEM; -+ udc->regs = ioremap(regs->start, regs->end - regs->start + 1); -+ if (!udc->regs) { -+ dev_err(&pdev->dev, "Unable to map I/O memory, aborting.\n"); -+ goto out_disable_clocks; -+ } -+ dev_info(&pdev->dev, "MMIO registers at 0x%08lx mapped at %p\n", -+ (unsigned long)regs->start, udc->regs); -+ udc->fifo = ioremap(fifo->start, fifo->end - fifo->start + 1); -+ if (!udc->fifo) { -+ dev_err(&pdev->dev, "Unable to map FIFO, aborting.\n"); -+ goto out_unmap_regs; -+ } -+ dev_info(&pdev->dev, "FIFO at 0x%08lx mapped at %p\n", -+ (unsigned long)fifo->start, udc->fifo); -+ -+ device_initialize(&udc->gadget.dev); -+ udc->gadget.dev.parent = &pdev->dev; -+ udc->gadget.dev.dma_mask = pdev->dev.dma_mask; -+ -+ /* The 3-word descriptors must be 4-word aligned... */ -+ udc->desc_pool = dma_pool_create("husb2-desc", &pdev->dev, -+ sizeof(struct husb2_dma_desc), -+ 16, 0); -+ if (!udc->desc_pool) { -+ dev_err(&pdev->dev, "Cannot create descriptor DMA pool\n"); -+ goto out_unmap_fifo; -+ } -+ -+ platform_set_drvdata(pdev, udc); -+ -+ udc_disable(udc); -+ -+ INIT_LIST_HEAD(&husb2_ep[0].ep.ep_list); -+ husb2_ep[0].ep_regs = udc->regs + HUSB2_EPT_BASE(0); -+ husb2_ep[0].dma_regs = udc->regs + HUSB2_DMA_BASE(0); -+ husb2_ep[0].fifo = udc->fifo + HUSB2_FIFO_BASE(0); -+ for (i = 1; i < ARRAY_SIZE(husb2_ep); i++) { -+ struct husb2_ep *ep = &husb2_ep[i]; -+ -+ ep->ep_regs = udc->regs + HUSB2_EPT_BASE(i); -+ ep->dma_regs = udc->regs + HUSB2_DMA_BASE(i); -+ ep->fifo = udc->fifo + HUSB2_FIFO_BASE(i); -+ -+ list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list); -+ } -+ -+ ret = request_irq(irq, husb2_udc_irq, SA_SAMPLE_RANDOM, -+ "husb2_udc", udc); -+ if (ret) { -+ dev_err(&pdev->dev, "Cannot request irq %d (error %d)\n", -+ irq, ret); -+ goto out_free_pool; -+ } -+ udc->irq = irq; -+ -+ husb2_init_debugfs(udc); -+ -+ return 0; -+ -+out_free_pool: -+ dma_pool_destroy(udc->desc_pool); -+out_unmap_fifo: -+ iounmap(udc->fifo); -+out_unmap_regs: -+ iounmap(udc->regs); -+out_disable_clocks: -+ clk_disable(hclk); -+ clk_disable(pclk); -+ clk_put(hclk); -+out_put_pclk: -+ clk_put(pclk); -+ -+ platform_set_drvdata(pdev, NULL); -+ -+ return ret; -+} -+ -+static int __devexit husb2_udc_remove(struct platform_device *pdev) -+{ -+ struct husb2_udc *udc; -+ -+ udc = platform_get_drvdata(pdev); -+ if (!udc) -+ return 0; -+ -+ husb2_cleanup_debugfs(udc); -+ -+ free_irq(udc->irq, udc); -+ dma_pool_destroy(udc->desc_pool); -+ iounmap(udc->fifo); -+ iounmap(udc->regs); -+ clk_disable(udc->hclk); -+ clk_disable(udc->pclk); -+ clk_put(udc->hclk); -+ clk_put(udc->pclk); -+ platform_set_drvdata(pdev, NULL); -+ -+ return 0; -+} -+ -+static struct platform_driver udc_driver = { -+ .probe = husb2_udc_probe, -+ .remove = __devexit_p(husb2_udc_remove), -+ .driver = { -+ .name = "usba", -+ }, -+}; -+ -+static int __init udc_init(void) -+{ -+ printk(KERN_INFO "husb2device: Driver version %s\n", DRIVER_VERSION); -+ return platform_driver_register(&udc_driver); -+} -+module_init(udc_init); -+ -+static void __exit udc_exit(void) -+{ -+ platform_driver_unregister(&udc_driver); -+} -+module_exit(udc_exit); -+ -+MODULE_DESCRIPTION("Atmel HUSB2 Device Controller driver"); -+MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>"); -+MODULE_LICENSE("GPL"); -diff -urN linux-2.6.20.4-0rig/drivers/usb/gadget/husb2_udc.h linux-2.6.20.4-atmel/drivers/usb/gadget/husb2_udc.h ---- linux-2.6.20.4-0rig/drivers/usb/gadget/husb2_udc.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/usb/gadget/husb2_udc.h 2007-03-24 16:42:29.000000000 +0100 -@@ -0,0 +1,406 @@ -+/* -+ * Driver for the Atmel HUSB2device high speed USB device 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 __LINUX_USB_GADGET_HUSB2_UDC_H__ -+#define __LINUX_USB_GADGET_HUSB2_UDC_H__ -+ -+/* USB register offsets */ -+#define HUSB2_CTRL 0x0000 -+#define HUSB2_FNUM 0x0004 -+#define HUSB2_INT_ENB 0x0010 -+#define HUSB2_INT_STA 0x0014 -+#define HUSB2_INT_CLR 0x0018 -+#define HUSB2_EPT_RST 0x001c -+#define HUSB2_TST_SOF_CNT 0x00d0 -+#define HUSB2_TST_CNT_A 0x00d4 -+#define HUSB2_TST_CNT_B 0x00d8 -+#define HUSB2_TST_MODE_REG 0x00dc -+#define HUSB2_TST 0x00f0 -+ -+/* USB endpoint register offsets */ -+#define HUSB2_EPT_CFG 0x0000 -+#define HUSB2_EPT_CTL_ENB 0x0004 -+#define HUSB2_EPT_CTL_DIS 0x0008 -+#define HUSB2_EPT_CTL 0x000c -+#define HUSB2_EPT_SET_STA 0x0014 -+#define HUSB2_EPT_CLR_STA 0x0018 -+#define HUSB2_EPT_STA 0x001c -+ -+/* USB DMA register offsets */ -+#define HUSB2_DMA_NXT_DSC 0x0000 -+#define HUSB2_DMA_ADDRESS 0x0004 -+#define HUSB2_DMA_CONTROL 0x0008 -+#define HUSB2_DMA_STATUS 0x000c -+ -+/* Bitfields in CTRL */ -+#define HUSB2_DEV_ADDR_OFFSET 0 -+#define HUSB2_DEV_ADDR_SIZE 7 -+#define HUSB2_FADDR_EN_OFFSET 7 -+#define HUSB2_FADDR_EN_SIZE 1 -+#define HUSB2_EN_HUSB2_OFFSET 8 -+#define HUSB2_EN_HUSB2_SIZE 1 -+#define HUSB2_DETACH_OFFSET 9 -+#define HUSB2_DETACH_SIZE 1 -+#define HUSB2_REMOTE_WAKE_UP_OFFSET 10 -+#define HUSB2_REMOTE_WAKE_UP_SIZE 1 -+ -+/* Bitfields in FNUM */ -+#define HUSB2_MICRO_FRAME_NUM_OFFSET 0 -+#define HUSB2_MICRO_FRAME_NUM_SIZE 3 -+#define HUSB2_FRAME_NUMBER_OFFSET 3 -+#define HUSB2_FRAME_NUMBER_SIZE 11 -+#define HUSB2_FRAME_NUM_ERROR_OFFSET 31 -+#define HUSB2_FRAME_NUM_ERROR_SIZE 1 -+ -+/* Bitfields in INT_ENB/INT_STA/INT_CLR */ -+#define HUSB2_HIGH_SPEED_OFFSET 0 -+#define HUSB2_HIGH_SPEED_SIZE 1 -+#define HUSB2_DET_SUSPEND_OFFSET 1 -+#define HUSB2_DET_SUSPEND_SIZE 1 -+#define HUSB2_MICRO_SOF_OFFSET 2 -+#define HUSB2_MICRO_SOF_SIZE 1 -+#define HUSB2_SOF_OFFSET 3 -+#define HUSB2_SOF_SIZE 1 -+#define HUSB2_END_OF_RESET_OFFSET 4 -+#define HUSB2_END_OF_RESET_SIZE 1 -+#define HUSB2_WAKE_UP_OFFSET 5 -+#define HUSB2_WAKE_UP_SIZE 1 -+#define HUSB2_END_OF_RESUME_OFFSET 6 -+#define HUSB2_END_OF_RESUME_SIZE 1 -+#define HUSB2_UPSTREAM_RESUME_OFFSET 7 -+#define HUSB2_UPSTREAM_RESUME_SIZE 1 -+#define HUSB2_EPT_INT_OFFSET 8 -+#define HUSB2_EPT_INT_SIZE 16 -+#define HUSB2_DMA_INT_OFFSET 24 -+#define HUSB2_DMA_INT_SIZE 8 -+ -+/* Bitfields in EPT_RST */ -+#define HUSB2_RST_OFFSET 0 -+#define HUSB2_RST_SIZE 16 -+ -+/* Bitfields in TST_SOF_CNT */ -+#define HUSB2_SOF_CNT_MAX_OFFSET 0 -+#define HUSB2_SOF_CNT_MAX_SIZE 7 -+#define HUSB2_SOF_CNT_LOAD_OFFSET 7 -+#define HUSB2_SOF_CNT_LOAD_SIZE 1 -+ -+/* Bitfields in TST_CNT_A */ -+#define HUSB2_CNT_A_MAX_OFFSET 0 -+#define HUSB2_CNT_A_MAX_SIZE 7 -+#define HUSB2_CNT_A_LOAD_OFFSET 7 -+#define HUSB2_CNT_A_LOAD_SIZE 1 -+ -+/* Bitfields in TST_CNT_B */ -+#define HUSB2_CNT_B_MAX_OFFSET 0 -+#define HUSB2_CNT_B_MAX_SIZE 7 -+#define HUSB2_CNT_B_LOAD_OFFSET 7 -+#define HUSB2_CNT_B_LOAD_SIZE 1 -+ -+/* Bitfields in TST_MODE_REG */ -+#define HUSB2_TST_MODE_OFFSET 0 -+#define HUSB2_TST_MODE_SIZE 6 -+ -+/* Bitfields in HUSB2_TST */ -+#define HUSB2_SPEED_CFG_OFFSET 0 -+#define HUSB2_SPEED_CFG_SIZE 2 -+#define HUSB2_TST_J_MODE_OFFSET 2 -+#define HUSB2_TST_J_MODE_SIZE 1 -+#define HUSB2_TST_K_MODE_OFFSET 3 -+#define HUSB2_TST_K_MODE_SIZE 1 -+#define HUSB2_TST_PKT_MODE_OFFSE 4 -+#define HUSB2_TST_PKT_MODE_SIZE 1 -+#define HUSB2_OPMODE2_OFFSET 5 -+#define HUSB2_OPMODE2_SIZE 1 -+ -+/* Bitfields in EPT_CFG */ -+#define HUSB2_EPT_SIZE_OFFSET 0 -+#define HUSB2_EPT_SIZE_SIZE 3 -+#define HUSB2_EPT_DIR_OFFSET 3 -+#define HUSB2_EPT_DIR_SIZE 1 -+#define HUSB2_EPT_TYPE_OFFSET 4 -+#define HUSB2_EPT_TYPE_SIZE 2 -+#define HUSB2_BK_NUMBER_OFFSET 6 -+#define HUSB2_BK_NUMBER_SIZE 2 -+#define HUSB2_NB_TRANS_OFFSET 8 -+#define HUSB2_NB_TRANS_SIZE 2 -+#define HUSB2_EPT_MAPPED_OFFSET 31 -+#define HUSB2_EPT_MAPPED_SIZE 1 -+ -+/* Bitfields in EPT_CTL/EPT_CTL_ENB/EPT_CTL_DIS */ -+#define HUSB2_EPT_ENABLE_OFFSET 0 -+#define HUSB2_EPT_ENABLE_SIZE 1 -+#define HUSB2_AUTO_VALID_OFFSET 1 -+#define HUSB2_AUTO_VALID_SIZE 1 -+#define HUSB2_INT_DIS_DMA_OFFSET 3 -+#define HUSB2_INT_DIS_DMA_SIZE 1 -+#define HUSB2_NYET_DIS_OFFSET 4 -+#define HUSB2_NYET_DIS_SIZE 1 -+#define HUSB2_DATAX_RX_OFFSET 6 -+#define HUSB2_DATAX_RX_SIZE 1 -+#define HUSB2_MDATA_RX_OFFSET 7 -+#define HUSB2_MDATA_RX_SIZE 1 -+/* Bits 8-15 and 31 enable interrupts for respective bits in EPT_STA */ -+#define HUSB2_BUSY_BANK_IE_OFFSET 18 -+#define HUSB2_BUSY_BANK_IE_SIZE 1 -+ -+/* Bitfields in EPT_SET_STA/EPT_CLR_STA/EPT_STA */ -+#define HUSB2_FORCE_STALL_OFFSET 5 -+#define HUSB2_FORCE_STALL_SIZE 1 -+#define HUSB2_TOGGLE_SEQ_OFFSET 6 -+#define HUSB2_TOGGLE_SEQ_SIZE 2 -+#define HUSB2_ERR_OVFLW_OFFSET 8 -+#define HUSB2_ERR_OVFLW_SIZE 1 -+#define HUSB2_RX_BK_RDY_OFFSET 9 -+#define HUSB2_RX_BK_RDY_SIZE 1 -+#define HUSB2_KILL_BANK_OFFSET 9 -+#define HUSB2_KILL_BANK_SIZE 1 -+#define HUSB2_TX_COMPLETE_OFFSET 10 -+#define HUSB2_TX_COMPLETE_SIZE 1 -+#define HUSB2_TX_PK_RDY_OFFSET 11 -+#define HUSB2_TX_PK_RDY_SIZE 1 -+#define HUSB2_ISO_ERR_TRANS_OFFSET 11 -+#define HUSB2_ISO_ERR_TRANS_SIZE 1 -+#define HUSB2_RX_SETUP_OFFSET 12 -+#define HUSB2_RX_SETUP_SIZE 1 -+#define HUSB2_ISO_ERR_FLOW_OFFSET 12 -+#define HUSB2_ISO_ERR_FLOW_SIZE 1 -+#define HUSB2_STALL_SENT_OFFSET 13 -+#define HUSB2_STALL_SENT_SIZE 1 -+#define HUSB2_ISO_ERR_CRC_OFFSET 13 -+#define HUSB2_ISO_ERR_CRC_SIZE 1 -+#define HUSB2_ISO_ERR_NBTRANS_OFFSET 13 -+#define HUSB2_ISO_ERR_NBTRANS_SIZE 1 -+#define HUSB2_NAK_IN_OFFSET 14 -+#define HUSB2_NAK_IN_SIZE 1 -+#define HUSB2_ISO_ERR_FLUSH_OFFSET 14 -+#define HUSB2_ISO_ERR_FLUSH_SIZE 1 -+#define HUSB2_NAK_OUT_OFFSET 15 -+#define HUSB2_NAK_OUT_SIZE 1 -+#define HUSB2_CURRENT_BANK_OFFSET 16 -+#define HUSB2_CURRENT_BANK_SIZE 2 -+#define HUSB2_BUSY_BANKS_OFFSET 18 -+#define HUSB2_BUSY_BANKS_SIZE 2 -+#define HUSB2_BYTE_COUNT_OFFSET 20 -+#define HUSB2_BYTE_COUNT_SIZE 11 -+#define HUSB2_SHORT_PACKET_OFFSET 31 -+#define HUSB2_SHORT_PACKET_SIZE 1 -+ -+/* Bitfields in DMA_CONTROL */ -+#define HUSB2_DMA_CH_EN_OFFSET 0 -+#define HUSB2_DMA_CH_EN_SIZE 1 -+#define HUSB2_DMA_LINK_OFFSET 1 -+#define HUSB2_DMA_LINK_SIZE 1 -+#define HUSB2_DMA_END_TR_EN_OFFSET 2 -+#define HUSB2_DMA_END_TR_EN_SIZE 1 -+#define HUSB2_DMA_END_BUF_EN_OFFSET 3 -+#define HUSB2_DMA_END_BUF_EN_SIZE 1 -+#define HUSB2_DMA_END_TR_IE_OFFSET 4 -+#define HUSB2_DMA_END_TR_IE_SIZE 1 -+#define HUSB2_DMA_END_BUF_IE_OFFSET 5 -+#define HUSB2_DMA_END_BUF_IE_SIZE 1 -+#define HUSB2_DMA_DESC_LOAD_IE_OFFSET 6 -+#define HUSB2_DMA_DESC_LOAD_IE_SIZE 1 -+#define HUSB2_DMA_BURST_LOCK_OFFSET 7 -+#define HUSB2_DMA_BURST_LOCK_SIZE 1 -+#define HUSB2_DMA_BUF_LEN_OFFSET 16 -+#define HUSB2_DMA_BUF_LEN_SIZE 16 -+ -+/* Bitfields in DMA_STATUS */ -+#define HUSB2_DMA_CH_ACTIVE_OFFSET 1 -+#define HUSB2_DMA_CH_ACTIVE_SIZE 1 -+#define HUSB2_DMA_END_TR_ST_OFFSET 4 -+#define HUSB2_DMA_END_TR_ST_SIZE 1 -+#define HUSB2_DMA_END_BUF_ST_OFFSET 5 -+#define HUSB2_DMA_END_BUF_ST_SIZE 1 -+#define HUSB2_DMA_DESC_LOAD_ST_OFFSET 6 -+#define HUSB2_DMA_DESC_LOAD_ST_SIZE 1 -+ -+/* Constants for SPEED_CFG */ -+#define HUSB2_SPEED_CFG_NORMAL 0 -+#define HUSB2_SPEED_CFG_FORCE_HIGH 2 -+#define HUSB2_SPEED_CFG_FORCE_FULL 3 -+ -+/* Constants for EPT_SIZE */ -+#define HUSB2_EPT_SIZE_8 0 -+#define HUSB2_EPT_SIZE_16 1 -+#define HUSB2_EPT_SIZE_32 2 -+#define HUSB2_EPT_SIZE_64 3 -+#define HUSB2_EPT_SIZE_128 4 -+#define HUSB2_EPT_SIZE_256 5 -+#define HUSB2_EPT_SIZE_512 6 -+#define HUSB2_EPT_SIZE_1024 7 -+ -+/* Constants for EPT_TYPE */ -+#define HUSB2_EPT_TYPE_CONTROL 0 -+#define HUSB2_EPT_TYPE_ISO 1 -+#define HUSB2_EPT_TYPE_BULK 2 -+#define HUSB2_EPT_TYPE_INT 3 -+ -+/* Constants for BK_NUMBER */ -+#define HUSB2_BK_NUMBER_ZERO 0 -+#define HUSB2_BK_NUMBER_ONE 1 -+#define HUSB2_BK_NUMBER_DOUBLE 2 -+#define HUSB2_BK_NUMBER_TRIPLE 3 -+ -+/* Bit manipulation macros */ -+#define HUSB2_BIT(name) \ -+ (1 << HUSB2_##name##_OFFSET) -+#define HUSB2_BF(name,value) \ -+ (((value) & ((1 << HUSB2_##name##_SIZE) - 1)) \ -+ << HUSB2_##name##_OFFSET) -+#define HUSB2_BFEXT(name,value) \ -+ (((value) >> HUSB2_##name##_OFFSET) \ -+ & ((1 << HUSB2_##name##_SIZE) - 1)) -+#define HUSB2_BFINS(name,value,old) \ -+ (((old) & ~(((1 << HUSB2_##name##_SIZE) - 1) \ -+ << HUSB2_##name##_OFFSET)) \ -+ | HUSB2_BF(name,value)) -+ -+/* Register access macros */ -+#define husb2_readl(udc,reg) \ -+ __raw_readl((udc)->regs + HUSB2_##reg) -+#define husb2_writel(udc,reg,value) \ -+ __raw_writel((value), (udc)->regs + HUSB2_##reg) -+#define husb2_ep_readl(ep,reg) \ -+ __raw_readl((ep)->ep_regs + HUSB2_EPT_##reg) -+#define husb2_ep_writel(ep,reg,value) \ -+ __raw_writel((value), (ep)->ep_regs + HUSB2_EPT_##reg) -+#define husb2_dma_readl(ep,reg) \ -+ __raw_readl((ep)->dma_regs + HUSB2_DMA_##reg) -+#define husb2_dma_writel(ep,reg,value) \ -+ __raw_writel((value), (ep)->dma_regs + HUSB2_DMA_##reg) -+ -+/* Calculate base address for a given endpoint or DMA controller */ -+#define HUSB2_EPT_BASE(x) (0x100 + (x) * 0x20) -+#define HUSB2_DMA_BASE(x) (0x300 + (x) * 0x10) -+#define HUSB2_FIFO_BASE(x) ((x) << 16) -+ -+/* Synth parameters */ -+#define HUSB2_NR_ENDPOINTS 7 -+ -+#define EP0_FIFO_SIZE 64 -+#define EP0_EPT_SIZE HUSB2_EPT_SIZE_64 -+#define EP0_NR_BANKS 1 -+#define BULK_FIFO_SIZE 512 -+#define BULK_EPT_SIZE HUSB2_EPT_SIZE_512 -+#define BULK_NR_BANKS 2 -+#define ISO_FIFO_SIZE 1024 -+#define ISO_EPT_SIZE HUSB2_EPT_SIZE_1024 -+#define ISO_NR_BANKS 3 -+#define INT_FIFO_SIZE 64 -+#define INT_EPT_SIZE HUSB2_EPT_SIZE_64 -+#define INT_NR_BANKS 3 -+ -+enum husb2_ctrl_state { -+ WAIT_FOR_SETUP, -+ DATA_STAGE_IN, -+ DATA_STAGE_OUT, -+ STATUS_STAGE_IN, -+ STATUS_STAGE_OUT, -+ STATUS_STAGE_ADDR, -+}; -+/* -+ EP_STATE_IDLE, -+ EP_STATE_SETUP, -+ EP_STATE_IN_DATA, -+ EP_STATE_OUT_DATA, -+ EP_STATE_SET_ADDR_STATUS, -+ EP_STATE_RX_STATUS, -+ EP_STATE_TX_STATUS, -+ EP_STATE_HALT, -+*/ -+ -+struct husb2_dma_desc { -+ dma_addr_t next; -+ dma_addr_t addr; -+ u32 ctrl; -+}; -+ -+struct husb2_ep { -+ int state; -+ void __iomem *ep_regs; -+ void __iomem *dma_regs; -+ void __iomem *fifo; -+ struct usb_ep ep; -+ struct husb2_udc *udc; -+ -+ struct list_head queue; -+ const struct usb_endpoint_descriptor *desc; -+ -+ u16 fifo_size; -+ u8 nr_banks; -+ u8 index; -+ u8 capabilities; -+ -+#ifdef CONFIG_DEBUG_FS -+ u32 last_dma_status; -+ struct dentry *debugfs_dir; -+ struct dentry *debugfs_queue; -+ struct dentry *debugfs_dma_status; -+#endif -+}; -+#define HUSB2_EP_CAP_ISOC 0x0001 -+#define HUSB2_EP_CAP_DMA 0x0002 -+ -+struct husb2_packet { -+ struct husb2_dma_desc *desc; -+ dma_addr_t desc_dma; -+}; -+ -+struct husb2_request { -+ struct usb_request req; -+ struct list_head queue; -+ -+ struct husb2_packet *packet; -+ unsigned int nr_pkts; -+ -+ unsigned int submitted:1; -+ unsigned int using_dma:1; -+ unsigned int last_transaction:1; -+ unsigned int send_zlp:1; -+}; -+ -+struct husb2_udc { -+ spinlock_t lock; -+ -+ void __iomem *regs; -+ void __iomem *fifo; -+ -+ struct dma_pool *desc_pool; -+ -+ struct usb_gadget gadget; -+ struct usb_gadget_driver *driver; -+ struct platform_device *pdev; -+ int irq; -+ struct clk *pclk; -+ struct clk *hclk; -+ -+#ifdef CONFIG_DEBUG_FS -+ struct dentry *debugfs_root; -+ struct dentry *debugfs_regs; -+#endif -+}; -+ -+#define to_husb2_ep(x) container_of((x), struct husb2_ep, ep) -+#define to_husb2_req(x) container_of((x), struct husb2_request, req) -+#define to_husb2_udc(x) container_of((x), struct husb2_udc, gadget) -+ -+#define ep_index(ep) ((ep)->index) -+#define ep_can_dma(ep) ((ep)->capabilities & HUSB2_EP_CAP_DMA) -+#define ep_is_in(ep) (((ep)->desc->bEndpointAddress \ -+ & USB_ENDPOINT_DIR_MASK) \ -+ == USB_DIR_IN) -+#define ep_is_isochronous(ep) \ -+ (((ep)->desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) \ -+ == USB_ENDPOINT_XFER_ISOC) -+#define ep_is_control(ep) (ep_index(ep) == 0) -+#define ep_name(ep) ((ep)->ep.name) -+#define ep_is_idle(ep) ((ep)->state == EP_STATE_IDLE) -+ -+#endif /* __LINUX_USB_GADGET_HUSB2_H */ -diff -urN linux-2.6.20.4-0rig/drivers/usb/gadget/Kconfig linux-2.6.20.4-atmel/drivers/usb/gadget/Kconfig ---- linux-2.6.20.4-0rig/drivers/usb/gadget/Kconfig 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/usb/gadget/Kconfig 2007-03-24 16:42:29.000000000 +0100 -@@ -154,6 +154,16 @@ - default USB_GADGET - select USB_GADGET_SELECTED - -+config USB_GADGET_HUSB2DEV -+ boolean "Atmel HUSB2DEVICE" -+ select USB_GADGET_DUALSPEED -+ depends on AVR32 -+ -+config USB_HUSB2DEV -+ tristate -+ depends on USB_GADGET_HUSB2DEV -+ default USB_GADGET -+ select USB_GADGET_SELECTED - - config USB_GADGET_OMAP - boolean "OMAP USB Device Controller" -diff -urN linux-2.6.20.4-0rig/drivers/usb/gadget/Makefile linux-2.6.20.4-atmel/drivers/usb/gadget/Makefile ---- linux-2.6.20.4-0rig/drivers/usb/gadget/Makefile 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/usb/gadget/Makefile 2007-03-24 16:42:29.000000000 +0100 -@@ -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_HUSB2DEV) += husb2_udc.o - - # - # USB gadget drivers -diff -urN linux-2.6.20.4-0rig/drivers/usb/gadget/serial.c linux-2.6.20.4-atmel/drivers/usb/gadget/serial.c ---- linux-2.6.20.4-0rig/drivers/usb/gadget/serial.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/usb/gadget/serial.c 2007-03-24 16:42:28.000000000 +0100 -@@ -333,7 +333,7 @@ - .strings = gs_strings, - }; - --static struct usb_device_descriptor gs_device_desc = { -+static struct usb_device_descriptor __attribute__((aligned(2))) gs_device_desc = { - .bLength = USB_DT_DEVICE_SIZE, - .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = __constant_cpu_to_le16(0x0200), -@@ -353,7 +353,7 @@ - .bmAttributes = USB_OTG_SRP, - }; - --static struct usb_config_descriptor gs_bulk_config_desc = { -+static struct usb_config_descriptor __attribute__((aligned(2))) gs_bulk_config_desc = { - .bLength = USB_DT_CONFIG_SIZE, - .bDescriptorType = USB_DT_CONFIG, - /* .wTotalLength computed dynamically */ -@@ -364,7 +364,7 @@ - .bMaxPower = 1, - }; - --static struct usb_config_descriptor gs_acm_config_desc = { -+static struct usb_config_descriptor __attribute__((aligned(2))) gs_acm_config_desc = { - .bLength = USB_DT_CONFIG_SIZE, - .bDescriptorType = USB_DT_CONFIG, - /* .wTotalLength computed dynamically */ -@@ -375,7 +375,7 @@ - .bMaxPower = 1, - }; - --static const struct usb_interface_descriptor gs_bulk_interface_desc = { -+static const struct usb_interface_descriptor __attribute__((aligned(2))) gs_bulk_interface_desc = { - .bLength = USB_DT_INTERFACE_SIZE, - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = GS_BULK_INTERFACE_ID, -@@ -386,7 +386,7 @@ - .iInterface = GS_DATA_STR_ID, - }; - --static const struct usb_interface_descriptor gs_control_interface_desc = { -+static const struct usb_interface_descriptor __attribute__((aligned(2))) gs_control_interface_desc = { - .bLength = USB_DT_INTERFACE_SIZE, - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = GS_CONTROL_INTERFACE_ID, -@@ -397,7 +397,7 @@ - .iInterface = GS_CONTROL_STR_ID, - }; - --static const struct usb_interface_descriptor gs_data_interface_desc = { -+static const struct usb_interface_descriptor __attribute__((aligned(2))) gs_data_interface_desc = { - .bLength = USB_DT_INTERFACE_SIZE, - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = GS_DATA_INTERFACE_ID, -@@ -408,7 +408,7 @@ - .iInterface = GS_DATA_STR_ID, - }; - --static const struct usb_cdc_header_desc gs_header_desc = { -+static const struct usb_cdc_header_desc __attribute__((aligned(2))) gs_header_desc = { - .bLength = sizeof(gs_header_desc), - .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = USB_CDC_HEADER_TYPE, -@@ -438,7 +438,7 @@ - .bSlaveInterface0 = 1, /* index of data interface */ - }; - --static struct usb_endpoint_descriptor gs_fullspeed_notify_desc = { -+static struct usb_endpoint_descriptor __attribute__((aligned(2))) gs_fullspeed_notify_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = USB_DIR_IN, -@@ -447,14 +447,14 @@ - .bInterval = 1 << GS_LOG2_NOTIFY_INTERVAL, - }; - --static struct usb_endpoint_descriptor gs_fullspeed_in_desc = { -+static struct usb_endpoint_descriptor __attribute__((aligned(2))) gs_fullspeed_in_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - }; - --static struct usb_endpoint_descriptor gs_fullspeed_out_desc = { -+static struct usb_endpoint_descriptor __attribute__((aligned(2))) gs_fullspeed_out_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = USB_DIR_OUT, -@@ -484,7 +484,7 @@ - }; - - #ifdef CONFIG_USB_GADGET_DUALSPEED --static struct usb_endpoint_descriptor gs_highspeed_notify_desc = { -+static struct usb_endpoint_descriptor __attribute__((aligned(2))) gs_highspeed_notify_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = USB_DIR_IN, -@@ -493,21 +493,21 @@ - .bInterval = GS_LOG2_NOTIFY_INTERVAL+4, - }; - --static struct usb_endpoint_descriptor gs_highspeed_in_desc = { -+static struct usb_endpoint_descriptor __attribute__((aligned(2))) gs_highspeed_in_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), - }; - --static struct usb_endpoint_descriptor gs_highspeed_out_desc = { -+static struct usb_endpoint_descriptor __attribute__((aligned(2))) gs_highspeed_out_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), - }; - --static struct usb_qualifier_descriptor gs_qualifier_desc = { -+static struct usb_qualifier_descriptor __attribute__((aligned(2))) gs_qualifier_desc = { - .bLength = sizeof(struct usb_qualifier_descriptor), - .bDescriptorType = USB_DT_DEVICE_QUALIFIER, - .bcdUSB = __constant_cpu_to_le16 (0x0200), -diff -urN linux-2.6.20.4-0rig/drivers/usb/gadget/zero.c linux-2.6.20.4-atmel/drivers/usb/gadget/zero.c ---- linux-2.6.20.4-0rig/drivers/usb/gadget/zero.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/usb/gadget/zero.c 2007-03-24 16:42:28.000000000 +0100 -@@ -221,7 +221,7 @@ - #define CONFIG_LOOPBACK 2 - - static struct usb_device_descriptor --device_desc = { -+device_desc __attribute__((aligned(2))) = { - .bLength = sizeof device_desc, - .bDescriptorType = USB_DT_DEVICE, - -@@ -237,7 +237,7 @@ - }; - - static struct usb_config_descriptor --source_sink_config = { -+source_sink_config __attribute__((aligned(2))) = { - .bLength = sizeof source_sink_config, - .bDescriptorType = USB_DT_CONFIG, - -@@ -250,7 +250,7 @@ - }; - - static struct usb_config_descriptor --loopback_config = { -+loopback_config __attribute__((aligned(2))) = { - .bLength = sizeof loopback_config, - .bDescriptorType = USB_DT_CONFIG, - -@@ -273,7 +273,7 @@ - /* one interface in each configuration */ - - static const struct usb_interface_descriptor --source_sink_intf = { -+source_sink_intf __attribute__((aligned(2))) = { - .bLength = sizeof source_sink_intf, - .bDescriptorType = USB_DT_INTERFACE, - -@@ -283,7 +283,7 @@ - }; - - static const struct usb_interface_descriptor --loopback_intf = { -+loopback_intf __attribute__((aligned(2))) = { - .bLength = sizeof loopback_intf, - .bDescriptorType = USB_DT_INTERFACE, - -@@ -295,7 +295,7 @@ - /* two full speed bulk endpoints; their use is config-dependent */ - - static struct usb_endpoint_descriptor --fs_source_desc = { -+fs_source_desc __attribute__((aligned(2))) = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - -@@ -304,7 +304,7 @@ - }; - - static struct usb_endpoint_descriptor --fs_sink_desc = { -+fs_sink_desc __attribute__((aligned(2))) = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - -@@ -340,7 +340,7 @@ - */ - - static struct usb_endpoint_descriptor --hs_source_desc = { -+hs_source_desc __attribute__((aligned(2))) = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - -@@ -349,7 +349,7 @@ - }; - - static struct usb_endpoint_descriptor --hs_sink_desc = { -+hs_sink_desc __attribute__((aligned(2))) = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - -@@ -358,7 +358,7 @@ - }; - - static struct usb_qualifier_descriptor --dev_qualifier = { -+dev_qualifier __attribute__((aligned(2))) = { - .bLength = sizeof dev_qualifier, - .bDescriptorType = USB_DT_DEVICE_QUALIFIER, - -diff -urN linux-2.6.20.4-0rig/drivers/usb/host/ohci-at91.c linux-2.6.20.4-atmel/drivers/usb/host/ohci-at91.c ---- linux-2.6.20.4-0rig/drivers/usb/host/ohci-at91.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/usb/host/ohci-at91.c 2007-03-24 16:39:15.000000000 +0100 -@@ -18,19 +18,38 @@ - #include <asm/mach-types.h> - #include <asm/hardware.h> - #include <asm/arch/board.h> -+#include <asm/arch/cpu.h> - - #ifndef CONFIG_ARCH_AT91 - #error "CONFIG_ARCH_AT91 must be defined." - #endif - - /* interface and function clocks */ --static struct clk *iclk, *fclk; -+static struct clk *iclk, *fclk, *hclock; - static int clocked; - - extern int usb_disabled(void); - - /*-------------------------------------------------------------------------*/ - -+static void at91_start_clock(void) -+{ -+ if (cpu_is_at91sam9261()) -+ clk_enable(hclock); -+ clk_enable(iclk); -+ clk_enable(fclk); -+ clocked = 1; -+} -+ -+static void at91_stop_clock(void) -+{ -+ clk_disable(fclk); -+ clk_disable(iclk); -+ if (cpu_is_at91sam9261()) -+ clk_disable(hclock); -+ clocked = 0; -+} -+ - static void at91_start_hc(struct platform_device *pdev) - { - struct usb_hcd *hcd = platform_get_drvdata(pdev); -@@ -41,9 +60,7 @@ - /* - * Start the USB clocks. - */ -- clk_enable(iclk); -- clk_enable(fclk); -- clocked = 1; -+ at91_start_clock(); - - /* - * The USB host controller must remain in reset. -@@ -66,9 +83,7 @@ - /* - * Stop the USB clocks. - */ -- clk_disable(fclk); -- clk_disable(iclk); -- clocked = 0; -+ at91_stop_clock(); - } - - -@@ -126,6 +141,8 @@ - - iclk = clk_get(&pdev->dev, "ohci_clk"); - fclk = clk_get(&pdev->dev, "uhpck"); -+ if (cpu_is_at91sam9261()) -+ hclock = clk_get(&pdev->dev, "hck0"); - - at91_start_hc(pdev); - ohci_hcd_init(hcd_to_ohci(hcd)); -@@ -137,6 +154,8 @@ - /* Error handling */ - at91_stop_hc(pdev); - -+ if (cpu_is_at91sam9261()) -+ clk_put(hclock); - clk_put(fclk); - clk_put(iclk); - -@@ -170,11 +189,12 @@ - at91_stop_hc(pdev); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -- disable_irq_wake(hcd->irq); - -+ if (cpu_is_at91sam9261()) -+ clk_put(hclock); - clk_put(fclk); - clk_put(iclk); -- fclk = iclk = NULL; -+ fclk = iclk = hclock = NULL; - - dev_set_drvdata(&pdev->dev, NULL); - return 0; -@@ -271,8 +291,6 @@ - - if (device_may_wakeup(&pdev->dev)) - enable_irq_wake(hcd->irq); -- else -- disable_irq_wake(hcd->irq); - - /* - * The integrated transceivers seem unable to notice disconnect, -@@ -283,9 +301,7 @@ - */ - if (at91_suspend_entering_slow_clock()) { - ohci_usb_reset (ohci); -- clk_disable(fclk); -- clk_disable(iclk); -- clocked = 0; -+ at91_stop_clock(); - } - - return 0; -@@ -293,11 +309,13 @@ - - static int ohci_hcd_at91_drv_resume(struct platform_device *pdev) - { -- if (!clocked) { -- clk_enable(iclk); -- clk_enable(fclk); -- clocked = 1; -- } -+ struct usb_hcd *hcd = platform_get_drvdata(pdev); -+ -+ if (device_may_wakeup(&pdev->dev)) -+ disable_irq_wake(hcd->irq); -+ -+ if (!clocked) -+ at91_start_clock(); - - return 0; - } -diff -urN linux-2.6.20.4-0rig/drivers/video/atmel_lcdfb.c linux-2.6.20.4-atmel/drivers/video/atmel_lcdfb.c ---- linux-2.6.20.4-0rig/drivers/video/atmel_lcdfb.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/video/atmel_lcdfb.c 2007-03-24 16:39:15.000000000 +0100 -@@ -0,0 +1,781 @@ -+/* -+ * drivers/video/atmel_lcdfb.c -+ * -+ * Driver for AT91/AVR32 LCD Controller -+ * -+ * Copyright (C) 2007 Atmel Corporation -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/platform_device.h> -+#include <linux/dma-mapping.h> -+#include <linux/interrupt.h> -+#include <linux/clk.h> -+#include <linux/fb.h> -+#include <linux/init.h> -+#include <linux/delay.h> -+ -+#include <asm/arch/board.h> -+#include <asm/arch/cpu.h> -+#include <asm/arch/gpio.h> -+ -+#include <video/atmel_lcdc.h> -+ -+#define lcdc_readl(sinfo, reg) __raw_readl((sinfo)->mmio+(reg)) -+#define lcdc_writel(sinfo, reg, val) __raw_writel((val), (sinfo)->mmio+(reg)) -+ -+/* More or less configurable parameters */ -+#define ATMEL_LCDC_FIFO_SIZE 512 -+#define ATMEL_LCDC_CRST_VAL_DEFAULT 0xc8 -+#define ATMEL_LCDC_DMA_BURST_LEN 16 -+ -+#define LCD_POWER_ON 0 -+#define LCD_POWER_OFF 1 -+ -+#if defined(CONFIG_ARCH_AT91) -+static inline void atmel_lcdfb_update_dma2d(struct fb_info *info, -+ struct fb_var_screeninfo *var) { } -+static inline void atmel_lcdfb_set_2dcfg(struct fb_info *info) { } -+#elif defined(CONFIG_AVR32) -+static void atmel_lcdfb_update_dma2d(struct fb_info *info, -+ struct fb_var_screeninfo *var) -+{ -+ dma2dcfg = lcdc_readl(sinfo, ATMEL_LCDC_DMA2DCFG); -+ dma2dcfg = LCDC_INSBF(DMA2DCFG_PIXELOFF, pixeloff, dma2dcfg); -+ lcdc_writel(sinfo, ATMEL_LCDC_DMA2DCFG, dma2dcfg); -+ -+ /* Update configuration */ -+ lcdc_writel(sinfo, ATMEL_LCDC_DMACON, -+ lcdc_readl(sinfo, ATMEL_LCDC_DMACON) | LCDC_BIT(DMACON_DMAUPDT)); -+} -+ -+static void atmel_lcdfb_set_2dcfg(struct fb_info *info) -+{ -+ /* ...set 2D configuration (necessary for xres_virtual != xres) */ -+ value = LCDC_MKBF(DMA2DCFG_ADDRINC, -+ info->var.xres_virtual - info->var.xres); -+ lcdc_writel(sinfo, DMA2DCFG, value); -+ -+ /* ...wait for DMA engine to become idle... */ -+ while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & LCDC_BIT(DMACON_DMABUSY)) -+ msleep(10); -+} -+#endif -+ -+ -+static struct fb_fix_screeninfo atmel_lcdfb_fix __initdata = { -+ .type = FB_TYPE_PACKED_PIXELS, -+ .visual = FB_VISUAL_TRUECOLOR, -+ .xpanstep = 0, -+ .ypanstep = 0, -+ .ywrapstep = 0, -+ .accel = FB_ACCEL_NONE, -+}; -+ -+static u32 pseudo_palette[16] = { -+ 0x000000, -+ 0xaa0000, -+ 0x00aa00, -+ 0xaa5500, -+ 0x0000aa, -+ 0xaa00aa, -+ 0x00aaaa, -+ 0xaaaaaa, -+ 0x555555, -+ 0xff5555, -+ 0x55ff55, -+ 0xffff55, -+ 0x5555ff, -+ 0xff55ff, -+ 0x55ffff, -+ 0xffffff -+}; -+ -+static void atmel_lcdfb_update_dma(struct fb_info *info, -+ struct fb_var_screeninfo *var) -+{ -+ struct atmel_lcdfb_info *sinfo = info->par; -+ struct fb_fix_screeninfo *fix = &info->fix; -+ unsigned long dma_addr; -+ -+ dma_addr = (fix->smem_start + var->yoffset * fix->line_length -+ + var->xoffset * var->bits_per_pixel / 8); -+ -+ dma_addr &= ~3UL; -+ -+ /* Set framebuffer DMA base address and pixel offset */ -+ lcdc_writel(sinfo, ATMEL_LCDC_DMABADDR1, dma_addr); -+ -+ atmel_lcdfb_update_dma2d(info, var); -+} -+ -+static inline void atmel_lcdfb_unmap_video_memory(struct atmel_lcdfb_info *sinfo) -+{ -+ struct fb_info *info = sinfo->info; -+ -+ dma_free_writecombine(info->device, sinfo->map_size, -+ sinfo->map_cpu, sinfo->map_dma); -+} -+ -+/** -+ * atmel_lcdfb_alloc_framebuffer - Allocate framebuffer memory -+ * @sinfo: the frame buffer to allocate memory for -+ */ -+static int atmel_lcdfb_map_video_memory(struct atmel_lcdfb_info *sinfo) -+{ -+ struct fb_info *info = sinfo->info; -+ struct fb_var_screeninfo *var = &info->var; -+ -+ sinfo->map_size = (var->xres_virtual * var->yres_virtual -+ * ((var->bits_per_pixel + 7) / 8)); -+ -+ sinfo->map_cpu = dma_alloc_writecombine(info->device, sinfo->map_size, -+ &sinfo->map_dma, GFP_KERNEL); -+ -+ if (!sinfo->map_cpu) { -+ return -ENOMEM; -+ } -+ -+ return 0; -+} -+ -+/** -+ * atmel_lcdfb_check_var - Validates a var passed in. -+ * @var: frame buffer variable screen structure -+ * @info: frame buffer structure that represents a single frame buffer -+ * -+ * Checks to see if the hardware supports the state requested by -+ * var passed in. This function does not alter the hardware -+ * state!!! This means the data stored in struct fb_info and -+ * struct atmel_lcdfb_info do not change. This includes the var -+ * inside of struct fb_info. Do NOT change these. This function -+ * can be called on its own if we intent to only test a mode and -+ * not actually set it. The stuff in modedb.c is a example of -+ * this. If the var passed in is slightly off by what the -+ * hardware can support then we alter the var PASSED in to what -+ * we can do. If the hardware doesn't support mode change a -+ * -EINVAL will be returned by the upper layers. You don't need -+ * to implement this function then. If you hardware doesn't -+ * support changing the resolution then this function is not -+ * needed. In this case the driver would just provide a var that -+ * represents the static state the screen is in. -+ * -+ * Returns negative errno on error, or zero on success. -+ */ -+static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var, -+ struct fb_info *info) -+{ -+ struct device *dev = info->device; -+ struct atmel_lcdfb_info *sinfo = info->par; -+ unsigned long clk_value_khz = 0; -+ -+ clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000; -+ -+ dev_dbg(dev, "%s:\n", __func__); -+ dev_dbg(dev, " resolution: %ux%u\n", var->xres, var->yres); -+ dev_dbg(dev, " pixclk: %lu KHz\n", PICOS2KHZ(var->pixclock)); -+ dev_dbg(dev, " bpp: %u\n", var->bits_per_pixel); -+ dev_dbg(dev, " clk: %lu KHz\n", clk_value_khz); -+ -+ if ((PICOS2KHZ(var->pixclock) * var->bits_per_pixel / 8) > clk_value_khz) { -+ dev_err(dev, "%lu KHz pixel clock is too fast\n", PICOS2KHZ(var->pixclock)); -+ return -EINVAL; -+ } -+ -+ /* Force same alignment for each line */ -+ var->xres = (var->xres + 3) & ~3UL; -+ var->xres_virtual = (var->xres_virtual + 3) & ~3UL; -+ -+ var->red.msb_right = var->green.msb_right = var->blue.msb_right = 0; -+ var->transp.offset = var->transp.length = 0; -+ -+ switch (var->bits_per_pixel) { -+ case 2: -+ case 4: -+ case 8: -+ var->red.offset = var->green.offset = var->blue.offset = 0; -+ var->red.length = var->green.length = var->blue.length -+ = var->bits_per_pixel; -+ break; -+ case 15: -+ case 16: -+ var->red.offset = 0; -+ var->green.offset = 5; -+ var->blue.offset = 10; -+ var->red.length = var->green.length = var->blue.length = 5; -+ break; -+ case 24: -+ case 32: -+ var->red.offset = 16; -+ var->green.offset = 8; -+ var->blue.offset = 0; -+ var->red.length = var->green.length = var->blue.length = 8; -+ break; -+ default: -+ dev_err(dev, "color depth %d not supported\n", -+ var->bits_per_pixel); -+ return -EINVAL; -+ } -+ -+ var->xoffset = var->yoffset = 0; -+ var->red.msb_right = var->green.msb_right = var->blue.msb_right = -+ var->transp.msb_right = 0; -+ -+ return 0; -+} -+ -+/** -+ * atmel_lcdfb_set_par - Alters the hardware state. -+ * @info: frame buffer structure that represents a single frame buffer -+ * -+ * Using the fb_var_screeninfo in fb_info we set the resolution -+ * of the this particular framebuffer. This function alters the -+ * par AND the fb_fix_screeninfo stored in fb_info. It doesn't -+ * not alter var in fb_info since we are using that data. This -+ * means we depend on the data in var inside fb_info to be -+ * supported by the hardware. atmel_lcdfb_check_var is always called -+ * before atmel_lcdfb_set_par to ensure this. Again if you can't -+ * change the resolution you don't need this function. -+ * -+ */ -+static int atmel_lcdfb_set_par(struct fb_info *info) -+{ -+ struct atmel_lcdfb_info *sinfo = info->par; -+ unsigned long value; -+ unsigned long clk_value_khz = 0; -+ -+ dev_dbg(info->device, "%s:\n", __func__); -+ dev_dbg(info->device, " * resolution: %ux%u (%ux%u virtual)\n", -+ info->var.xres, info->var.yres, -+ info->var.xres_virtual, info->var.yres_virtual); -+ -+ /* Turn off the LCD controller and the DMA controller */ -+ lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET); -+ -+ lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0); -+ -+ /* Reset LCDC DMA*/ -+ lcdc_writel(sinfo, ATMEL_LCDC_DMACON, ATMEL_LCDC_DMARST); -+ -+ if (info->var.bits_per_pixel <= 8) -+ info->fix.visual = FB_VISUAL_PSEUDOCOLOR; -+ else -+ info->fix.visual = FB_VISUAL_TRUECOLOR; -+ -+ info->fix.line_length = info->var.xres_virtual * (info->var.bits_per_pixel / 8); -+ -+ /* Re-initialize the DMA engine... */ -+ dev_dbg(info->device, " * update DMA engine\n"); -+ atmel_lcdfb_update_dma(info, &info->var); -+ -+ /* ...set frame size and burst length = 8 words (?) */ -+ value = (info->var.yres * info->var.xres * info->var.bits_per_pixel) / 32; -+ value |= ((ATMEL_LCDC_DMA_BURST_LEN - 1) << ATMEL_LCDC_BLENGTH_OFFSET); -+ lcdc_writel(sinfo, ATMEL_LCDC_DMAFRMCFG, value); -+ -+ atmel_lcdfb_set_2dcfg(info); -+ -+ /* Now, the LCDC core... */ -+ -+ /* Set pixel clock */ -+ clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000; -+ -+ value = clk_value_khz / PICOS2KHZ(info->var.pixclock); -+ -+ if (clk_value_khz % PICOS2KHZ(info->var.pixclock)) -+ value++; -+ -+ value = (value / 2) - 1; -+ -+ if (value == 0) { -+ dev_notice(info->device, "Bypassing pixel clock divider\n"); -+ lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1, ATMEL_LCDC_BYPASS); -+ } else -+ lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1, value << ATMEL_LCDC_CLKVAL_OFFSET); -+ -+ /* Initialize control register 2 */ -+ value = sinfo->default_lcdcon2; -+ -+ if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT)) -+ value |= ATMEL_LCDC_INVLINE_INVERTED; -+ if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT)) -+ value |= ATMEL_LCDC_INVFRAME_INVERTED; -+ -+ switch (info->var.bits_per_pixel) { -+ case 1: value |= ATMEL_LCDC_PIXELSIZE_1; break; -+ case 2: value |= ATMEL_LCDC_PIXELSIZE_2; break; -+ case 4: value |= ATMEL_LCDC_PIXELSIZE_4; break; -+ case 8: value |= ATMEL_LCDC_PIXELSIZE_8; break; -+ case 15: /* fall through */ -+ case 16: value |= ATMEL_LCDC_PIXELSIZE_16; break; -+ case 24: value |= ATMEL_LCDC_PIXELSIZE_24; break; -+ case 32: value |= ATMEL_LCDC_PIXELSIZE_32; break; -+ default: BUG(); break; -+ } -+ dev_dbg(info->device, " * LCDCON2 = %08lx\n", value); -+ lcdc_writel(sinfo, ATMEL_LCDC_LCDCON2, value); -+ -+ /* Vertical timing */ -+ value = (info->var.vsync_len - 1) << ATMEL_LCDC_VPW_OFFSET; -+ value |= info->var.upper_margin << ATMEL_LCDC_VBP_OFFSET; -+ value |= info->var.lower_margin; -+ dev_dbg(info->device, " * LCDTIM1 = %08lx\n", value); -+ lcdc_writel(sinfo, ATMEL_LCDC_TIM1, value); -+ -+ /* Horizontal timing */ -+ value = (info->var.right_margin - 1) << ATMEL_LCDC_HFP_OFFSET; -+ value |= (info->var.hsync_len - 1) << ATMEL_LCDC_HPW_OFFSET; -+ value |= (info->var.left_margin - 1); -+ dev_dbg(info->device, " * LCDTIM2 = %08lx\n", value); -+ lcdc_writel(sinfo, ATMEL_LCDC_TIM2, value); -+ -+ /* Display size */ -+ value = (info->var.xres - 1) << ATMEL_LCDC_HOZVAL_OFFSET; -+ value |= info->var.yres - 1; -+ lcdc_writel(sinfo, ATMEL_LCDC_LCDFRMCFG, value); -+ -+ /* FIFO Threshold: Use formula from data sheet */ -+ value = ATMEL_LCDC_FIFO_SIZE - (2 * ATMEL_LCDC_DMA_BURST_LEN + 3); -+ lcdc_writel(sinfo, ATMEL_LCDC_FIFO, value); -+ -+ /* Toggle LCD_MODE every frame */ -+ lcdc_writel(sinfo, ATMEL_LCDC_MVAL, 0); -+ -+ /* Disable all interrupts */ -+ lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL); -+ -+ // Set contrast -+ value = ATMEL_LCDC_PS_DIV8 | ATMEL_LCDC_POL_POSITIVE | ATMEL_LCDC_ENA_PWMENABLE; -+ lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, value); -+ lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, ATMEL_LCDC_CRST_VAL_DEFAULT); -+ /* ...wait for DMA engine to become idle... */ -+ while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY) -+ msleep(10); -+ -+ dev_dbg(info->device, " * re-enable DMA engine\n"); -+ /* ...and enable it with updated configuration */ -+ lcdc_writel(sinfo, ATMEL_LCDC_DMACON, sinfo->default_dmacon); -+ -+ dev_dbg(info->device, " * re-enable LCDC core\n"); -+ lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, -+ (sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET) | ATMEL_LCDC_PWR); -+ -+ dev_dbg(info->device, " * DONE\n"); -+ -+ return 0; -+} -+ -+static inline u_int chan_to_field(u_int chan, const struct fb_bitfield *bf) -+{ -+ chan &= 0xffff; -+ chan >>= 16 - bf->length; -+ return chan << bf->offset; -+} -+ -+/** -+ * atmel_lcdfb_setcolreg - Optional function. Sets a color register. -+ * @regno: Which register in the CLUT we are programming -+ * @red: The red value which can be up to 16 bits wide -+ * @green: The green value which can be up to 16 bits wide -+ * @blue: The blue value which can be up to 16 bits wide. -+ * @transp: If supported the alpha value which can be up to 16 bits wide. -+ * @info: frame buffer info structure -+ * -+ * Set a single color register. The values supplied have a 16 bit -+ * magnitude which needs to be scaled in this function for the hardware. -+ * Things to take into consideration are how many color registers, if -+ * any, are supported with the current color visual. With truecolor mode -+ * no color palettes are supported. Here a psuedo palette is created -+ * which we store the value in pseudo_palette in struct fb_info. For -+ * pseudocolor mode we have a limited color palette. To deal with this -+ * we can program what color is displayed for a particular pixel value. -+ * DirectColor is similar in that we can program each color field. If -+ * we have a static colormap we don't need to implement this function. -+ * -+ * Returns negative errno on error, or zero on success. In an -+ * ideal world, this would have been the case, but as it turns -+ * out, the other drivers return 1 on failure, so that's what -+ * we're going to do. -+ */ -+static int atmel_lcdfb_setcolreg(unsigned int regno, unsigned int red, -+ unsigned int green, unsigned int blue, -+ unsigned int transp, struct fb_info *info) -+{ -+ struct atmel_lcdfb_info *sinfo = info->par; -+ unsigned int val; -+ u32 *pal; -+ int ret = 1; -+ -+ if (info->var.grayscale) -+ red = green = blue = (19595 * red + 38470 * green -+ + 7471 * blue) >> 16; -+ -+ switch (info->fix.visual) { -+ case FB_VISUAL_TRUECOLOR: -+ if (regno < 16) { -+ pal = info->pseudo_palette; -+ -+ val = chan_to_field(red, &info->var.red); -+ val |= chan_to_field(green, &info->var.green); -+ val |= chan_to_field(blue, &info->var.blue); -+ -+ pal[regno] = val; -+ ret = 0; -+ } -+ break; -+ -+ case FB_VISUAL_PSEUDOCOLOR: -+ if (regno < 256) { -+ val = ((red >> 11) & 0x001f); -+ val |= ((green >> 6) & 0x03e0); -+ val |= ((blue >> 1) & 0x7c00); -+ -+ /* -+ * TODO: intensity bit. Maybe something like -+ * ~(red[10] ^ green[10] ^ blue[10]) & 1 -+ */ -+ -+ lcdc_writel(sinfo, ATMEL_LCDC_LUT_(regno), val); -+ ret = 0; -+ } -+ break; -+ } -+ -+ return ret; -+} -+ -+static int atmel_lcdfb_pan_display(struct fb_var_screeninfo *var, -+ struct fb_info *info) -+{ -+ dev_dbg(info->device, "%s\n", __func__); -+ -+ atmel_lcdfb_update_dma(info, var); -+ -+ return 0; -+} -+ -+static struct fb_ops atmel_lcdfb_ops = { -+ .owner = THIS_MODULE, -+ .fb_check_var = atmel_lcdfb_check_var, -+ .fb_set_par = atmel_lcdfb_set_par, -+ .fb_setcolreg = atmel_lcdfb_setcolreg, -+ .fb_pan_display = atmel_lcdfb_pan_display, -+ .fb_fillrect = cfb_fillrect, -+ .fb_copyarea = cfb_copyarea, -+ .fb_imageblit = cfb_imageblit, -+}; -+ -+static irqreturn_t atmel_lcdfb_interrupt(int irq, void *dev_id) -+{ -+ struct fb_info *info = dev_id; -+ struct atmel_lcdfb_info *sinfo = info->par; -+ u32 status; -+ -+ status = lcdc_readl(sinfo, ATMEL_LCDC_ISR); -+ lcdc_writel(sinfo, ATMEL_LCDC_IDR, status); -+ return IRQ_HANDLED; -+} -+ -+static int atmel_lcdfb_init_fbinfo(struct atmel_lcdfb_info *sinfo) -+{ -+ struct fb_info *info = sinfo->info; -+ int ret = 0; -+ -+ info->screen_base = sinfo->map_cpu; -+ info->fix.smem_start = sinfo->map_dma; -+ info->fix.smem_len = sinfo->map_size; -+ -+ memset(info->screen_base, 0, info->fix.smem_len); -+ info->var.activate |= FB_ACTIVATE_FORCE | FB_ACTIVATE_NOW; -+ -+ dev_info(info->device, -+ "%luKiB frame buffer at %08lx (mapped at %p)\n", -+ (unsigned long)info->fix.smem_len / 1024, -+ (unsigned long)info->fix.smem_start, -+ info->screen_base); -+ -+ /* Allocate colormap */ -+ ret = fb_alloc_cmap(&info->cmap, 256, 0); -+ if (ret < 0) -+ dev_err(info->device, "Alloc color map failed\n"); -+ -+ return ret; -+} -+ -+static int atmel_lcdfb_start_clock(struct atmel_lcdfb_info *sinfo) -+{ -+ int ret = 0; -+ -+ if (sinfo->bus_clk && !IS_ERR(sinfo->bus_clk)) -+ clk_enable(sinfo->bus_clk); -+ else { -+ if (cpu_is_at91sam9261()) { -+ /* not an error for other cpus */ -+ ret = -ENXIO; -+ } -+ } -+ -+ if (sinfo->lcdc_clk && !IS_ERR(sinfo->lcdc_clk)) -+ clk_enable(sinfo->lcdc_clk); -+ else -+ ret = -ENXIO; -+ -+ return ret; -+} -+ -+static void atmel_lcdfb_stop_clock(struct atmel_lcdfb_info *sinfo) -+{ -+ if (sinfo->bus_clk && !IS_ERR(sinfo->bus_clk)) -+ clk_disable(sinfo->bus_clk); -+ if (sinfo->lcdc_clk && !IS_ERR(sinfo->lcdc_clk)) -+ clk_disable(sinfo->lcdc_clk); -+} -+ -+ -+static int atmel_lcdfb_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct fb_info *info; -+ struct atmel_lcdfb_info *sinfo; -+ struct resource *regs = NULL; -+ struct resource *map = NULL; -+ int ret; -+ -+ dev_dbg(dev, "%s BEGIN\n", __func__); -+ -+ ret = -ENOMEM; -+ info = framebuffer_alloc(sizeof(struct atmel_lcdfb_info), dev); -+ if (!info) { -+ dev_err(dev, "cannot allocate memory\n"); -+ goto out; -+ } -+ -+ sinfo = info->par; -+ memcpy(sinfo, dev->platform_data, sizeof(struct atmel_lcdfb_info)); -+ sinfo->info = info; -+ sinfo->pdev = pdev; -+ -+ strcpy(info->fix.id, sinfo->pdev->name); -+ info->flags = sinfo->default_flags; -+ info->pseudo_palette = pseudo_palette; -+ info->fbops = &atmel_lcdfb_ops; -+ -+ memcpy(&info->monspecs, sinfo->default_monspecs, sizeof(info->monspecs)); -+ info->fix = atmel_lcdfb_fix; -+ -+ /* Enable LCDC Clocks */ -+ if (cpu_is_at91sam9261()) -+ sinfo->bus_clk = clk_get(dev, "hck1"); -+ sinfo->lcdc_clk = clk_get(dev, "lcdc_clk"); -+ if (atmel_lcdfb_start_clock(sinfo)) { -+ dev_err(dev, "unable to clock LCDC\n"); -+ goto free_info; -+ } -+ -+ ret = fb_find_mode(&info->var, info, NULL, info->monspecs.modedb, -+ info->monspecs.modedb_len, info->monspecs.modedb, -+ sinfo->default_bpp); -+ if (!ret) { -+ dev_err(dev, "no suitable video mode found\n"); -+ goto stop_clk; -+ } -+ -+ -+ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!regs) { -+ dev_err(dev, "resources unusable\n"); -+ ret = -ENXIO; -+ goto stop_clk; -+ } -+ -+ sinfo->irq_base = platform_get_irq(pdev, 0); -+ if (sinfo->irq_base < 0) { -+ dev_err(dev, "unable to get irq\n"); -+ ret = sinfo->irq_base; -+ goto stop_clk; -+ } -+ -+ /* Initialize video memory */ -+ map = platform_get_resource(pdev, IORESOURCE_MEM, 1); -+ if (map) { -+ /* use a pre-allocated memory buffer */ -+ sinfo->map_dma = map->start; -+ sinfo->map_size = map->end - map->start + 1; -+ if (!request_mem_region(sinfo->map_dma, -+ sinfo->map_size, pdev->name)) { -+ ret = -EBUSY; -+ goto stop_clk; -+ } -+ -+ sinfo->map_cpu = ioremap(sinfo->map_dma, sinfo->map_size); -+ if (!sinfo->map_cpu) -+ goto release_intmem; -+ } else { -+ /* alocate memory buffer */ -+ ret = atmel_lcdfb_map_video_memory(sinfo); -+ if (ret < 0) { -+ dev_err(dev, "cannot allocate framebuffer: %d\n", ret); -+ goto stop_clk; -+ } -+ } -+ -+ /* LCDC registers */ -+ info->fix.mmio_start = regs->start; -+ info->fix.mmio_len = regs->end - regs->start + 1; -+ -+ if (!request_mem_region(info->fix.mmio_start, -+ info->fix.mmio_len, pdev->name)) { -+ ret = -EBUSY; -+ goto free_fb; -+ } -+ -+ sinfo->mmio = ioremap(info->fix.mmio_start, info->fix.mmio_len); -+ if (!sinfo->mmio) { -+ dev_err(dev, "cannot map LCDC registers\n"); -+ goto release_mem; -+ } -+ -+ /* interrupt */ -+ ret = request_irq(sinfo->irq_base, atmel_lcdfb_interrupt, 0, pdev->name, info); -+ if (ret) { -+ dev_err(dev, "request_irq failed: %d\n", ret); -+ goto unmap_mmio; -+ } -+ -+ ret = atmel_lcdfb_init_fbinfo(sinfo); -+ if (ret < 0) { -+ dev_err(dev, "init fbinfo failed: %d\n", ret); -+ goto unregister_irqs; -+ } -+ -+ /* -+ * This makes sure that our colour bitfield -+ * descriptors are correctly initialised. -+ */ -+ atmel_lcdfb_check_var(&info->var, info); -+ atmel_lcdfb_set_par(info); -+ -+ ret = fb_set_var(info, &info->var); -+ if (ret) { -+ dev_warn(dev, "unable to set display parameters\n"); -+ goto free_cmap; -+ } -+ -+ dev_set_drvdata(dev, info); -+ -+ /* -+ * Tell the world that we're ready to go -+ */ -+ ret = register_framebuffer(info); -+ if (ret < 0) { -+ dev_err(dev, "failed to register framebuffer device: %d\n", ret); -+ goto free_cmap; -+ } -+ -+ /* Power up the LCDC screen */ -+ if (sinfo->power_control_pin) -+ at91_set_gpio_value(sinfo->power_control_pin, LCD_POWER_ON); -+ -+ dev_info(dev, "fb%d: Atmel LCDC at 0x%08lx (mapped at %p), irq %lu\n", -+ info->node, info->fix.mmio_start, sinfo->mmio, sinfo->irq_base); -+ -+ return 0; -+ -+ -+free_cmap: -+ fb_dealloc_cmap(&info->cmap); -+unregister_irqs: -+ free_irq(sinfo->irq_base, info); -+unmap_mmio: -+ iounmap(sinfo->mmio); -+release_mem: -+ release_mem_region(info->fix.mmio_start, info->fix.mmio_len); -+free_fb: -+ if (map) { -+ iounmap(sinfo->map_cpu); -+ } else { -+ atmel_lcdfb_unmap_video_memory(sinfo); -+ } -+ -+release_intmem: -+ if (map) { -+ release_mem_region(sinfo->map_dma, sinfo->map_size); -+ } -+stop_clk: -+ atmel_lcdfb_stop_clock(sinfo); -+free_info: -+ framebuffer_release(info); -+out: -+ dev_dbg(dev, "%s FAILED\n", __func__); -+ return ret; -+} -+ -+static int atmel_lcdfb_remove(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct fb_info *info = dev_get_drvdata(dev); -+ struct atmel_lcdfb_info *sinfo = info->par; -+ -+ if (!sinfo) -+ return 0; -+ -+ if (sinfo->power_control_pin) -+ at91_set_gpio_value(sinfo->power_control_pin, LCD_POWER_OFF); -+ unregister_framebuffer(info); -+ atmel_lcdfb_stop_clock(sinfo); -+ fb_dealloc_cmap(&info->cmap); -+ free_irq(sinfo->irq_base, info); -+ iounmap(sinfo->mmio); -+ release_mem_region(info->fix.mmio_start, info->fix.mmio_len); -+ if (platform_get_resource(pdev, IORESOURCE_MEM, 1)) { -+ iounmap(sinfo->map_cpu); -+ release_mem_region(sinfo->map_dma, sinfo->map_size); -+ } else { -+ atmel_lcdfb_unmap_video_memory(sinfo); -+ } -+ -+ dev_set_drvdata(dev, NULL); -+ framebuffer_release(info); -+ -+ return 0; -+} -+ -+static struct platform_driver atmel_lcdfb_driver = { -+ .probe = atmel_lcdfb_probe, -+ .remove = atmel_lcdfb_remove, -+ .driver = { -+ .name = "atmel_lcdfb", -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+static int __init atmel_lcdfb_init(void) -+{ -+ return platform_driver_register(&atmel_lcdfb_driver); -+} -+ -+static void __exit atmel_lcdfb_exit(void) -+{ -+ platform_driver_unregister(&atmel_lcdfb_driver); -+} -+ -+module_init(atmel_lcdfb_init); -+module_exit(atmel_lcdfb_exit); -+ -+MODULE_AUTHOR("Atmel Corporation"); -+MODULE_DESCRIPTION("AT91/AT32 LCD Controller framebuffer driver"); -+MODULE_LICENSE("GPL"); -diff -urN linux-2.6.20.4-0rig/drivers/video/backlight/Kconfig linux-2.6.20.4-atmel/drivers/video/backlight/Kconfig ---- linux-2.6.20.4-0rig/drivers/video/backlight/Kconfig 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/video/backlight/Kconfig 2007-03-24 16:42:29.000000000 +0100 -@@ -42,6 +42,18 @@ - depends on LCD_CLASS_DEVICE - default y - -+config LCD_LTV350QV -+ tristate "Samsung LTV350QV LCD Panel" -+ depends on LCD_DEVICE && SPI -+ 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 most ATSTK1000 boards. -+ - config BACKLIGHT_CORGI - tristate "Sharp Corgi Backlight Driver (SL Series)" - depends on BACKLIGHT_DEVICE && PXA_SHARPSL -diff -urN linux-2.6.20.4-0rig/drivers/video/backlight/ltv350qv.c linux-2.6.20.4-atmel/drivers/video/backlight/ltv350qv.c ---- linux-2.6.20.4-0rig/drivers/video/backlight/ltv350qv.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/video/backlight/ltv350qv.c 2007-03-24 16:42:29.000000000 +0100 -@@ -0,0 +1,300 @@ -+/* -+ * Power control for Samsung LTV350QV Quarter VGA LCD Panel -+ * -+ * 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. -+ */ -+#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/reboot.h> -+#include <linux/spi/spi.h> -+ -+#define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL) -+ -+struct ltv350qv { -+ struct spi_device *spi; -+ u8 *buffer; -+ int power; -+ struct semaphore lock; -+ struct lcd_device *ld; -+ struct list_head list; -+ int halt_done; -+}; -+ -+static LIST_HEAD(lcd_list); -+ -+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] = 0x74; -+ 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] = 0x76; -+ 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); -+} -+ -+#define write_reg(_spi, reg, val) \ -+ do { \ -+ ret = ltv350qv_write_reg(_spi, reg, val); \ -+ if (ret) \ -+ goto out; \ -+ } while (0) -+ -+static int ltv350qv_power_on(struct ltv350qv *lcd) -+{ -+ int ret; -+ -+ write_reg(lcd, 9, 0x0000); -+ msleep(15); -+ write_reg(lcd, 9, 0x4000); -+ write_reg(lcd, 10, 0x2000); -+ write_reg(lcd, 9, 0x4055); -+ msleep(55); -+ write_reg(lcd, 1, 0x409d); -+ write_reg(lcd, 2, 0x0204); -+ write_reg(lcd, 3, 0x0100); -+ write_reg(lcd, 4, 0x3000); -+ write_reg(lcd, 5, 0x4003); -+ write_reg(lcd, 6, 0x000a); -+ write_reg(lcd, 7, 0x0021); -+ write_reg(lcd, 8, 0x0c00); -+ write_reg(lcd, 10, 0x0103); -+ write_reg(lcd, 11, 0x0301); -+ write_reg(lcd, 12, 0x1f0f); -+ write_reg(lcd, 13, 0x1f0f); -+ write_reg(lcd, 14, 0x0707); -+ write_reg(lcd, 15, 0x0307); -+ write_reg(lcd, 16, 0x0707); -+ write_reg(lcd, 17, 0x0000); -+ write_reg(lcd, 18, 0x0004); -+ write_reg(lcd, 19, 0x0000); -+ -+ msleep(20); -+ write_reg(lcd, 9, 0x4a55); -+ write_reg(lcd, 5, 0x5003); -+ -+out: -+ return ret; -+} -+ -+static int ltv350qv_power_off(struct ltv350qv *lcd) -+{ -+ int ret; -+ -+ /* GON -> 0, POC -> 0 */ -+ write_reg(lcd, 9, 0x4055); -+ /* DSC -> 0 */ -+ write_reg(lcd, 5, 0x4003); -+ /* VCOMG -> 0 */ -+ write_reg(lcd, 10, 0x2103); -+ -+ msleep(1); -+ -+ /* AP[2:0] -> 000 */ -+ write_reg(lcd, 9, 0x4050); -+ -+out: -+ return ret; -+} -+ -+static int ltv350qv_power(struct ltv350qv *lcd, int power) -+{ -+ int ret = 0; -+ -+ down(&lcd->lock); -+ -+ 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; -+ -+ up(&lcd->lock); -+ -+ return ret; -+} -+ -+static int ltv350qv_set_power(struct lcd_device *ld, int power) -+{ -+ struct ltv350qv *lcd; -+ -+ lcd = class_get_devdata(&ld->class_dev); -+ return ltv350qv_power(lcd, power); -+} -+ -+static int ltv350qv_get_power(struct lcd_device *ld) -+{ -+ struct ltv350qv *lcd; -+ -+ lcd = class_get_devdata(&ld->class_dev); -+ return lcd->power; -+} -+ -+static struct lcd_properties lcd_properties = { -+ .owner = THIS_MODULE, -+ .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; -+ init_MUTEX(&lcd->lock); -+ lcd->buffer = kzalloc(8, GFP_KERNEL); -+ -+ spi->mode = SPI_MODE_3; -+ spi->bits_per_word = 8; -+ ret = spi_setup(spi); -+ if (ret) -+ goto out_free_lcd; -+ -+ ld = lcd_device_register("ltv350qv", lcd, &lcd_properties); -+ if (IS_ERR(ld)) { -+ ret = PTR_ERR(ld); -+ goto out_free_lcd; -+ } -+ lcd->ld = ld; -+ -+ list_add(&lcd->list, &lcd_list); -+ -+ ret = ltv350qv_power(lcd, FB_BLANK_UNBLANK); -+ if (ret) -+ goto out_unregister; -+ -+ dev_set_drvdata(&spi->dev, lcd); -+ -+ return 0; -+ -+out_unregister: -+ lcd_device_unregister(ld); -+out_free_lcd: -+ kfree(lcd); -+ return ret; -+} -+ -+static int __devexit ltv350qv_remove(struct spi_device *spi) -+{ -+ struct ltv350qv *lcd = dev_get_drvdata(&spi->dev); -+ -+ ltv350qv_power(lcd, FB_BLANK_POWERDOWN); -+ list_del(&lcd->list); -+ lcd_device_unregister(lcd->ld); -+ kfree(lcd); -+ -+ return 0; -+} -+ -+#ifdef CONFIG_PM -+static int ltv350qv_suspend(struct spi_device *spi, -+ pm_message_t state, u32 level) -+{ -+ struct ltv350qv *lcd = dev_get_drvdata(&spi->dev); -+ -+ if (level == SUSPEND_POWER_DOWN) -+ return ltv350qv_power(lcd, FB_BLANK_POWERDOWN); -+ -+ return 0; -+} -+ -+static int ltv350qv_resume(struct spi_device *spi, u32 level) -+{ -+ struct ltv350qv *lcd = dev_get_drvdata(&spi->dev); -+ -+ if (level == RESUME_POWER_ON) -+ return ltv350qv_power(lcd, FB_BLANK_UNBLANK); -+ -+ return 0; -+} -+#else -+#define ltv350qv_suspend NULL -+#define ltv350qv_resume NULL -+#endif -+ -+/* Power down all displays on reboot, poweroff or halt */ -+static int ltv350qv_halt(struct notifier_block *nb, unsigned long event, -+ void *p) -+{ -+ struct ltv350qv *lcd; -+ -+ list_for_each_entry(lcd, &lcd_list, list) { -+ if (!lcd->halt_done) -+ ltv350qv_power(lcd, FB_BLANK_POWERDOWN); -+ lcd->halt_done = 1; -+ } -+ -+ return NOTIFY_OK; -+} -+ -+static struct spi_driver ltv350qv_driver = { -+ .driver = { -+ .name = "ltv350qv", -+ .bus = &spi_bus_type, -+ .owner = THIS_MODULE, -+ }, -+ -+ .probe = ltv350qv_probe, -+ .remove = __devexit_p(ltv350qv_remove), -+ .suspend = ltv350qv_suspend, -+ .resume = ltv350qv_resume, -+}; -+ -+static struct notifier_block ltv350qv_notifier = { -+ .notifier_call = ltv350qv_halt, -+}; -+ -+static int __init ltv350qv_init(void) -+{ -+ register_reboot_notifier(<v350qv_notifier); -+ return spi_register_driver(<v350qv_driver); -+} -+ -+static void __exit ltv350qv_exit(void) -+{ -+ unregister_reboot_notifier(<v350qv_notifier); -+ spi_unregister_driver(<v350qv_driver); -+} -+module_init(ltv350qv_init); -+module_exit(ltv350qv_exit); -+ -+MODULE_AUTHOR("Atmel Norway"); -+MODULE_DESCRIPTION("Samsung LTV350QV LCD Driver"); -+MODULE_LICENSE("GPL"); -diff -urN linux-2.6.20.4-0rig/drivers/video/backlight/Makefile linux-2.6.20.4-atmel/drivers/video/backlight/Makefile ---- linux-2.6.20.4-0rig/drivers/video/backlight/Makefile 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/video/backlight/Makefile 2007-03-24 16:42:29.000000000 +0100 -@@ -5,3 +5,4 @@ - obj-$(CONFIG_BACKLIGHT_CORGI) += corgi_bl.o - obj-$(CONFIG_BACKLIGHT_HP680) += hp680_bl.o - obj-$(CONFIG_BACKLIGHT_LOCOMO) += locomolcd.o -+obj-$(CONFIG_LCD_LTV350QV) += ltv350qv.o -diff -urN linux-2.6.20.4-0rig/drivers/video/fbmem.c linux-2.6.20.4-atmel/drivers/video/fbmem.c ---- linux-2.6.20.4-0rig/drivers/video/fbmem.c 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/video/fbmem.c 2007-03-24 16:42:29.000000000 +0100 -@@ -1199,6 +1199,10 @@ - pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE; - #elif defined(__arm__) || defined(__sh__) || defined(__m32r__) - vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); -+#elif defined(__avr32__) -+ vma->vm_page_prot = __pgprot((pgprot_val(vma->vm_page_prot) -+ & ~_PAGE_CACHABLE) -+ | (_PAGE_BUFFER | _PAGE_DIRTY)); - #elif defined(__ia64__) - if (efi_range_is_wc(vma->vm_start, vma->vm_end - vma->vm_start)) - vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); -diff -urN linux-2.6.20.4-0rig/drivers/video/Kconfig linux-2.6.20.4-atmel/drivers/video/Kconfig ---- linux-2.6.20.4-0rig/drivers/video/Kconfig 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/video/Kconfig 2007-03-24 16:42:29.000000000 +0100 -@@ -276,6 +276,28 @@ - If you plan to use the LCD display with your SA-1100 system, say - Y here. - -+config FB_SIDSA -+ tristate "SIDSA LCDC support" -+ select FB_CFB_FILLRECT -+ select FB_CFB_COPYAREA -+ select FB_CFB_IMAGEBLIT -+ depends on FB && AVR32 -+ help -+ This enables support for the SIDSA LCD Controller. -+ -+config FB_SIDSA_DEFAULT_BPP -+ int "SIDSA LCDC default color depth" -+ default 24 -+ depends on FB_SIDSA -+ help -+ Specify the maximum color depth you want to be able to -+ support. This, together with the resolution of the LCD -+ panel, determines the amount of framebuffer memory allocated -+ when the driver is initialized. -+ -+ Allowable values are 1, 2, 4, 8, 16, 24 and 32. If unsure, -+ say 24. -+ - config FB_IMX - tristate "Motorola i.MX LCD support" - depends on FB && ARM && ARCH_IMX -@@ -698,6 +720,22 @@ - working with S1D13806). Product specs at - <http://www.erd.epson.com/vdc/html/legacy_13xxx.htm> - -+config FB_ATMEL -+ tristate "AT91/AT32 LCD Controller support" -+ depends on FB && (ARCH_AT91SAM9261 || ARCH_AT91SAM9263 || AVR32) -+ select FB_CFB_FILLRECT -+ select FB_CFB_COPYAREA -+ select FB_CFB_IMAGEBLIT -+ help -+ This enables support for the AT91/AT32 LCD Controller. -+ -+config FB_INTSRAM -+ bool "Frame Buffer in internal SRAM" -+ depends on FB_ATMEL && ARCH_AT91SAM9261 -+ help -+ Say Y if you want to map Frame Buffer in internal SRAM. Say N if you want -+ to let frame buffer in external SDRAM. -+ - config FB_NVIDIA - tristate "nVidia Framebuffer Support" - depends on FB && PCI -diff -urN linux-2.6.20.4-0rig/drivers/video/Makefile linux-2.6.20.4-atmel/drivers/video/Makefile ---- linux-2.6.20.4-0rig/drivers/video/Makefile 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/video/Makefile 2007-03-24 16:42:29.000000000 +0100 -@@ -78,6 +78,7 @@ - obj-$(CONFIG_FB_SUN3) += sun3fb.o - obj-$(CONFIG_FB_HIT) += hitfb.o - obj-$(CONFIG_FB_EPSON1355) += epson1355fb.o -+obj-$(CONFIG_FB_ATMEL) += atmel_lcdfb.o - obj-$(CONFIG_FB_PVR2) += pvr2fb.o - obj-$(CONFIG_FB_VOODOO1) += sstfb.o - obj-$(CONFIG_FB_ARMCLCD) += amba-clcd.o -@@ -100,6 +101,7 @@ - obj-$(CONFIG_FB_PNX4008_DUM) += pnx4008/ - obj-$(CONFIG_FB_PNX4008_DUM_RGB) += pnx4008/ - obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o -+obj-$(CONFIG_FB_SIDSA) += sidsafb.o - - # Platform or fallback drivers go here - obj-$(CONFIG_FB_VESA) += vesafb.o -diff -urN linux-2.6.20.4-0rig/drivers/video/sidsafb.c linux-2.6.20.4-atmel/drivers/video/sidsafb.c ---- linux-2.6.20.4-0rig/drivers/video/sidsafb.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/drivers/video/sidsafb.c 2007-03-24 16:42:29.000000000 +0100 -@@ -0,0 +1,860 @@ -+/* -+ * Framebuffer Driver for Atmel/SIDSA LCD Controller -+ * -+ * Copyright (C) 2004-2006 Atmel Corporation -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+#undef DEBUG -+ -+#include <linux/clk.h> -+#include <linux/completion.h> -+#include <linux/kernel.h> -+#include <linux/dma-mapping.h> -+#include <linux/interrupt.h> -+#include <linux/fb.h> -+#include <linux/init.h> -+#include <linux/delay.h> -+#include <linux/platform_device.h> -+ -+#include <asm/arch/board.h> -+ -+#include <asm/periph/lcdc.h> -+ -+/* More or less configurable parameters */ -+#define SIDSAFB_FIFO_SIZE 512 -+#define SIDSAFB_DMA_BURST_LEN 8 -+ -+/* TODO: These should be autogenerated from part description file */ -+#define LCDC_DISTYPE_STN_MONO 0 -+#define LCDC_DISTYPE_STN_COLOR 1 -+#define LCDC_DISTYPE_TFT 2 -+#define LCDC_LUT 0xc00 -+ -+struct sidsafb_info { -+ spinlock_t lock; -+ struct fb_info * info; -+ void __iomem * regs; -+ unsigned long irq_base; -+ int wait_for_vsync; -+ struct completion vsync_complete; -+ unsigned int guard_time; -+ struct clk *hclk; -+ struct clk *pixclk; -+ struct platform_device *pdev; -+ u32 pseudo_palette[16]; -+}; -+ -+/* -+ * How large framebuffer to allocate if none was provided by the -+ * platform. This default is the smallest we can possibly get away -+ * with. -+ */ -+static unsigned long fb_size = (320 * 240); -+ -+#if 0 -+static struct fb_videomode sony_modes[] = { -+ { -+ .refresh = 48, -+ .xres = 240, .yres = 160, -+ .pixclock = 520833, -+ -+ .left_margin = 7, .right_margin = 9, -+ .upper_margin = 19, .lower_margin = 20, -+ .hsync_len = 9, .vsync_len = 2, -+ -+ .sync = 0, -+ .vmode = FB_VMODE_NONINTERLACED, -+ }, -+}; -+#endif -+ -+#if 0 -+static struct fb_videomode vga_modes[] = { -+ { -+ .refresh = 122, -+ .xres = 320, .yres = 240, -+ .pixclock = 80000, -+ -+ .left_margin = 10, .right_margin = 20, -+ .upper_margin = 30, .lower_margin = 5, -+ .hsync_len = 20, .vsync_len = 3, -+ -+ .sync = 0, -+ .vmode = FB_VMODE_NONINTERLACED, -+ }, -+ { -+ .refresh = 70, -+ .xres = 640, .yres = 480, -+ .pixclock = 40000, -+ -+ .left_margin = 10, .right_margin = 20, -+ .upper_margin = 30, .lower_margin = 5, -+ .hsync_len = 20, .vsync_len = 3, -+ -+ .sync = 0, -+ .vmode = FB_VMODE_NONINTERLACED, -+ }, -+}; -+#else -+static struct fb_videomode samsung_modes[] = { -+ { -+ .refresh = 75, -+ .xres = 320, .yres = 240, -+ .pixclock = 145111, -+ -+ .left_margin = 17, .right_margin = 33, -+ .upper_margin = 10, .lower_margin = 10, -+ .hsync_len = 16, .vsync_len = 1, -+ -+ .sync = FB_SYNC_PCLK_RISING, -+ .vmode = FB_VMODE_NONINTERLACED, -+ }, -+}; -+#endif -+ -+#if 1 -+static struct fb_monspecs default_monspecs = { -+ .modedb = samsung_modes, -+ .manufacturer = "SNG", -+ .monitor = "LCD panel", -+ .serial_no = "xxxx", -+ .ascii = "yyyy", -+ .modedb_len = ARRAY_SIZE(samsung_modes), -+ .hfmin = 14820, -+ .hfmax = 22230, -+ .vfmin = 60, -+ .vfmax = 90, -+ .dclkmax = 30000000, -+}; -+#endif -+ -+#if 0 -+static struct fb_monspecs default_monspecs = { -+ .modedb = sony_modes, -+ .manufacturer = "SNY", /* 4 chars?!? */ -+ .monitor = "LCD panel", -+ .serial_no = "xxxx", -+ .ascii = "yyyy", -+ .modedb_len = ARRAY_SIZE(sony_modes), -+ .hfmin = 7000, -+ .hfmax = 8000, -+ .vfmin = 45, -+ .vfmax = 50, -+}; -+// #else -+static struct fb_monspecs default_monspecs = { -+ .modedb = vga_modes, -+ .manufacturer = "VGA", -+ .monitor = "Generic VGA", -+ .serial_no = "xxxx", -+ .ascii = "yyyy", -+ .modedb_len = ARRAY_SIZE(vga_modes), -+ .hfmin = 30000, -+ .hfmax = 64000, -+ .vfmin = 50, -+ .vfmax = 150, -+}; -+#endif -+ -+/* Driver defaults */ -+static struct fb_fix_screeninfo sidsafb_fix __devinitdata = { -+ .id = "sidsafb", -+ .type = FB_TYPE_PACKED_PIXELS, -+ .visual = FB_VISUAL_TRUECOLOR, -+ .xpanstep = 1, -+ .ypanstep = 1, -+ .ywrapstep = 0, -+ .accel = FB_ACCEL_NONE, -+}; -+ -+/* -+ * Let the user decide whether FBIOPAN_DISPLAY waits for the next -+ * vsync or not. -+ */ -+static ssize_t -+vsync_pan_show(struct device *dev, struct device_attribute *attr, char *buf) -+{ -+ struct fb_info *info = dev_get_drvdata(dev); -+ struct sidsafb_info *sinfo = info->par; -+ -+ return sprintf(buf, "%d\n", sinfo->wait_for_vsync); -+} -+ -+static ssize_t -+vsync_pan_store(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct fb_info *info = dev_get_drvdata(dev); -+ struct sidsafb_info *sinfo = info->par; -+ unsigned long val; -+ -+ val = simple_strtoul(buf, NULL, 0); -+ if (val) -+ sinfo->wait_for_vsync = 1; -+ else -+ sinfo->wait_for_vsync = 0; -+ -+ return count; -+} -+ -+static DEVICE_ATTR(vsync_pan, 0644, vsync_pan_show, vsync_pan_store); -+ -+static void sidsafb_update_dma(struct fb_info *info, -+ struct fb_var_screeninfo *var) -+{ -+ struct sidsafb_info *sinfo = info->par; -+ struct fb_fix_screeninfo *fix = &info->fix; -+ unsigned long dma_addr; -+ unsigned long pixeloff; -+ unsigned long dma2dcfg; -+ -+ dma_addr = (fix->smem_start + var->yoffset * fix->line_length -+ + var->xoffset * var->bits_per_pixel / 8); -+ -+ dma_addr &= ~3UL; -+ pixeloff = LCDC_MKBF(DMA2DCFG_PIXELOFF, var->xoffset * var->bits_per_pixel); -+ -+ /* Set framebuffer DMA base address and pixel offset */ -+ lcdc_writel(sinfo, DMABADDR1, dma_addr); -+ dma2dcfg = lcdc_readl(sinfo, DMA2DCFG); -+ dma2dcfg = LCDC_INSBF(DMA2DCFG_PIXELOFF, pixeloff, dma2dcfg); -+ lcdc_writel(sinfo, DMA2DCFG, dma2dcfg); -+ -+ /* Update configuration */ -+ lcdc_writel(sinfo, DMACON, (lcdc_readl(sinfo, DMACON) -+ | LCDC_BIT(DMACON_DMAUPDT))); -+} -+ -+/** -+ * sidsafb_check_var - Validates a var passed in. -+ * @var: frame buffer variable screen structure -+ * @info: frame buffer structure that represents a single frame buffer -+ * -+ * Checks to see if the hardware supports the state requested by -+ * var passed in. This function does not alter the hardware -+ * state!!! This means the data stored in struct fb_info and -+ * struct sidsafb_info do not change. This includes the var -+ * inside of struct fb_info. Do NOT change these. This function -+ * can be called on its own if we intent to only test a mode and -+ * not actually set it. The stuff in modedb.c is a example of -+ * this. If the var passed in is slightly off by what the -+ * hardware can support then we alter the var PASSED in to what -+ * we can do. If the hardware doesn't support mode change a -+ * -EINVAL will be returned by the upper layers. You don't need -+ * to implement this function then. If you hardware doesn't -+ * support changing the resolution then this function is not -+ * needed. In this case the driver would just provide a var that -+ * represents the static state the screen is in. -+ * -+ * Returns negative errno on error, or zero on success. -+ */ -+static int sidsafb_check_var(struct fb_var_screeninfo *var, -+ struct fb_info *info) -+{ -+ unsigned long new_fb_size; -+ -+ pr_debug("sidsafb_check_var:\n"); -+ pr_debug(" resolution: %ux%u\n", var->xres, var->yres); -+ pr_debug(" pixclk: %llu Hz\n", 1000000000000ULL / var->pixclock); -+ pr_debug(" bpp: %u\n", var->bits_per_pixel); -+ -+ new_fb_size = (var->xres_virtual * var->yres_virtual -+ * ((var->bits_per_pixel + 7) / 8)); -+ if (new_fb_size > info->fix.smem_len) { -+ printk(KERN_NOTICE -+ "sidsafb: %uB framebuffer too small for %ux%ux%u\n", -+ info->fix.smem_len, var->xres_virtual, -+ var->yres_virtual, var->bits_per_pixel); -+ return -EINVAL; -+ } -+ -+ /* Force same alignment for each line */ -+ var->xres = (var->xres + 3) & ~3UL; -+ var->xres_virtual = (var->xres_virtual + 3) & ~3UL; -+ -+ var->red.msb_right = var->green.msb_right = var->blue.msb_right = 0; -+ var->transp.offset = var->transp.length = 0; -+ -+ switch (var->bits_per_pixel) { -+ case 2: -+ case 4: -+ case 8: -+ var->red.offset = var->green.offset = var->blue.offset = 0; -+ var->red.length = var->green.length = var->blue.length -+ = var->bits_per_pixel; -+ break; -+ case 15: -+ case 16: -+ /* -+ * Bit 16 is the "intensity" bit, I think. Not sure -+ * what we're going to use that for... -+ */ -+ var->red.offset = 0; -+ var->green.offset = 5; -+ var->blue.offset = 10; -+ var->red.length = 5; -+ var->green.length = 5; -+ var->blue.length = 5; -+ break; -+ case 32: -+ var->transp.offset = 24; -+ var->transp.length = 8; -+ /* fall through */ -+ case 24: -+ var->red.offset = 16; -+ var->green.offset = 8; -+ var->blue.offset = 0; -+ var->red.length = var->green.length = var->blue.length = 8; -+ break; -+ default: -+ printk(KERN_NOTICE "sidsafb: color depth %d not supported\n", -+ var->bits_per_pixel); -+ return -EINVAL; -+ } -+ -+ var->xoffset = var->yoffset = 0; -+ var->red.msb_right = var->green.msb_right = var->blue.msb_right = -+ var->transp.msb_right = 0; -+ -+ return 0; -+} -+ -+/** -+ * sidsafb_set_par - Alters the hardware state. -+ * @info: frame buffer structure that represents a single frame buffer -+ * -+ * Using the fb_var_screeninfo in fb_info we set the resolution -+ * of the this particular framebuffer. This function alters the -+ * par AND the fb_fix_screeninfo stored in fb_info. It doesn't -+ * not alter var in fb_info since we are using that data. This -+ * means we depend on the data in var inside fb_info to be -+ * supported by the hardware. sidsafb_check_var is always called -+ * before sidsafb_set_par to ensure this. Again if you can't -+ * change the resolution you don't need this function. -+ * -+ */ -+static int sidsafb_set_par(struct fb_info *info) -+{ -+ struct sidsafb_info *sinfo = info->par; -+ unsigned long value; -+ -+ pr_debug("sidsafb_set_par:\n"); -+ pr_debug(" * resolution: %ux%u (%ux%u virtual)\n", -+ info->var.xres, info->var.yres, -+ info->var.xres_virtual, info->var.yres_virtual); -+ -+ /* Turn off the LCD controller and the DMA controller */ -+ pr_debug("writing 0x%08x to %p\n", -+ LCDC_MKBF(PWRCON_GUARD_TIME, sinfo->guard_time), -+ sinfo->regs + LCDC_PWRCON); -+ lcdc_writel(sinfo, PWRCON, -+ LCDC_MKBF(PWRCON_GUARD_TIME, sinfo->guard_time)); -+ pr_debug("writing 0 to %p\n", sinfo->regs + LCDC_DMACON); -+ lcdc_writel(sinfo, DMACON, 0); -+ -+ info->fix.line_length = (info->var.xres_virtual -+ * (info->var.bits_per_pixel / 8)); -+ -+ if (info->var.bits_per_pixel <= 8) -+ info->fix.visual = FB_VISUAL_PSEUDOCOLOR; -+ else -+ info->fix.visual = FB_VISUAL_TRUECOLOR; -+ -+ /* Re-initialize the DMA engine... */ -+ pr_debug(" * update DMA engine\n"); -+ sidsafb_update_dma(info, &info->var); -+ -+ /* ...set frame size and burst length = 8 words (?) */ -+ value = LCDC_MKBF(DMAFRMCFG_FRMSIZE, -+ (info->var.yres * info->fix.line_length + 3) / 4); -+ value |= LCDC_MKBF(DMAFRMCFG_BRSTLEN, (SIDSAFB_DMA_BURST_LEN - 1)); -+ lcdc_writel(sinfo, DMAFRMCFG, value); -+ -+ /* ...set 2D configuration (necessary for xres_virtual != xres) */ -+ value = LCDC_MKBF(DMA2DCFG_ADDRINC, -+ info->var.xres_virtual - info->var.xres); -+ lcdc_writel(sinfo, DMA2DCFG, value); -+ -+ /* ...wait for DMA engine to become idle... */ -+ while (lcdc_readl(sinfo, DMACON) & LCDC_BIT(DMACON_DMABUSY)) -+ msleep(10); -+ -+ pr_debug(" * re-enable DMA engine\n"); -+ /* ...and enable it with updated configuration */ -+ lcdc_writel(sinfo, DMACON, (LCDC_BIT(DMACON_DMAEN) -+ | LCDC_BIT(DMACON_DMAUPDT) -+ | LCDC_BIT(DMACON_DMA2DEN))); -+ -+ /* Now, the LCD core... */ -+ -+ /* Set pixel clock. */ -+ value = (clk_get_rate(sinfo->pixclk) / 100000) * info->var.pixclock; -+ value /= 10000000; -+ value = (value + 1) / 2; -+ if (value == 0) { -+ printk("sidsafb: Bypassing lcdc_pclk divider\n"); -+ lcdc_writel(sinfo, LCDCON1, LCDC_BIT(LCDCON1_BYPASS)); -+ } else { -+ lcdc_writel(sinfo, LCDCON1, LCDC_MKBF(LCDCON1_CLKVAL, value - 1)); -+ } -+ -+ /* Initialize control register 2 */ -+ value = (LCDC_BIT(LCDCON2_CLKMOD) -+ | LCDC_MKBF(LCDCON2_DISTYPE, LCDC_DISTYPE_TFT)); -+ if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT)) -+ value |= LCDC_BIT(LCDCON2_INVLINE); -+ if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT)) -+ value |= LCDC_BIT(LCDCON2_INVFRAME); -+ if (info->var.sync & FB_SYNC_PCLK_RISING) -+ value |= LCDC_BIT(LCDCON2_INVCLK); -+ -+ switch (info->var.bits_per_pixel) { -+ case 1: value |= LCDC_MKBF(LCDCON2_PIXELSIZE, 0); break; -+ case 2: value |= LCDC_MKBF(LCDCON2_PIXELSIZE, 1); break; -+ case 4: value |= LCDC_MKBF(LCDCON2_PIXELSIZE, 2); break; -+ case 8: value |= LCDC_MKBF(LCDCON2_PIXELSIZE, 3); break; -+ case 15: /* fall through */ -+ case 16: value |= LCDC_MKBF(LCDCON2_PIXELSIZE, 4); break; -+ case 24: value |= LCDC_MKBF(LCDCON2_PIXELSIZE, 5); break; -+ case 32: value |= LCDC_MKBF(LCDCON2_PIXELSIZE, 6); break; -+ default: BUG(); break; -+ } -+ pr_debug(" * LCDCON2 = %08lx\n", value); -+ lcdc_writel(sinfo, LCDCON2, value); -+ -+ /* Vertical timing */ -+ value = LCDC_MKBF(LCDTIM1_VPW, info->var.vsync_len - 1); -+ value |= LCDC_MKBF(LCDTIM1_VBP, info->var.upper_margin); -+ value |= LCDC_MKBF(LCDTIM1_VFP, info->var.lower_margin); -+ pr_debug(" * LCDTIM1 = %08lx\n", value); -+ lcdc_writel(sinfo, LCDTIM1, value); -+ -+ /* Horizontal timing */ -+ value = LCDC_MKBF(LCDTIM2_HFP, info->var.right_margin - 1); -+ value |= LCDC_MKBF(LCDTIM2_HPW, info->var.hsync_len - 1); -+ value |= LCDC_MKBF(LCDTIM2_HBP, info->var.left_margin - 1); -+ pr_debug(" * LCDTIM2 = %08lx\n", value); -+ lcdc_writel(sinfo, LCDTIM2, value); -+ -+ /* Display size */ -+ value = LCDC_MKBF(LCDFRMCFG_LINESIZE, info->var.xres - 1); -+ value |= LCDC_MKBF(LCDFRMCFG_LINEVAL, info->var.yres - 1); -+ lcdc_writel(sinfo, LCDFRMCFG, value); -+ -+ /* FIFO Threshold: Use formula from data sheet */ -+ value = SIDSAFB_FIFO_SIZE - (2 * SIDSAFB_DMA_BURST_LEN + 3); -+ lcdc_writel(sinfo, LCDFIFO, value); -+ -+ /* Toggle LCD_MODE every frame */ -+ lcdc_writel(sinfo, LCDMVAL, 0); -+ -+ /* Disable all interrupts */ -+ lcdc_writel(sinfo, LCD_IDR, ~0UL); -+ -+ /* Wait for the LCDC core to become idle and enable it */ -+ while(lcdc_readl(sinfo, PWRCON) & LCDC_BIT(PWRCON_LCD_BUSY)) -+ msleep(10); -+ -+ pr_debug(" * re-enable LCD core\n"); -+ lcdc_writel(sinfo, PWRCON, -+ LCDC_MKBF(PWRCON_GUARD_TIME, sinfo->guard_time) -+ | LCDC_BIT(PWRCON_LCD_PWR)); -+ -+ pr_debug(" * DONE\n"); -+ return 0; -+} -+ -+static inline u_int chan_to_field(u_int chan, const struct fb_bitfield *bf) -+{ -+ chan &= 0xffff; -+ chan >>= 16 - bf->length; -+ return chan << bf->offset; -+} -+ -+/** -+ * sidsafb_setcolreg - Optional function. Sets a color register. -+ * @regno: Which register in the CLUT we are programming -+ * @red: The red value which can be up to 16 bits wide -+ * @green: The green value which can be up to 16 bits wide -+ * @blue: The blue value which can be up to 16 bits wide. -+ * @transp: If supported the alpha value which can be up to 16 bits wide. -+ * @info: frame buffer info structure -+ * -+ * Set a single color register. The values supplied have a 16 bit -+ * magnitude which needs to be scaled in this function for the hardware. -+ * Things to take into consideration are how many color registers, if -+ * any, are supported with the current color visual. With truecolor mode -+ * no color palettes are supported. Here a psuedo palette is created -+ * which we store the value in pseudo_palette in struct fb_info. For -+ * pseudocolor mode we have a limited color palette. To deal with this -+ * we can program what color is displayed for a particular pixel value. -+ * DirectColor is similar in that we can program each color field. If -+ * we have a static colormap we don't need to implement this function. -+ * -+ * Returns negative errno on error, or zero on success. In an -+ * ideal world, this would have been the case, but as it turns -+ * out, the other drivers return 1 on failure, so that's what -+ * we're going to do. -+ */ -+static int sidsafb_setcolreg(unsigned int regno, unsigned int red, -+ unsigned int green, unsigned int blue, -+ unsigned int transp, struct fb_info *info) -+{ -+ struct sidsafb_info *sinfo = info->par; -+ unsigned int val; -+ u32 *pal; -+ int ret = 1; -+ -+ if (info->var.grayscale) -+ red = green = blue = (19595 * red + 38470 * green -+ + 7471 * blue) >> 16; -+ -+ switch (info->fix.visual) { -+ case FB_VISUAL_TRUECOLOR: -+ if (regno < 16) { -+ pal = info->pseudo_palette; -+ -+ val = chan_to_field(red, &info->var.red); -+ val |= chan_to_field(green, &info->var.green); -+ val |= chan_to_field(blue, &info->var.blue); -+ -+ pal[regno] = val; -+ ret = 0; -+ } -+ break; -+ -+ case FB_VISUAL_PSEUDOCOLOR: -+ if (regno < 256) { -+ val = ((red >> 11) & 0x001f); -+ val |= ((green >> 6) & 0x03e0); -+ val |= ((blue >> 1) & 0x7c00); -+ -+ /* -+ * TODO: intensity bit. Maybe something like -+ * ~(red[10] ^ green[10] ^ blue[10]) & 1 -+ */ -+ -+ lcdc_writel(sinfo, LUT + regno * 4, val); -+ ret = 0; -+ } -+ break; -+ } -+ -+ return ret; -+} -+ -+static int sidsafb_pan_display(struct fb_var_screeninfo *var, -+ struct fb_info *info) -+{ -+ struct sidsafb_info *sinfo = info->par; -+ -+ pr_debug("sidsafb_pan_display\n"); -+ -+ sidsafb_update_dma(info, var); -+ -+ if (sinfo->wait_for_vsync) { -+ spin_lock_irq(&sinfo->lock); -+ lcdc_writel(sinfo, LCD_ICR, LCDC_BIT(LCD_ICR_EOFIC)); -+ lcdc_writel(sinfo, LCD_IER, LCDC_BIT(LCD_IER_EOFIE)); -+ init_completion(&sinfo->vsync_complete); -+ lcdc_readl(sinfo, LCD_IMR); -+ spin_unlock_irq(&sinfo->lock); -+ -+ wait_for_completion(&sinfo->vsync_complete); -+ -+ lcdc_writel(sinfo, LCD_IDR, LCDC_BIT(LCD_IDR_EOFID)); -+ } -+ -+ return 0; -+} -+ -+static struct fb_ops sidsafb_ops = { -+ .owner = THIS_MODULE, -+ .fb_check_var = sidsafb_check_var, -+ .fb_set_par = sidsafb_set_par, -+ .fb_setcolreg = sidsafb_setcolreg, -+ .fb_pan_display = sidsafb_pan_display, -+ .fb_fillrect = cfb_fillrect, -+ .fb_copyarea = cfb_copyarea, -+ .fb_imageblit = cfb_imageblit, -+}; -+ -+static irqreturn_t sidsafb_interrupt(int irq, void *dev_id) -+{ -+ struct fb_info *info = dev_id; -+ struct sidsafb_info *sinfo = info->par; -+ u32 status; -+ -+ status = lcdc_readl(sinfo, LCD_ISR); -+ while (status) { -+ if (status & LCDC_BIT(LCD_ISR_EOFIS)) { -+ pr_debug("sidsafb: DMA End Of Frame interrupt\n"); -+ -+ lcdc_writel(sinfo, LCD_ICR, LCDC_BIT(LCD_ICR_EOFIC)); -+ status &= ~LCDC_BIT(LCD_ISR_EOFIS); -+ complete(&sinfo->vsync_complete); -+ } -+ -+ if (status) { -+ printk(KERN_ERR -+ "LCDC: Interrupts still pending: 0x%x\n", -+ status); -+ lcdc_writel(sinfo, LCD_IDR, status); -+ } -+ -+ status = lcdc_readl(sinfo, LCD_ISR); -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+static void __devinit init_pseudo_palette(u32 *palette) -+{ -+ static const u32 init_palette[16] = { -+ 0x000000, -+ 0xaa0000, -+ 0x00aa00, -+ 0xaa5500, -+ 0x0000aa, -+ 0xaa00aa, -+ 0x00aaaa, -+ 0xaaaaaa, -+ 0x555555, -+ 0xff5555, -+ 0x55ff55, -+ 0xffff55, -+ 0x5555ff, -+ 0xff55ff, -+ 0x55ffff, -+ 0xffffff -+ }; -+ -+ memcpy(palette, init_palette, sizeof(init_palette)); -+} -+ -+static int __devinit sidsafb_set_fbinfo(struct sidsafb_info *sinfo) -+{ -+ struct fb_info *info = sinfo->info; -+ -+ init_pseudo_palette(sinfo->pseudo_palette); -+ -+ info->flags = (FBINFO_DEFAULT -+ | FBINFO_PARTIAL_PAN_OK -+ | FBINFO_HWACCEL_XPAN -+ | FBINFO_HWACCEL_YPAN); -+ memcpy(&info->fix, &sidsafb_fix, sizeof(info->fix)); -+ memcpy(&info->monspecs, &default_monspecs, sizeof(info->monspecs)); -+ info->fbops = &sidsafb_ops; -+ info->pseudo_palette = sinfo->pseudo_palette; -+ -+ return 0; -+} -+ -+static int __devinit sidsafb_probe(struct platform_device *pdev) -+{ -+ struct lcdc_platform_data *fb_data = pdev->dev.platform_data; -+ struct fb_info *info; -+ struct sidsafb_info *sinfo; -+ const struct resource *mmio_resource; -+ int ret; -+ -+ pr_debug("sidsafb_probe BEGIN\n"); -+ -+ mmio_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!mmio_resource) { -+ dev_err(&pdev->dev, "no MMIO resource found\n"); -+ return -ENXIO; -+ } -+ -+ ret = -ENOMEM; -+ info = framebuffer_alloc(sizeof(struct sidsafb_info), &pdev->dev); -+ if (!info) { -+ dev_err(&pdev->dev, "failed to allocate memory\n"); -+ goto out; -+ } -+ -+ sinfo = info->par; -+ sinfo->info = info; -+ sinfo->pdev = pdev; -+ sinfo->guard_time = 1; -+ -+ spin_lock_init(&sinfo->lock); -+ sidsafb_set_fbinfo(sinfo); -+ info->fix.mmio_start = mmio_resource->start; -+ info->fix.mmio_len = mmio_resource->end - mmio_resource->start + 1; -+ sinfo->irq_base = platform_get_irq(pdev, 0); -+ -+ sinfo->hclk = clk_get(&pdev->dev, "hclk"); -+ if (IS_ERR(sinfo->hclk)) { -+ dev_err(&pdev->dev, "failed to get hclk\n"); -+ ret = PTR_ERR(sinfo->hclk); -+ goto free_info; -+ } -+ sinfo->pixclk = clk_get(&pdev->dev, "pixclk"); -+ if (IS_ERR(sinfo->pixclk)) { -+ dev_err(&pdev->dev, "failed to get pixel clock\n"); -+ ret = PTR_ERR(sinfo->hclk); -+ goto put_hclk; -+ } -+ -+ clk_enable(sinfo->hclk); -+ clk_enable(sinfo->pixclk); -+ -+ /* Use platform-supplied framebuffer memory if available */ -+ if (fb_data && fb_data->fbmem_size != 0) { -+ info->fix.smem_start = fb_data->fbmem_start; -+ info->fix.smem_len = fb_data->fbmem_size; -+ info->screen_base = ioremap(info->fix.smem_start, -+ info->fix.smem_len); -+ } else { -+ dma_addr_t paddr; -+ -+ info->fix.smem_len = fb_size; -+ info->screen_base = dma_alloc_coherent(&pdev->dev, fb_size, -+ &paddr, GFP_KERNEL); -+ info->fix.smem_start = paddr; -+ } -+ -+ if (!info->screen_base) { -+ printk(KERN_ERR "sidsafb: Could not allocate framebuffer\n"); -+ goto disable_clocks; -+ } -+ -+ sinfo->regs = ioremap(info->fix.mmio_start, info->fix.mmio_len); -+ if (!sinfo->regs) { -+ printk(KERN_ERR "sidsafb: Could not map LCDC registers\n"); -+ goto free_fb; -+ } -+ -+ ret = fb_find_mode(&info->var, info, NULL, info->monspecs.modedb, -+ info->monspecs.modedb_len, info->monspecs.modedb, -+ CONFIG_FB_SIDSA_DEFAULT_BPP); -+ if (!ret) { -+ printk(KERN_ERR "sidsafb: No suitable video mode found\n"); -+ goto unmap_regs; -+ } -+ -+ ret = request_irq(sinfo->irq_base, sidsafb_interrupt, 0, -+ "sidsafb", info); -+ if (ret) -+ goto unmap_regs; -+ -+ /* Allocate colormap */ -+ if (fb_alloc_cmap(&info->cmap, 256, 0)) { -+ ret = -ENOMEM; -+ goto unregister_irqs; -+ } -+ -+ platform_set_drvdata(pdev, info); -+ ret = device_create_file(&pdev->dev, &dev_attr_vsync_pan); -+ if (ret) -+ goto free_cmap; -+ -+ /* -+ * Tell the world that we're ready to go -+ */ -+ ret = register_framebuffer(info); -+ if (ret) -+ goto remove_attrs; -+ -+ printk("fb%d: Atmel LCDC at 0x%08lx (mapped at %p), irq %lu\n", -+ info->node, info->fix.mmio_start, sinfo->regs, sinfo->irq_base); -+ -+ memset_io(info->screen_base, 0, info->fix.smem_len); -+ info->var.activate |= FB_ACTIVATE_FORCE | FB_ACTIVATE_NOW; -+ ret = fb_set_var(info, &info->var); -+ if (ret) -+ printk(KERN_WARNING -+ "sidsafb: Unable to set display parameters\n"); -+ info->var.activate &= ~(FB_ACTIVATE_FORCE | FB_ACTIVATE_NOW); -+ -+ pr_debug("sidsafb_probe SUCCESS\n"); -+ return 0; -+ -+ -+remove_attrs: -+ device_remove_file(&pdev->dev, &dev_attr_vsync_pan); -+free_cmap: -+ fb_dealloc_cmap(&info->cmap); -+unregister_irqs: -+ free_irq(sinfo->irq_base, info); -+unmap_regs: -+ iounmap(sinfo->regs); -+free_fb: -+ if (!fb_data || fb_data->fbmem_size == 0) -+ dma_free_coherent(&pdev->dev, info->fix.smem_len, -+ (void __force *)info->screen_base, -+ info->fix.smem_start); -+disable_clocks: -+ clk_disable(sinfo->pixclk); -+ clk_disable(sinfo->hclk); -+ clk_put(sinfo->pixclk); -+put_hclk: -+ clk_put(sinfo->hclk); -+free_info: -+ framebuffer_release(info); -+out: -+ pr_debug("sidsafb_probe FAILED\n"); -+ return ret; -+} -+ -+static int __devexit sidsafb_remove(struct platform_device *pdev) -+{ -+ struct lcdc_platform_data *fb_data = pdev->dev.platform_data; -+ struct fb_info *info = platform_get_drvdata(pdev); -+ struct sidsafb_info *sinfo; -+ -+ if (!info) -+ return 0; -+ sinfo = info->par; -+ -+ /* TODO: Restore original state */ -+ unregister_framebuffer(info); -+ -+ device_remove_file(&pdev->dev, &dev_attr_vsync_pan); -+ -+ fb_dealloc_cmap(&info->cmap); -+ free_irq(sinfo->irq_base, info); -+ iounmap(sinfo->regs); -+ if (!fb_data || fb_data->fbmem_size == 0) -+ dma_free_coherent(&pdev->dev, info->fix.smem_len, -+ (void __force *)info->screen_base, -+ info->fix.smem_start); -+ clk_disable(sinfo->hclk); -+ clk_put(sinfo->hclk); -+ platform_set_drvdata(pdev, NULL); -+ framebuffer_release(info); -+ -+ return 0; -+} -+ -+static struct platform_driver sidsafb_driver = { -+ .probe = sidsafb_probe, -+ .remove = __devexit_p(sidsafb_remove), -+ .driver = { -+ .name = "lcdc", -+ }, -+}; -+ -+int __init sidsafb_init(void) -+{ -+ return platform_driver_register(&sidsafb_driver); -+} -+ -+static void __exit sidsafb_exit(void) -+{ -+ platform_driver_unregister(&sidsafb_driver); -+} -+ -+module_init(sidsafb_init); -+module_exit(sidsafb_exit); -+ -+module_param(fb_size, ulong, 0644); -+MODULE_PARM_DESC(fb_size, "Minimum framebuffer size to allocate"); -+ -+MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>"); -+MODULE_DESCRIPTION("Atmel/SIDSA LCD Controller framebuffer driver"); -+MODULE_LICENSE("GPL"); -diff -urN linux-2.6.20.4-0rig/include/asm-arm/arch-at91rm9200/at91_dbgu.h linux-2.6.20.4-atmel/include/asm-arm/arch-at91rm9200/at91_dbgu.h ---- linux-2.6.20.4-0rig/include/asm-arm/arch-at91rm9200/at91_dbgu.h 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/asm-arm/arch-at91rm9200/at91_dbgu.h 2007-03-24 16:39:15.000000000 +0100 -@@ -35,6 +35,20 @@ - #define AT91_CIDR_NVPSIZ (0xf << 8) /* Nonvolatile Program Memory Size */ - #define AT91_CIDR_NVPSIZ2 (0xf << 12) /* Second Nonvolatile Program Memory Size */ - #define AT91_CIDR_SRAMSIZ (0xf << 16) /* Internal SRAM Size */ -+#define AT91_CIDR_SRAMSIZ_1K (1 << 16) -+#define AT91_CIDR_SRAMSIZ_2K (2 << 16) -+#define AT91_CIDR_SRAMSIZ_112K (4 << 16) -+#define AT91_CIDR_SRAMSIZ_4K (5 << 16) -+#define AT91_CIDR_SRAMSIZ_80K (6 << 16) -+#define AT91_CIDR_SRAMSIZ_160K (7 << 16) -+#define AT91_CIDR_SRAMSIZ_8K (8 << 16) -+#define AT91_CIDR_SRAMSIZ_16K (9 << 16) -+#define AT91_CIDR_SRAMSIZ_32K (10 << 16) -+#define AT91_CIDR_SRAMSIZ_64K (11 << 16) -+#define AT91_CIDR_SRAMSIZ_128K (12 << 16) -+#define AT91_CIDR_SRAMSIZ_256K (13 << 16) -+#define AT91_CIDR_SRAMSIZ_96K (14 << 16) -+#define AT91_CIDR_SRAMSIZ_512K (15 << 16) - #define AT91_CIDR_ARCH (0xff << 20) /* Architecture Identifier */ - #define AT91_CIDR_NVPTYP (7 << 28) /* Nonvolatile Program Memory Type */ - #define AT91_CIDR_EXT (1 << 31) /* Extension Flag */ -diff -urN linux-2.6.20.4-0rig/include/asm-arm/arch-at91rm9200/at91_mci.h linux-2.6.20.4-atmel/include/asm-arm/arch-at91rm9200/at91_mci.h ---- linux-2.6.20.4-0rig/include/asm-arm/arch-at91rm9200/at91_mci.h 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/asm-arm/arch-at91rm9200/at91_mci.h 2007-03-24 16:39:15.000000000 +0100 -@@ -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 */ -diff -urN linux-2.6.20.4-0rig/include/asm-arm/arch-at91rm9200/at91_pdc.h linux-2.6.20.4-atmel/include/asm-arm/arch-at91rm9200/at91_pdc.h ---- linux-2.6.20.4-0rig/include/asm-arm/arch-at91rm9200/at91_pdc.h 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/asm-arm/arch-at91rm9200/at91_pdc.h 1970-01-01 01:00:00.000000000 +0100 -@@ -1,36 +0,0 @@ --/* -- * include/asm-arm/arch-at91rm9200/at91_pdc.h -- * -- * Copyright (C) 2005 Ivan Kokshaysky -- * Copyright (C) SAN People -- * -- * Peripheral Data Controller (PDC) registers. -- * Based on AT91RM9200 datasheet revision E. -- * -- * 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_PDC_H --#define AT91_PDC_H -- --#define AT91_PDC_RPR 0x100 /* Receive Pointer Register */ --#define AT91_PDC_RCR 0x104 /* Receive Counter Register */ --#define AT91_PDC_TPR 0x108 /* Transmit Pointer Register */ --#define AT91_PDC_TCR 0x10c /* Transmit Counter Register */ --#define AT91_PDC_RNPR 0x110 /* Receive Next Pointer Register */ --#define AT91_PDC_RNCR 0x114 /* Receive Next Counter Register */ --#define AT91_PDC_TNPR 0x118 /* Transmit Next Pointer Register */ --#define AT91_PDC_TNCR 0x11c /* Transmit Next Counter Register */ -- --#define AT91_PDC_PTCR 0x120 /* Transfer Control Register */ --#define AT91_PDC_RXTEN (1 << 0) /* Receiver Transfer Enable */ --#define AT91_PDC_RXTDIS (1 << 1) /* Receiver Transfer Disable */ --#define AT91_PDC_TXTEN (1 << 8) /* Transmitter Transfer Enable */ --#define AT91_PDC_TXTDIS (1 << 9) /* Transmitter Transfer Disable */ -- --#define AT91_PDC_PTSR 0x124 /* Transfer Status Register */ -- --#endif -diff -urN linux-2.6.20.4-0rig/include/asm-arm/arch-at91rm9200/at91_rstc.h linux-2.6.20.4-atmel/include/asm-arm/arch-at91rm9200/at91_rstc.h ---- linux-2.6.20.4-0rig/include/asm-arm/arch-at91rm9200/at91_rstc.h 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/asm-arm/arch-at91rm9200/at91_rstc.h 2007-03-24 16:39:16.000000000 +0100 -@@ -17,7 +17,7 @@ - #define AT91_RSTC_PROCRST (1 << 0) /* Processor Reset */ - #define AT91_RSTC_PERRST (1 << 2) /* Peripheral Reset */ - #define AT91_RSTC_EXTRST (1 << 3) /* External Reset */ --#define AT91_RSTC_KEY (0xff << 24) /* KEY Password */ -+#define AT91_RSTC_KEY (0xa5 << 24) /* KEY Password */ - - #define AT91_RSTC_SR (AT91_RSTC + 0x04) /* Reset Controller Status Register */ - #define AT91_RSTC_URSTS (1 << 0) /* User Reset Status */ -@@ -34,6 +34,5 @@ - #define AT91_RSTC_URSTEN (1 << 0) /* User Reset Enable */ - #define AT91_RSTC_URSTIEN (1 << 4) /* User Reset Interrupt Enable */ - #define AT91_RSTC_ERSTL (0xf << 8) /* External Reset Length */ --#define AT91_RSTC_KEY (0xff << 24) /* KEY Password */ - - #endif -diff -urN linux-2.6.20.4-0rig/include/asm-arm/arch-at91rm9200/at91sam9260.h linux-2.6.20.4-atmel/include/asm-arm/arch-at91rm9200/at91sam9260.h ---- linux-2.6.20.4-0rig/include/asm-arm/arch-at91rm9200/at91sam9260.h 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/asm-arm/arch-at91rm9200/at91sam9260.h 2007-03-24 16:39:16.000000000 +0100 -@@ -113,6 +113,10 @@ - - #define AT91SAM9260_UHP_BASE 0x00500000 /* USB Host controller */ - -+#define AT91SAM9XE_FLASH_BASE 0x00200000 /* Internal FLASH base address */ -+#define AT91SAM9XE_SRAM_BASE 0x00300000 /* Internal SRAM base address */ -+ -+ - #if 0 - /* - * PIO pin definitions (peripheral A/B multiplexing). -diff -urN linux-2.6.20.4-0rig/include/asm-arm/arch-at91rm9200/at91sam9260_matrix.h linux-2.6.20.4-atmel/include/asm-arm/arch-at91rm9200/at91sam9260_matrix.h ---- linux-2.6.20.4-0rig/include/asm-arm/arch-at91rm9200/at91sam9260_matrix.h 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/asm-arm/arch-at91rm9200/at91sam9260_matrix.h 2007-03-24 16:39:16.000000000 +0100 -@@ -18,7 +18,7 @@ - #define AT91_MATRIX_MCFG2 (AT91_MATRIX + 0x08) /* Master Configuration Register 2 */ - #define AT91_MATRIX_MCFG3 (AT91_MATRIX + 0x0C) /* Master Configuration Register 3 */ - #define AT91_MATRIX_MCFG4 (AT91_MATRIX + 0x10) /* Master Configuration Register 4 */ --#define AT91_MATRIX_MCFG5 (AT91_MATRIX + 0x04) /* Master Configuration Register 5 */ -+#define AT91_MATRIX_MCFG5 (AT91_MATRIX + 0x14) /* Master Configuration Register 5 */ - #define AT91_MATRIX_ULBT (7 << 0) /* Undefined Length Burst Type */ - #define AT91_MATRIX_ULBT_INFINITE (0 << 0) - #define AT91_MATRIX_ULBT_SINGLE (1 << 0) -diff -urN linux-2.6.20.4-0rig/include/asm-arm/arch-at91rm9200/at91sam9263.h linux-2.6.20.4-atmel/include/asm-arm/arch-at91rm9200/at91sam9263.h ---- linux-2.6.20.4-0rig/include/asm-arm/arch-at91rm9200/at91sam9263.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/asm-arm/arch-at91rm9200/at91sam9263.h 2007-03-24 16:39:16.000000000 +0100 -@@ -0,0 +1,131 @@ -+/* -+ * include/asm-arm/arch-at91rm9200/at91sam9263.h -+ * -+ * (C) 2007 Atmel Corporation. -+ * -+ * Common definitions. -+ * Based on AT91SAM9263 datasheet revision B (Preliminary). -+ * -+ * 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 AT91SAM9263_H -+#define AT91SAM9263_H -+ -+/* -+ * Peripheral identifiers/interrupts. -+ */ -+#define AT91_ID_FIQ 0 /* Advanced Interrupt Controller (FIQ) */ -+#define AT91_ID_SYS 1 /* System Peripherals */ -+#define AT91SAM9263_ID_PIOA 2 /* Parallel IO Controller A */ -+#define AT91SAM9263_ID_PIOB 3 /* Parallel IO Controller B */ -+#define AT91SAM9263_ID_PIOCDE 4 /* Parallel IO Controller C, D and E */ -+#define AT91SAM9263_ID_US0 7 /* USART 0 */ -+#define AT91SAM9263_ID_US1 8 /* USART 1 */ -+#define AT91SAM9263_ID_US2 9 /* USART 2 */ -+#define AT91SAM9263_ID_MCI0 10 /* Multimedia Card Interface 0 */ -+#define AT91SAM9263_ID_MCI1 11 /* Multimedia Card Interface 1 */ -+#define AT91SAM9263_ID_CAN 12 /* CAN */ -+#define AT91SAM9263_ID_TWI 13 /* Two-Wire Interface */ -+#define AT91SAM9263_ID_SPI0 14 /* Serial Peripheral Interface 0 */ -+#define AT91SAM9263_ID_SPI1 15 /* Serial Peripheral Interface 1 */ -+#define AT91SAM9263_ID_SSC0 16 /* Serial Synchronous Controller 0 */ -+#define AT91SAM9263_ID_SSC1 17 /* Serial Synchronous Controller 1 */ -+#define AT91SAM9263_ID_AC97C 18 /* AC97 Controller */ -+#define AT91SAM9263_ID_TCB 19 /* Timer Counter 0, 1 and 2 */ -+#define AT91SAM9263_ID_PWMC 20 /* Pulse Width Modulation Controller */ -+#define AT91SAM9263_ID_EMAC 21 /* Ethernet */ -+#define AT91SAM9263_ID_2DGE 23 /* 2D Graphic Engine */ -+#define AT91SAM9263_ID_UDP 24 /* USB Device Port */ -+#define AT91SAM9263_ID_ISI 25 /* Image Sensor Interface */ -+#define AT91SAM9263_ID_LCDC 26 /* LCD Controller */ -+#define AT91SAM9263_ID_DMA 27 /* DMA Controller */ -+#define AT91SAM9263_ID_UHP 29 /* USB Host port */ -+#define AT91SAM9263_ID_IRQ0 30 /* Advanced Interrupt Controller (IRQ0) */ -+#define AT91SAM9263_ID_IRQ1 31 /* Advanced Interrupt Controller (IRQ1) */ -+ -+ -+/* -+ * User Peripheral physical base addresses. -+ */ -+#define AT91SAM9263_BASE_UDP 0xfff78000 -+#define AT91SAM9263_BASE_TCB0 0xfff7c000 -+#define AT91SAM9263_BASE_TC0 0xfff7c000 -+#define AT91SAM9263_BASE_TC1 0xfff7c040 -+#define AT91SAM9263_BASE_TC2 0xfff7c080 -+#define AT91SAM9263_BASE_MCI0 0xfff80000 -+#define AT91SAM9263_BASE_MCI1 0xfff84000 -+#define AT91SAM9263_BASE_TWI 0xfff88000 -+#define AT91SAM9263_BASE_US0 0xfff8c000 -+#define AT91SAM9263_BASE_US1 0xfff90000 -+#define AT91SAM9263_BASE_US2 0xfff94000 -+#define AT91SAM9263_BASE_SSC0 0xfff98000 -+#define AT91SAM9263_BASE_SSC1 0xfff9c000 -+#define AT91SAM9263_BASE_AC97C 0xfffa0000 -+#define AT91SAM9263_BASE_SPI0 0xfffa4000 -+#define AT91SAM9263_BASE_SPI1 0xfffa8000 -+#define AT91SAM9263_BASE_CAN 0xfffac000 -+#define AT91SAM9263_BASE_PWMC 0xfffb8000 -+#define AT91SAM9263_BASE_EMAC 0xfffbc000 -+#define AT91SAM9263_BASE_ISI 0xfffc4000 -+#define AT91SAM9263_BASE_2DGE 0xfffc8000 -+#define AT91_BASE_SYS 0xffffe000 -+ -+/* -+ * System Peripherals (offset from AT91_BASE_SYS) -+ */ -+#define AT91_ECC0 (0xffffe000 - AT91_BASE_SYS) -+#define AT91_SDRAMC0 (0xffffe200 - AT91_BASE_SYS) -+#define AT91_SMC0 (0xffffe400 - AT91_BASE_SYS) -+#define AT91_ECC1 (0xffffe600 - AT91_BASE_SYS) -+#define AT91_SDRAMC1 (0xffffe800 - AT91_BASE_SYS) -+#define AT91_SMC1 (0xffffea00 - AT91_BASE_SYS) -+#define AT91_MATRIX (0xffffec00 - AT91_BASE_SYS) -+#define AT91_CCFG (0xffffed10 - AT91_BASE_SYS) -+#define AT91_DBGU (0xffffee00 - AT91_BASE_SYS) -+#define AT91_AIC (0xfffff000 - AT91_BASE_SYS) -+#define AT91_PIOA (0xfffff200 - AT91_BASE_SYS) -+#define AT91_PIOB (0xfffff400 - AT91_BASE_SYS) -+#define AT91_PIOC (0xfffff600 - AT91_BASE_SYS) -+#define AT91_PIOD (0xfffff800 - AT91_BASE_SYS) -+#define AT91_PIOE (0xfffffa00 - AT91_BASE_SYS) -+#define AT91_PMC (0xfffffc00 - AT91_BASE_SYS) -+#define AT91_RSTC (0xfffffd00 - AT91_BASE_SYS) -+#define AT91_SHDWC (0xfffffd10 - AT91_BASE_SYS) -+#define AT91_RTT0 (0xfffffd20 - AT91_BASE_SYS) -+#define AT91_PIT (0xfffffd30 - AT91_BASE_SYS) -+#define AT91_WDT (0xfffffd40 - AT91_BASE_SYS) -+#define AT91_RTT1 (0xfffffd50 - AT91_BASE_SYS) -+#define AT91_GPBR (0xfffffd60 - AT91_BASE_SYS) -+ -+#define AT91_SMC AT91_SMC0 -+ -+/* -+ * Internal Memory. -+ */ -+#define AT91SAM9263_SRAM0_BASE 0x00300000 /* Internal SRAM 0 base address */ -+#define AT91SAM9263_SRAM0_SIZE (80 * SZ_1K) /* Internal SRAM 0 size (80Kb) */ -+ -+#define AT91SAM9263_ROM_BASE 0x00400000 /* Internal ROM base address */ -+#define AT91SAM9263_ROM_SIZE SZ_128K /* Internal ROM size (128Kb) */ -+ -+#define AT91SAM9263_SRAM1_BASE 0x00500000 /* Internal SRAM 1 base address */ -+#define AT91SAM9263_SRAM1_SIZE SZ_16K /* Internal SRAM 1 size (16Kb) */ -+ -+#define AT91SAM9263_LCDC_BASE 0x00700000 /* LCD Controller */ -+#define AT91SAM9263_DMAC_BASE 0x00800000 /* DMA Controller */ -+#define AT91SAM9263_UHP_BASE 0x00a00000 /* USB Host controller */ -+ -+#if 0 -+/* -+ * PIO pin definitions (peripheral A/B multiplexing). -+ */ -+ -+// TODO: Add -+ -+#endif -+ -+#endif -diff -urN linux-2.6.20.4-0rig/include/asm-arm/arch-at91rm9200/at91sam9263_matrix.h linux-2.6.20.4-atmel/include/asm-arm/arch-at91rm9200/at91sam9263_matrix.h ---- linux-2.6.20.4-0rig/include/asm-arm/arch-at91rm9200/at91sam9263_matrix.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/asm-arm/arch-at91rm9200/at91sam9263_matrix.h 2007-03-24 16:39:16.000000000 +0100 -@@ -0,0 +1,129 @@ -+/* -+ * include/asm-arm/arch-at91rm9200/at91sam9263_matrix.h -+ * -+ * Copyright (C) 2006 Atmel Corporation. -+ * -+ * Memory Controllers (MATRIX, EBI) - System peripherals registers. -+ * Based on AT91SAM9263 datasheet revision B (Preliminary). -+ * -+ * 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 AT91SAM9263_MATRIX_H -+#define AT91SAM9263_MATRIX_H -+ -+#define AT91_MATRIX_MCFG0 (AT91_MATRIX + 0x00) /* Master Configuration Register 0 */ -+#define AT91_MATRIX_MCFG1 (AT91_MATRIX + 0x04) /* Master Configuration Register 1 */ -+#define AT91_MATRIX_MCFG2 (AT91_MATRIX + 0x08) /* Master Configuration Register 2 */ -+#define AT91_MATRIX_MCFG3 (AT91_MATRIX + 0x0C) /* Master Configuration Register 3 */ -+#define AT91_MATRIX_MCFG4 (AT91_MATRIX + 0x10) /* Master Configuration Register 4 */ -+#define AT91_MATRIX_MCFG5 (AT91_MATRIX + 0x14) /* Master Configuration Register 5 */ -+#define AT91_MATRIX_MCFG6 (AT91_MATRIX + 0x18) /* Master Configuration Register 6 */ -+#define AT91_MATRIX_MCFG7 (AT91_MATRIX + 0x1C) /* Master Configuration Register 7 */ -+#define AT91_MATRIX_MCFG8 (AT91_MATRIX + 0x20) /* Master Configuration Register 8 */ -+#define AT91_MATRIX_ULBT (7 << 0) /* Undefined Length Burst Type */ -+#define AT91_MATRIX_ULBT_INFINITE (0 << 0) -+#define AT91_MATRIX_ULBT_SINGLE (1 << 0) -+#define AT91_MATRIX_ULBT_FOUR (2 << 0) -+#define AT91_MATRIX_ULBT_EIGHT (3 << 0) -+#define AT91_MATRIX_ULBT_SIXTEEN (4 << 0) -+ -+#define AT91_MATRIX_SCFG0 (AT91_MATRIX + 0x40) /* Slave Configuration Register 0 */ -+#define AT91_MATRIX_SCFG1 (AT91_MATRIX + 0x44) /* Slave Configuration Register 1 */ -+#define AT91_MATRIX_SCFG2 (AT91_MATRIX + 0x48) /* Slave Configuration Register 2 */ -+#define AT91_MATRIX_SCFG3 (AT91_MATRIX + 0x4C) /* Slave Configuration Register 3 */ -+#define AT91_MATRIX_SCFG4 (AT91_MATRIX + 0x50) /* Slave Configuration Register 4 */ -+#define AT91_MATRIX_SCFG5 (AT91_MATRIX + 0x54) /* Slave Configuration Register 5 */ -+#define AT91_MATRIX_SCFG6 (AT91_MATRIX + 0x58) /* Slave Configuration Register 6 */ -+#define AT91_MATRIX_SCFG7 (AT91_MATRIX + 0x5C) /* Slave Configuration Register 7 */ -+#define AT91_MATRIX_SLOT_CYCLE (0xff << 0) /* Maximum Number of Allowed Cycles for a Burst */ -+#define AT91_MATRIX_DEFMSTR_TYPE (3 << 16) /* Default Master Type */ -+#define AT91_MATRIX_DEFMSTR_TYPE_NONE (0 << 16) -+#define AT91_MATRIX_DEFMSTR_TYPE_LAST (1 << 16) -+#define AT91_MATRIX_DEFMSTR_TYPE_FIXED (2 << 16) -+#define AT91_MATRIX_FIXED_DEFMSTR (7 << 18) /* Fixed Index of Default Master */ -+#define AT91_MATRIX_ARBT (3 << 24) /* Arbitration Type */ -+#define AT91_MATRIX_ARBT_ROUND_ROBIN (0 << 24) -+#define AT91_MATRIX_ARBT_FIXED_PRIORITY (1 << 24) -+ -+#define AT91_MATRIX_PRAS0 (AT91_MATRIX + 0x80) /* Priority Register A for Slave 0 */ -+#define AT91_MATRIX_PRBS0 (AT91_MATRIX + 0x84) /* Priority Register B for Slave 0 */ -+#define AT91_MATRIX_PRAS1 (AT91_MATRIX + 0x88) /* Priority Register A for Slave 1 */ -+#define AT91_MATRIX_PRBS1 (AT91_MATRIX + 0x8C) /* Priority Register B for Slave 1 */ -+#define AT91_MATRIX_PRAS2 (AT91_MATRIX + 0x90) /* Priority Register A for Slave 2 */ -+#define AT91_MATRIX_PRBS2 (AT91_MATRIX + 0x94) /* Priority Register B for Slave 2 */ -+#define AT91_MATRIX_PRAS3 (AT91_MATRIX + 0x98) /* Priority Register A for Slave 3 */ -+#define AT91_MATRIX_PRBS3 (AT91_MATRIX + 0x9C) /* Priority Register B for Slave 3 */ -+#define AT91_MATRIX_PRAS4 (AT91_MATRIX + 0xA0) /* Priority Register A for Slave 4 */ -+#define AT91_MATRIX_PRBS4 (AT91_MATRIX + 0xA4) /* Priority Register B for Slave 4 */ -+#define AT91_MATRIX_PRAS5 (AT91_MATRIX + 0xA8) /* Priority Register A for Slave 5 */ -+#define AT91_MATRIX_PRBS5 (AT91_MATRIX + 0xAC) /* Priority Register B for Slave 5 */ -+#define AT91_MATRIX_PRAS6 (AT91_MATRIX + 0xB0) /* Priority Register A for Slave 6 */ -+#define AT91_MATRIX_PRBS6 (AT91_MATRIX + 0xB4) /* Priority Register B for Slave 6 */ -+#define AT91_MATRIX_PRAS7 (AT91_MATRIX + 0xB8) /* Priority Register A for Slave 7 */ -+#define AT91_MATRIX_PRBS7 (AT91_MATRIX + 0xBC) /* Priority Register B for Slave 7 */ -+#define AT91_MATRIX_M0PR (3 << 0) /* Master 0 Priority */ -+#define AT91_MATRIX_M1PR (3 << 4) /* Master 1 Priority */ -+#define AT91_MATRIX_M2PR (3 << 8) /* Master 2 Priority */ -+#define AT91_MATRIX_M3PR (3 << 12) /* Master 3 Priority */ -+#define AT91_MATRIX_M4PR (3 << 16) /* Master 4 Priority */ -+#define AT91_MATRIX_M5PR (3 << 20) /* Master 5 Priority */ -+#define AT91_MATRIX_M6PR (3 << 24) /* Master 6 Priority */ -+#define AT91_MATRIX_M7PR (3 << 28) /* Master 7 Priority */ -+#define AT91_MATRIX_M8PR (3 << 0) /* Master 8 Priority (in Register B) */ -+ -+#define AT91_MATRIX_MRCR (AT91_MATRIX + 0x100) /* Master Remap Control Register */ -+#define AT91_MATRIX_RCB0 (1 << 0) /* Remap Command for AHB Master 0 (ARM926EJ-S Instruction Master) */ -+#define AT91_MATRIX_RCB1 (1 << 1) /* Remap Command for AHB Master 1 (ARM926EJ-S Data Master) */ -+#define AT91_MATRIX_RCB2 (1 << 2) -+#define AT91_MATRIX_RCB3 (1 << 3) -+#define AT91_MATRIX_RCB4 (1 << 4) -+#define AT91_MATRIX_RCB5 (1 << 5) -+#define AT91_MATRIX_RCB6 (1 << 6) -+#define AT91_MATRIX_RCB7 (1 << 7) -+#define AT91_MATRIX_RCB8 (1 << 8) -+ -+#define AT91_MATRIX_TCMR (AT91_MATRIX + 0x114) /* TCM Configuration Register */ -+#define AT91_MATRIX_ITCM_SIZE (0xf << 0) /* Size of ITCM enabled memory block */ -+#define AT91_MATRIX_ITCM_0 (0 << 0) -+#define AT91_MATRIX_ITCM_16 (5 << 0) -+#define AT91_MATRIX_ITCM_32 (6 << 0) -+#define AT91_MATRIX_DTCM_SIZE (0xf << 4) /* Size of DTCM enabled memory block */ -+#define AT91_MATRIX_DTCM_0 (0 << 4) -+#define AT91_MATRIX_DTCM_16 (5 << 4) -+#define AT91_MATRIX_DTCM_32 (6 << 4) -+ -+#define AT91_MATRIX_EBI0CSA (AT91_MATRIX + 0x120) /* EBI0 Chip Select Assignment Register */ -+#define AT91_MATRIX_EBI0_CS1A (1 << 1) /* Chip Select 1 Assignment */ -+#define AT91_MATRIX_EBI0_CS1A_SMC (0 << 1) -+#define AT91_MATRIX_EBI0_CS1A_SDRAMC (1 << 1) -+#define AT91_MATRIX_EBI0_CS3A (1 << 3) /* Chip Select 3 Assignment */ -+#define AT91_MATRIX_EBI0_CS3A_SMC (0 << 3) -+#define AT91_MATRIX_EBI0_CS3A_SMC_SMARTMEDIA (1 << 3) -+#define AT91_MATRIX_EBI0_CS4A (1 << 4) /* Chip Select 4 Assignment */ -+#define AT91_MATRIX_EBI0_CS4A_SMC (0 << 4) -+#define AT91_MATRIX_EBI0_CS4A_SMC_CF1 (1 << 4) -+#define AT91_MATRIX_EBI0_CS5A (1 << 5) /* Chip Select 5 Assignment */ -+#define AT91_MATRIX_EBI0_CS5A_SMC (0 << 5) -+#define AT91_MATRIX_EBI0_CS5A_SMC_CF2 (1 << 5) -+#define AT91_MATRIX_EBI0_DBPUC (1 << 8) /* Data Bus Pull-up Configuration */ -+#define AT91_MATRIX_EBI0_VDDIOMSEL (1 << 16) /* Memory voltage selection */ -+#define AT91_MATRIX_EBI0_VDDIOMSEL_1_8V (0 << 16) -+#define AT91_MATRIX_EBI0_VDDIOMSEL_3_3V (1 << 16) -+ -+#define AT91_MATRIX_EBI1CSA (AT91_MATRIX + 0x124) /* EBI1 Chip Select Assignment Register */ -+#define AT91_MATRIX_EBI1_CS1A (1 << 1) /* Chip Select 1 Assignment */ -+#define AT91_MATRIX_EBI1_CS1A_SMC (0 << 1) -+#define AT91_MATRIX_EBI1_CS1A_SDRAMC (1 << 1) -+#define AT91_MATRIX_EBI1_CS2A (1 << 3) /* Chip Select 3 Assignment */ -+#define AT91_MATRIX_EBI1_CS2A_SMC (0 << 3) -+#define AT91_MATRIX_EBI1_CS2A_SMC_SMARTMEDIA (1 << 3) -+#define AT91_MATRIX_EBI1_DBPUC (1 << 8) /* Data Bus Pull-up Configuration */ -+#define AT91_MATRIX_EBI1_VDDIOMSEL (1 << 16) /* Memory voltage selection */ -+#define AT91_MATRIX_EBI1_VDDIOMSEL_1_8V (0 << 16) -+#define AT91_MATRIX_EBI1_VDDIOMSEL_3_3V (1 << 16) -+ -+#endif -diff -urN linux-2.6.20.4-0rig/include/asm-arm/arch-at91rm9200/at91sam926x_mc.h linux-2.6.20.4-atmel/include/asm-arm/arch-at91rm9200/at91sam926x_mc.h ---- linux-2.6.20.4-0rig/include/asm-arm/arch-at91rm9200/at91sam926x_mc.h 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/asm-arm/arch-at91rm9200/at91sam926x_mc.h 2007-03-24 16:39:16.000000000 +0100 -@@ -131,4 +131,11 @@ - #define AT91_SMC_PS_16 (2 << 28) - #define AT91_SMC_PS_32 (3 << 28) - -+#if defined(AT91_SMC1) /* The AT91SAM9263 has 2 Static Memory contollers */ -+#define AT91_SMC1_SETUP(n) (AT91_SMC1 + 0x00 + ((n)*0x10)) /* Setup Register for CS n */ -+#define AT91_SMC1_PULSE(n) (AT91_SMC1 + 0x04 + ((n)*0x10)) /* Pulse Register for CS n */ -+#define AT91_SMC1_CYCLE(n) (AT91_SMC1 + 0x08 + ((n)*0x10)) /* Cycle Register for CS n */ -+#define AT91_SMC1_MODE(n) (AT91_SMC1 + 0x0c + ((n)*0x10)) /* Mode Register for CS n */ -+#endif -+ - #endif -diff -urN linux-2.6.20.4-0rig/include/asm-arm/arch-at91rm9200/board.h linux-2.6.20.4-atmel/include/asm-arm/arch-at91rm9200/board.h ---- linux-2.6.20.4-0rig/include/asm-arm/arch-at91rm9200/board.h 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/asm-arm/arch-at91rm9200/board.h 2007-03-24 16:39:16.000000000 +0100 -@@ -34,6 +34,7 @@ - #include <linux/mtd/partitions.h> - #include <linux/device.h> - #include <linux/spi/spi.h> -+#include <video/atmel_lcdc.h> - - /* USB Device */ - struct at91_udc_data { -@@ -60,18 +61,23 @@ - u8 wp_pin; /* (SD) writeprotect detect */ - u8 vcc_pin; /* power switching (high == on) */ - }; --extern void __init at91_add_device_mmc(struct at91_mmc_data *data); -+extern void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data); - -- /* Ethernet */ -+/* Ethernet (EMAC & MACB) */ - struct at91_eth_data { - u8 phy_irq_pin; /* PHY IRQ */ - u8 is_rmii; /* using RMII interface? */ - }; - extern void __init at91_add_device_eth(struct at91_eth_data *data); - -+#if defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9263) -+#define eth_platform_data at91_eth_data -+#endif -+ - /* USB Host */ - struct at91_usbh_data { - u8 ports; /* number of ports on root hub */ -+ u8 vbus_pin[]; /* port power switch */ - }; - extern void __init at91_add_device_usbh(struct at91_usbh_data *data); - -@@ -93,6 +99,9 @@ - /* SPI */ - extern void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices); - -+ /* LCD Controler */ -+extern void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data); -+ - /* Serial */ - struct at91_uart_config { - unsigned short console_tty; /* tty number of serial console */ -@@ -114,4 +123,13 @@ - 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); -+ - #endif -diff -urN linux-2.6.20.4-0rig/include/asm-arm/arch-at91rm9200/cpu.h linux-2.6.20.4-atmel/include/asm-arm/arch-at91rm9200/cpu.h ---- linux-2.6.20.4-0rig/include/asm-arm/arch-at91rm9200/cpu.h 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/asm-arm/arch-at91rm9200/cpu.h 2007-03-24 16:39:16.000000000 +0100 -@@ -20,7 +20,11 @@ - #define ARCH_ID_AT91RM9200 0x09290780 - #define ARCH_ID_AT91SAM9260 0x019803a0 - #define ARCH_ID_AT91SAM9261 0x019703a0 -+#define ARCH_ID_AT91SAM9263 0x019607a0 - -+#define ARCH_ID_AT91SAM9XE128 0x329973a0 -+#define ARCH_ID_AT91SAM9XE256 0x329a93a0 -+#define ARCH_ID_AT91SAM9XE512 0x329aa3a0 - - static inline unsigned long at91_cpu_identify(void) - { -@@ -28,6 +32,16 @@ - } - - -+#define ARCH_FAMILY_AT91X92 0x09200000 -+#define ARCH_FAMILY_AT91SAM9 0x01900000 -+#define ARCH_FAMILY_AT91SAM9XE 0x02900000 -+ -+static inline unsigned long at91_arch_identify(void) -+{ -+ return (at91_sys_read(AT91_DBGU_CIDR) & AT91_CIDR_ARCH); -+} -+ -+ - #ifdef CONFIG_ARCH_AT91RM9200 - #define cpu_is_at91rm9200() (at91_cpu_identify() == ARCH_ID_AT91RM9200) - #else -@@ -35,8 +49,10 @@ - #endif - - #ifdef CONFIG_ARCH_AT91SAM9260 --#define cpu_is_at91sam9260() (at91_cpu_identify() == ARCH_ID_AT91SAM9260) -+#define cpu_is_at91sam9xe() (at91_arch_identify() == ARCH_FAMILY_AT91SAM9XE) -+#define cpu_is_at91sam9260() ((at91_cpu_identify() == ARCH_ID_AT91SAM9260) || cpu_is_at91sam9xe()) - #else -+#define cpu_is_at91sam9xe() (0) - #define cpu_is_at91sam9260() (0) - #endif - -@@ -46,4 +62,10 @@ - #define cpu_is_at91sam9261() (0) - #endif - -+#ifdef CONFIG_ARCH_AT91SAM9263 -+#define cpu_is_at91sam9263() (at91_cpu_identify() == ARCH_ID_AT91SAM9263) -+#else -+#define cpu_is_at91sam9263() (0) -+#endif -+ - #endif -diff -urN linux-2.6.20.4-0rig/include/asm-arm/arch-at91rm9200/debug-macro.S linux-2.6.20.4-atmel/include/asm-arm/arch-at91rm9200/debug-macro.S ---- linux-2.6.20.4-0rig/include/asm-arm/arch-at91rm9200/debug-macro.S 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/asm-arm/arch-at91rm9200/debug-macro.S 2007-03-24 16:39:16.000000000 +0100 -@@ -16,24 +16,24 @@ - - .macro addruart,rx - mrc p15, 0, \rx, c1, c0 -- tst \rx, #1 @ MMU enabled? -- ldreq \rx, =AT91_BASE_SYS @ System peripherals (phys address) -- ldrne \rx, =AT91_VA_BASE_SYS @ System peripherals (virt address) -+ tst \rx, #1 @ MMU enabled? -+ ldreq \rx, =(AT91_BASE_SYS + AT91_DBGU) @ System peripherals (phys address) -+ ldrne \rx, =(AT91_VA_BASE_SYS + AT91_DBGU) @ System peripherals (virt address) - .endm - - .macro senduart,rd,rx -- strb \rd, [\rx, #AT91_DBGU_THR] @ Write to Transmitter Holding Register -+ strb \rd, [\rx, #(AT91_DBGU_THR - AT91_DBGU)] @ Write to Transmitter Holding Register - .endm - - .macro waituart,rd,rx --1001: ldr \rd, [\rx, #AT91_DBGU_SR] @ Read Status Register -- tst \rd, #AT91_DBGU_TXRDY @ DBGU_TXRDY = 1 when ready to transmit -+1001: ldr \rd, [\rx, #(AT91_DBGU_SR - AT91_DBGU)] @ Read Status Register -+ tst \rd, #AT91_DBGU_TXRDY @ DBGU_TXRDY = 1 when ready to transmit - beq 1001b - .endm - - .macro busyuart,rd,rx --1001: ldr \rd, [\rx, #AT91_DBGU_SR] @ Read Status Register -- tst \rd, #AT91_DBGU_TXEMPTY @ DBGU_TXEMPTY = 1 when transmission complete -+1001: ldr \rd, [\rx, #(AT91_DBGU_SR - AT91_DBGU)] @ Read Status Register -+ tst \rd, #AT91_DBGU_TXEMPTY @ DBGU_TXEMPTY = 1 when transmission complete - beq 1001b - .endm - -diff -urN linux-2.6.20.4-0rig/include/asm-arm/arch-at91rm9200/entry-macro.S linux-2.6.20.4-atmel/include/asm-arm/arch-at91rm9200/entry-macro.S ---- linux-2.6.20.4-0rig/include/asm-arm/arch-at91rm9200/entry-macro.S 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/asm-arm/arch-at91rm9200/entry-macro.S 2007-03-24 16:39:16.000000000 +0100 -@@ -17,10 +17,10 @@ - .endm - - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp -- ldr \base, =(AT91_VA_BASE_SYS) @ base virtual address of SYS peripherals -- ldr \irqnr, [\base, #AT91_AIC_IVR] @ read IRQ vector register: de-asserts nIRQ to processor (and clears interrupt) -- ldr \irqstat, [\base, #AT91_AIC_ISR] @ read interrupt source number -- teq \irqstat, #0 @ ISR is 0 when no current interrupt, or spurious interrupt -- streq \tmp, [\base, #AT91_AIC_EOICR] @ not going to be handled further, then ACK it now. -+ ldr \base, =(AT91_VA_BASE_SYS + AT91_AIC) @ base virtual address of AIC peripheral -+ ldr \irqnr, [\base, #(AT91_AIC_IVR - AT91_AIC)] @ read IRQ vector register: de-asserts nIRQ to processor (and clears interrupt) -+ ldr \irqstat, [\base, #(AT91_AIC_ISR - AT91_AIC)] @ read interrupt source number -+ teq \irqstat, #0 @ ISR is 0 when no current interrupt, or spurious interrupt -+ streq \tmp, [\base, #(AT91_AIC_EOICR - AT91_AIC)] @ not going to be handled further, then ACK it now. - .endm - -diff -urN linux-2.6.20.4-0rig/include/asm-arm/arch-at91rm9200/gpio.h linux-2.6.20.4-atmel/include/asm-arm/arch-at91rm9200/gpio.h ---- linux-2.6.20.4-0rig/include/asm-arm/arch-at91rm9200/gpio.h 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/asm-arm/arch-at91rm9200/gpio.h 2007-03-24 16:39:16.000000000 +0100 -@@ -17,7 +17,7 @@ - - #define PIN_BASE NR_AIC_IRQS - --#define MAX_GPIO_BANKS 4 -+#define MAX_GPIO_BANKS 5 - - /* these pin numbers double as IRQ numbers, like AT91xxx_ID_* values */ - -@@ -26,37 +26,31 @@ - #define AT91_PIN_PA2 (PIN_BASE + 0x00 + 2) - #define AT91_PIN_PA3 (PIN_BASE + 0x00 + 3) - #define AT91_PIN_PA4 (PIN_BASE + 0x00 + 4) -- - #define AT91_PIN_PA5 (PIN_BASE + 0x00 + 5) - #define AT91_PIN_PA6 (PIN_BASE + 0x00 + 6) - #define AT91_PIN_PA7 (PIN_BASE + 0x00 + 7) - #define AT91_PIN_PA8 (PIN_BASE + 0x00 + 8) - #define AT91_PIN_PA9 (PIN_BASE + 0x00 + 9) -- - #define AT91_PIN_PA10 (PIN_BASE + 0x00 + 10) - #define AT91_PIN_PA11 (PIN_BASE + 0x00 + 11) - #define AT91_PIN_PA12 (PIN_BASE + 0x00 + 12) - #define AT91_PIN_PA13 (PIN_BASE + 0x00 + 13) - #define AT91_PIN_PA14 (PIN_BASE + 0x00 + 14) -- - #define AT91_PIN_PA15 (PIN_BASE + 0x00 + 15) - #define AT91_PIN_PA16 (PIN_BASE + 0x00 + 16) - #define AT91_PIN_PA17 (PIN_BASE + 0x00 + 17) - #define AT91_PIN_PA18 (PIN_BASE + 0x00 + 18) - #define AT91_PIN_PA19 (PIN_BASE + 0x00 + 19) -- - #define AT91_PIN_PA20 (PIN_BASE + 0x00 + 20) - #define AT91_PIN_PA21 (PIN_BASE + 0x00 + 21) - #define AT91_PIN_PA22 (PIN_BASE + 0x00 + 22) - #define AT91_PIN_PA23 (PIN_BASE + 0x00 + 23) - #define AT91_PIN_PA24 (PIN_BASE + 0x00 + 24) -- - #define AT91_PIN_PA25 (PIN_BASE + 0x00 + 25) - #define AT91_PIN_PA26 (PIN_BASE + 0x00 + 26) - #define AT91_PIN_PA27 (PIN_BASE + 0x00 + 27) - #define AT91_PIN_PA28 (PIN_BASE + 0x00 + 28) - #define AT91_PIN_PA29 (PIN_BASE + 0x00 + 29) -- - #define AT91_PIN_PA30 (PIN_BASE + 0x00 + 30) - #define AT91_PIN_PA31 (PIN_BASE + 0x00 + 31) - -@@ -65,37 +59,31 @@ - #define AT91_PIN_PB2 (PIN_BASE + 0x20 + 2) - #define AT91_PIN_PB3 (PIN_BASE + 0x20 + 3) - #define AT91_PIN_PB4 (PIN_BASE + 0x20 + 4) -- - #define AT91_PIN_PB5 (PIN_BASE + 0x20 + 5) - #define AT91_PIN_PB6 (PIN_BASE + 0x20 + 6) - #define AT91_PIN_PB7 (PIN_BASE + 0x20 + 7) - #define AT91_PIN_PB8 (PIN_BASE + 0x20 + 8) - #define AT91_PIN_PB9 (PIN_BASE + 0x20 + 9) -- - #define AT91_PIN_PB10 (PIN_BASE + 0x20 + 10) - #define AT91_PIN_PB11 (PIN_BASE + 0x20 + 11) - #define AT91_PIN_PB12 (PIN_BASE + 0x20 + 12) - #define AT91_PIN_PB13 (PIN_BASE + 0x20 + 13) - #define AT91_PIN_PB14 (PIN_BASE + 0x20 + 14) -- - #define AT91_PIN_PB15 (PIN_BASE + 0x20 + 15) - #define AT91_PIN_PB16 (PIN_BASE + 0x20 + 16) - #define AT91_PIN_PB17 (PIN_BASE + 0x20 + 17) - #define AT91_PIN_PB18 (PIN_BASE + 0x20 + 18) - #define AT91_PIN_PB19 (PIN_BASE + 0x20 + 19) -- - #define AT91_PIN_PB20 (PIN_BASE + 0x20 + 20) - #define AT91_PIN_PB21 (PIN_BASE + 0x20 + 21) - #define AT91_PIN_PB22 (PIN_BASE + 0x20 + 22) - #define AT91_PIN_PB23 (PIN_BASE + 0x20 + 23) - #define AT91_PIN_PB24 (PIN_BASE + 0x20 + 24) -- - #define AT91_PIN_PB25 (PIN_BASE + 0x20 + 25) - #define AT91_PIN_PB26 (PIN_BASE + 0x20 + 26) - #define AT91_PIN_PB27 (PIN_BASE + 0x20 + 27) - #define AT91_PIN_PB28 (PIN_BASE + 0x20 + 28) - #define AT91_PIN_PB29 (PIN_BASE + 0x20 + 29) -- - #define AT91_PIN_PB30 (PIN_BASE + 0x20 + 30) - #define AT91_PIN_PB31 (PIN_BASE + 0x20 + 31) - -@@ -104,37 +92,31 @@ - #define AT91_PIN_PC2 (PIN_BASE + 0x40 + 2) - #define AT91_PIN_PC3 (PIN_BASE + 0x40 + 3) - #define AT91_PIN_PC4 (PIN_BASE + 0x40 + 4) -- - #define AT91_PIN_PC5 (PIN_BASE + 0x40 + 5) - #define AT91_PIN_PC6 (PIN_BASE + 0x40 + 6) - #define AT91_PIN_PC7 (PIN_BASE + 0x40 + 7) - #define AT91_PIN_PC8 (PIN_BASE + 0x40 + 8) - #define AT91_PIN_PC9 (PIN_BASE + 0x40 + 9) -- - #define AT91_PIN_PC10 (PIN_BASE + 0x40 + 10) - #define AT91_PIN_PC11 (PIN_BASE + 0x40 + 11) - #define AT91_PIN_PC12 (PIN_BASE + 0x40 + 12) - #define AT91_PIN_PC13 (PIN_BASE + 0x40 + 13) - #define AT91_PIN_PC14 (PIN_BASE + 0x40 + 14) -- - #define AT91_PIN_PC15 (PIN_BASE + 0x40 + 15) - #define AT91_PIN_PC16 (PIN_BASE + 0x40 + 16) - #define AT91_PIN_PC17 (PIN_BASE + 0x40 + 17) - #define AT91_PIN_PC18 (PIN_BASE + 0x40 + 18) - #define AT91_PIN_PC19 (PIN_BASE + 0x40 + 19) -- - #define AT91_PIN_PC20 (PIN_BASE + 0x40 + 20) - #define AT91_PIN_PC21 (PIN_BASE + 0x40 + 21) - #define AT91_PIN_PC22 (PIN_BASE + 0x40 + 22) - #define AT91_PIN_PC23 (PIN_BASE + 0x40 + 23) - #define AT91_PIN_PC24 (PIN_BASE + 0x40 + 24) -- - #define AT91_PIN_PC25 (PIN_BASE + 0x40 + 25) - #define AT91_PIN_PC26 (PIN_BASE + 0x40 + 26) - #define AT91_PIN_PC27 (PIN_BASE + 0x40 + 27) - #define AT91_PIN_PC28 (PIN_BASE + 0x40 + 28) - #define AT91_PIN_PC29 (PIN_BASE + 0x40 + 29) -- - #define AT91_PIN_PC30 (PIN_BASE + 0x40 + 30) - #define AT91_PIN_PC31 (PIN_BASE + 0x40 + 31) - -@@ -143,40 +125,67 @@ - #define AT91_PIN_PD2 (PIN_BASE + 0x60 + 2) - #define AT91_PIN_PD3 (PIN_BASE + 0x60 + 3) - #define AT91_PIN_PD4 (PIN_BASE + 0x60 + 4) -- - #define AT91_PIN_PD5 (PIN_BASE + 0x60 + 5) - #define AT91_PIN_PD6 (PIN_BASE + 0x60 + 6) - #define AT91_PIN_PD7 (PIN_BASE + 0x60 + 7) - #define AT91_PIN_PD8 (PIN_BASE + 0x60 + 8) - #define AT91_PIN_PD9 (PIN_BASE + 0x60 + 9) -- - #define AT91_PIN_PD10 (PIN_BASE + 0x60 + 10) - #define AT91_PIN_PD11 (PIN_BASE + 0x60 + 11) - #define AT91_PIN_PD12 (PIN_BASE + 0x60 + 12) - #define AT91_PIN_PD13 (PIN_BASE + 0x60 + 13) - #define AT91_PIN_PD14 (PIN_BASE + 0x60 + 14) -- - #define AT91_PIN_PD15 (PIN_BASE + 0x60 + 15) - #define AT91_PIN_PD16 (PIN_BASE + 0x60 + 16) - #define AT91_PIN_PD17 (PIN_BASE + 0x60 + 17) - #define AT91_PIN_PD18 (PIN_BASE + 0x60 + 18) - #define AT91_PIN_PD19 (PIN_BASE + 0x60 + 19) -- - #define AT91_PIN_PD20 (PIN_BASE + 0x60 + 20) - #define AT91_PIN_PD21 (PIN_BASE + 0x60 + 21) - #define AT91_PIN_PD22 (PIN_BASE + 0x60 + 22) - #define AT91_PIN_PD23 (PIN_BASE + 0x60 + 23) - #define AT91_PIN_PD24 (PIN_BASE + 0x60 + 24) -- - #define AT91_PIN_PD25 (PIN_BASE + 0x60 + 25) - #define AT91_PIN_PD26 (PIN_BASE + 0x60 + 26) - #define AT91_PIN_PD27 (PIN_BASE + 0x60 + 27) - #define AT91_PIN_PD28 (PIN_BASE + 0x60 + 28) - #define AT91_PIN_PD29 (PIN_BASE + 0x60 + 29) -- - #define AT91_PIN_PD30 (PIN_BASE + 0x60 + 30) - #define AT91_PIN_PD31 (PIN_BASE + 0x60 + 31) - -+#define AT91_PIN_PE0 (PIN_BASE + 0x80 + 0) -+#define AT91_PIN_PE1 (PIN_BASE + 0x80 + 1) -+#define AT91_PIN_PE2 (PIN_BASE + 0x80 + 2) -+#define AT91_PIN_PE3 (PIN_BASE + 0x80 + 3) -+#define AT91_PIN_PE4 (PIN_BASE + 0x80 + 4) -+#define AT91_PIN_PE5 (PIN_BASE + 0x80 + 5) -+#define AT91_PIN_PE6 (PIN_BASE + 0x80 + 6) -+#define AT91_PIN_PE7 (PIN_BASE + 0x80 + 7) -+#define AT91_PIN_PE8 (PIN_BASE + 0x80 + 8) -+#define AT91_PIN_PE9 (PIN_BASE + 0x80 + 9) -+#define AT91_PIN_PE10 (PIN_BASE + 0x80 + 10) -+#define AT91_PIN_PE11 (PIN_BASE + 0x80 + 11) -+#define AT91_PIN_PE12 (PIN_BASE + 0x80 + 12) -+#define AT91_PIN_PE13 (PIN_BASE + 0x80 + 13) -+#define AT91_PIN_PE14 (PIN_BASE + 0x80 + 14) -+#define AT91_PIN_PE15 (PIN_BASE + 0x80 + 15) -+#define AT91_PIN_PE16 (PIN_BASE + 0x80 + 16) -+#define AT91_PIN_PE17 (PIN_BASE + 0x80 + 17) -+#define AT91_PIN_PE18 (PIN_BASE + 0x80 + 18) -+#define AT91_PIN_PE19 (PIN_BASE + 0x80 + 19) -+#define AT91_PIN_PE20 (PIN_BASE + 0x80 + 20) -+#define AT91_PIN_PE21 (PIN_BASE + 0x80 + 21) -+#define AT91_PIN_PE22 (PIN_BASE + 0x80 + 22) -+#define AT91_PIN_PE23 (PIN_BASE + 0x80 + 23) -+#define AT91_PIN_PE24 (PIN_BASE + 0x80 + 24) -+#define AT91_PIN_PE25 (PIN_BASE + 0x80 + 25) -+#define AT91_PIN_PE26 (PIN_BASE + 0x80 + 26) -+#define AT91_PIN_PE27 (PIN_BASE + 0x80 + 27) -+#define AT91_PIN_PE28 (PIN_BASE + 0x80 + 28) -+#define AT91_PIN_PE29 (PIN_BASE + 0x80 + 29) -+#define AT91_PIN_PE30 (PIN_BASE + 0x80 + 30) -+#define AT91_PIN_PE31 (PIN_BASE + 0x80 + 31) -+ - #ifndef __ASSEMBLY__ - /* setup setup routines, called from board init or driver probe() */ - extern int __init_or_module at91_set_A_periph(unsigned pin, int use_pullup); -diff -urN linux-2.6.20.4-0rig/include/asm-arm/arch-at91rm9200/hardware.h linux-2.6.20.4-atmel/include/asm-arm/arch-at91rm9200/hardware.h ---- linux-2.6.20.4-0rig/include/asm-arm/arch-at91rm9200/hardware.h 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/asm-arm/arch-at91rm9200/hardware.h 2007-03-24 16:39:16.000000000 +0100 -@@ -22,21 +22,23 @@ - #include <asm/arch/at91sam9260.h> - #elif defined(CONFIG_ARCH_AT91SAM9261) - #include <asm/arch/at91sam9261.h> -+#elif defined(CONFIG_ARCH_AT91SAM9263) -+#include <asm/arch/at91sam9263.h> - #else - #error "Unsupported AT91 processor" - #endif - - - /* -- * Remap the peripherals from address 0xFFFA0000 .. 0xFFFFFFFF -- * to 0xFEFA0000 .. 0xFF000000. (384Kb) -+ * Remap the peripherals from address 0xFFF78000 .. 0xFFFFFFFF -+ * to 0xFEF78000 .. 0xFF000000. (544Kb) - */ --#define AT91_IO_PHYS_BASE 0xFFFA0000 -+#define AT91_IO_PHYS_BASE 0xFFF78000 - #define AT91_IO_SIZE (0xFFFFFFFF - AT91_IO_PHYS_BASE + 1) - #define AT91_IO_VIRT_BASE (0xFF000000 - AT91_IO_SIZE) - - /* Convert a physical IO address to virtual IO address */ --#define AT91_IO_P2V(x) ((x) - AT91_IO_PHYS_BASE + AT91_IO_VIRT_BASE) -+#define AT91_IO_P2V(x) ((x) - AT91_IO_PHYS_BASE + AT91_IO_VIRT_BASE) - - /* - * Virtual to Physical Address mapping for IO devices. -diff -urN linux-2.6.20.4-0rig/include/asm-arm/arch-at91rm9200/ics1523.h linux-2.6.20.4-atmel/include/asm-arm/arch-at91rm9200/ics1523.h ---- linux-2.6.20.4-0rig/include/asm-arm/arch-at91rm9200/ics1523.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/asm-arm/arch-at91rm9200/ics1523.h 2007-03-24 16:39:16.000000000 +0100 -@@ -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 */ -diff -urN linux-2.6.20.4-0rig/include/asm-arm/arch-at91rm9200/irqs.h linux-2.6.20.4-atmel/include/asm-arm/arch-at91rm9200/irqs.h ---- linux-2.6.20.4-0rig/include/asm-arm/arch-at91rm9200/irqs.h 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/asm-arm/arch-at91rm9200/irqs.h 2007-03-24 16:39:16.000000000 +0100 -@@ -37,8 +37,8 @@ - * IRQ interrupt symbols are the AT91xxx_ID_* symbols - * for IRQs handled directly through the AIC, or else the AT91_PIN_* - * symbols in gpio.h for ones handled indirectly as GPIOs. -- * We make provision for 4 banks of GPIO. -+ * We make provision for 5 banks of GPIO. - */ --#define NR_IRQS (NR_AIC_IRQS + (4 * 32)) -+#define NR_IRQS (NR_AIC_IRQS + (5 * 32)) - - #endif -diff -urN linux-2.6.20.4-0rig/include/asm-arm/arch-at91rm9200/spi.h linux-2.6.20.4-atmel/include/asm-arm/arch-at91rm9200/spi.h ---- linux-2.6.20.4-0rig/include/asm-arm/arch-at91rm9200/spi.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/asm-arm/arch-at91rm9200/spi.h 2007-03-24 16:39:16.000000000 +0100 -@@ -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 -diff -urN linux-2.6.20.4-0rig/include/asm-arm/arch-at91rm9200/timex.h linux-2.6.20.4-atmel/include/asm-arm/arch-at91rm9200/timex.h ---- linux-2.6.20.4-0rig/include/asm-arm/arch-at91rm9200/timex.h 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/asm-arm/arch-at91rm9200/timex.h 2007-03-24 16:39:16.000000000 +0100 -@@ -32,6 +32,11 @@ - #define AT91SAM9_MASTER_CLOCK 99300000 - #define CLOCK_TICK_RATE (AT91SAM9_MASTER_CLOCK/16) - -+#elif defined(CONFIG_ARCH_AT91SAM9263) -+ -+#define AT91SAM9_MASTER_CLOCK 99959500 -+#define CLOCK_TICK_RATE (AT91SAM9_MASTER_CLOCK/16) -+ - #endif - - #endif -diff -urN linux-2.6.20.4-0rig/include/asm-avr32/arch-at32ap/at32ap7000.h linux-2.6.20.4-atmel/include/asm-avr32/arch-at32ap/at32ap7000.h ---- linux-2.6.20.4-0rig/include/asm-avr32/arch-at32ap/at32ap7000.h 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/asm-avr32/arch-at32ap/at32ap7000.h 2007-03-24 16:42:28.000000000 +0100 -@@ -24,10 +24,12 @@ - #define GPIO_PIOB_BASE (GPIO_PIOA_BASE + 32) - #define GPIO_PIOC_BASE (GPIO_PIOB_BASE + 32) - #define GPIO_PIOD_BASE (GPIO_PIOC_BASE + 32) -+#define GPIO_PIOE_BASE (GPIO_PIOD_BASE + 32) - - #define GPIO_PIN_PA(N) (GPIO_PIOA_BASE + (N)) - #define GPIO_PIN_PB(N) (GPIO_PIOB_BASE + (N)) - #define GPIO_PIN_PC(N) (GPIO_PIOC_BASE + (N)) - #define GPIO_PIN_PD(N) (GPIO_PIOD_BASE + (N)) -+#define GPIO_PIN_PE(N) (GPIO_PIOE_BASE + (N)) - - #endif /* __ASM_ARCH_AT32AP7000_H__ */ -diff -urN linux-2.6.20.4-0rig/include/asm-avr32/arch-at32ap/at91_pdc.h linux-2.6.20.4-atmel/include/asm-avr32/arch-at32ap/at91_pdc.h ---- linux-2.6.20.4-0rig/include/asm-avr32/arch-at32ap/at91_pdc.h 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/asm-avr32/arch-at32ap/at91_pdc.h 1970-01-01 01:00:00.000000000 +0100 -@@ -1,36 +0,0 @@ --/* -- * include/asm-arm/arch-at91rm9200/at91_pdc.h -- * -- * Copyright (C) 2005 Ivan Kokshaysky -- * Copyright (C) SAN People -- * -- * Peripheral Data Controller (PDC) registers. -- * Based on AT91RM9200 datasheet revision E. -- * -- * 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_PDC_H --#define AT91_PDC_H -- --#define AT91_PDC_RPR 0x100 /* Receive Pointer Register */ --#define AT91_PDC_RCR 0x104 /* Receive Counter Register */ --#define AT91_PDC_TPR 0x108 /* Transmit Pointer Register */ --#define AT91_PDC_TCR 0x10c /* Transmit Counter Register */ --#define AT91_PDC_RNPR 0x110 /* Receive Next Pointer Register */ --#define AT91_PDC_RNCR 0x114 /* Receive Next Counter Register */ --#define AT91_PDC_TNPR 0x118 /* Transmit Next Pointer Register */ --#define AT91_PDC_TNCR 0x11c /* Transmit Next Counter Register */ -- --#define AT91_PDC_PTCR 0x120 /* Transfer Control Register */ --#define AT91_PDC_RXTEN (1 << 0) /* Receiver Transfer Enable */ --#define AT91_PDC_RXTDIS (1 << 1) /* Receiver Transfer Disable */ --#define AT91_PDC_TXTEN (1 << 8) /* Transmitter Transfer Enable */ --#define AT91_PDC_TXTDIS (1 << 9) /* Transmitter Transfer Disable */ -- --#define AT91_PDC_PTSR 0x124 /* Transfer Status Register */ -- --#endif -diff -urN linux-2.6.20.4-0rig/include/asm-avr32/arch-at32ap/board.h linux-2.6.20.4-atmel/include/asm-avr32/arch-at32ap/board.h ---- linux-2.6.20.4-0rig/include/asm-avr32/arch-at32ap/board.h 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/asm-avr32/arch-at32ap/board.h 2007-03-24 16:42:29.000000000 +0100 -@@ -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); - -@@ -26,7 +28,19 @@ - struct platform_device * - at32_add_device_eth(unsigned int id, struct eth_platform_data *data); - --struct platform_device *at32_add_device_spi(unsigned int id); -+struct spi_board_info; -+struct platform_device * -+at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n); -+ -+struct platform_device *at32_add_device_twi(unsigned int id); -+ -+struct mci_platform_data { -+ int detect_pin; -+ int wp_pin; -+}; -+struct platform_device * -+at32_add_device_mci(unsigned int id, struct mci_platform_data *data); -+struct platform_device *at32_add_device_usba(unsigned int id); - - struct lcdc_platform_data { - unsigned long fbmem_start; -@@ -35,4 +49,8 @@ - struct platform_device * - at32_add_device_lcdc(unsigned int id, struct lcdc_platform_data *data); - -+struct platform_device *at32_add_device_ac97c(unsigned int id); -+struct platform_device *at32_add_device_abdac(unsigned int id); -+struct platform_device *at32_add_device_isi(unsigned int id); -+ - #endif /* __ASM_ARCH_BOARD_H */ -diff -urN linux-2.6.20.4-0rig/include/asm-avr32/arch-at32ap/gpio.h linux-2.6.20.4-atmel/include/asm-avr32/arch-at32ap/gpio.h ---- linux-2.6.20.4-0rig/include/asm-avr32/arch-at32ap/gpio.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/asm-avr32/arch-at32ap/gpio.h 2007-03-24 16:42:28.000000000 +0100 -@@ -0,0 +1,27 @@ -+#ifndef __ASM_AVR32_ARCH_GPIO_H -+#define __ASM_AVR32_ARCH_GPIO_H -+ -+#include <linux/compiler.h> -+#include <asm/irq.h> -+ -+ -+/* Arch-neutral GPIO API */ -+int __must_check gpio_request(unsigned int gpio, const char *label); -+void gpio_free(unsigned int gpio); -+ -+int gpio_direction_input(unsigned int gpio); -+int gpio_direction_output(unsigned int gpio); -+int gpio_get_value(unsigned int gpio); -+void gpio_set_value(unsigned int gpio, int value); -+ -+static inline int gpio_to_irq(unsigned int gpio) -+{ -+ return gpio + GPIO_IRQ_BASE; -+} -+ -+static inline int irq_to_gpio(unsigned int irq) -+{ -+ return irq - GPIO_IRQ_BASE; -+} -+ -+#endif /* __ASM_AVR32_ARCH_GPIO_H */ -diff -urN linux-2.6.20.4-0rig/include/asm-avr32/arch-at32ap/irq.h linux-2.6.20.4-atmel/include/asm-avr32/arch-at32ap/irq.h ---- linux-2.6.20.4-0rig/include/asm-avr32/arch-at32ap/irq.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/asm-avr32/arch-at32ap/irq.h 2007-03-24 16:42:28.000000000 +0100 -@@ -0,0 +1,14 @@ -+#ifndef __ASM_AVR32_ARCH_IRQ_H -+#define __ASM_AVR32_ARCH_IRQ_H -+ -+#define EIM_IRQ_BASE NR_INTERNAL_IRQS -+#define NR_EIM_IRQS 32 -+ -+#define AT32_EXTINT(n) (EIM_IRQ_BASE + (n)) -+ -+#define GPIO_IRQ_BASE (EIM_IRQ_BASE + NR_EIM_IRQS) -+#define NR_GPIO_IRQS (5 * 32) -+ -+#define NR_IRQS (GPIO_IRQ_BASE + NR_GPIO_IRQS) -+ -+#endif /* __ASM_AVR32_ARCH_IRQ_H */ -diff -urN linux-2.6.20.4-0rig/include/asm-avr32/arch-at32ap/portmux.h linux-2.6.20.4-atmel/include/asm-avr32/arch-at32ap/portmux.h ---- linux-2.6.20.4-0rig/include/asm-avr32/arch-at32ap/portmux.h 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/asm-avr32/arch-at32ap/portmux.h 2007-03-24 16:42:28.000000000 +0100 -@@ -15,12 +15,14 @@ - * - * The following flags determine the initial state of the pin. - */ --#define AT32_GPIOF_PULLUP 0x00000001 /* Enable pull-up */ --#define AT32_GPIOF_OUTPUT 0x00000002 /* Enable output driver */ --#define AT32_GPIOF_HIGH 0x00000004 /* Set output high */ -+#define AT32_GPIOF_PULLUP 0x00000001 /* (not-OUT) Enable pull-up */ -+#define AT32_GPIOF_OUTPUT 0x00000002 /* (OUT) Enable output driver */ -+#define AT32_GPIOF_HIGH 0x00000004 /* (OUT) Set output high */ -+#define AT32_GPIOF_DEGLITCH 0x00000008 /* (IN) Filter glitches */ - - void at32_select_periph(unsigned int pin, unsigned int periph, - unsigned long flags); - void at32_select_gpio(unsigned int pin, unsigned long flags); -+void at32_reserve_pin(unsigned int pin); - - #endif /* __ASM_ARCH_PORTMUX_H__ */ -diff -urN linux-2.6.20.4-0rig/include/asm-avr32/arch-at32ap/smc.h linux-2.6.20.4-atmel/include/asm-avr32/arch-at32ap/smc.h ---- linux-2.6.20.4-0rig/include/asm-avr32/arch-at32ap/smc.h 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/asm-avr32/arch-at32ap/smc.h 2007-03-24 16:42:29.000000000 +0100 -@@ -48,10 +48,32 @@ - unsigned int nwe_controlled:1; - - /* -+ * 0: NWAIT is disabled -+ * 1: Reserved -+ * 2: NWAIT is frozen mode -+ * 3: NWAIT in ready mode -+ */ -+ unsigned int nwait_mode:2; -+ -+ /* - * 0: Byte select access type - * 1: Byte write access type - */ - unsigned int byte_write:1; -+ -+ /* -+ * Number of clock cycles before data is released after -+ * the rising edge of the read controlling signal -+ * -+ * Total cycles from SMC is tdf_cycles + 1 -+ */ -+ unsigned int tdf_cycles:4; -+ -+ /* -+ * 0: TDF optimization disabled -+ * 1: TDF optimization enabled -+ */ -+ unsigned int tdf_mode:1; - }; - - extern int smc_set_configuration(int cs, const struct smc_config *config); -diff -urN linux-2.6.20.4-0rig/include/asm-avr32/checksum.h linux-2.6.20.4-atmel/include/asm-avr32/checksum.h ---- linux-2.6.20.4-0rig/include/asm-avr32/checksum.h 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/asm-avr32/checksum.h 2007-03-24 16:42:28.000000000 +0100 -@@ -38,7 +38,7 @@ - * passed in an incorrect kernel address to one of these functions. - * - * If you use these functions directly please don't forget the -- * verify_area(). -+ * access_ok(). - */ - static inline - __wsum csum_partial_copy_nocheck(const void *src, void *dst, -diff -urN linux-2.6.20.4-0rig/include/asm-avr32/dma-controller.h linux-2.6.20.4-atmel/include/asm-avr32/dma-controller.h ---- linux-2.6.20.4-0rig/include/asm-avr32/dma-controller.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/asm-avr32/dma-controller.h 2007-03-24 16:42:29.000000000 +0100 -@@ -0,0 +1,166 @@ -+/* -+ * Copyright (C) 2005-2006 Atmel Corporation -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+#ifndef __ASM_AVR32_DMA_CONTROLLER_H -+#define __ASM_AVR32_DMA_CONTROLLER_H -+ -+#include <linux/device.h> -+ -+#define DMA_DIR_MEM_TO_MEM 0x0000 -+#define DMA_DIR_MEM_TO_PERIPH 0x0001 -+#define DMA_DIR_PERIPH_TO_MEM 0x0002 -+#define DMA_DIR_PERIPH_TO_PERIPH 0x0003 -+ -+#define DMA_WIDTH_8BIT 0 -+#define DMA_WIDTH_16BIT 1 -+#define DMA_WIDTH_32BIT 2 -+ -+struct dma_request { -+ struct dma_controller *dmac; -+ struct list_head list; -+ -+ unsigned short channel; -+ -+ void (*xfer_complete)(struct dma_request *req); -+ void (*block_complete)(struct dma_request *req); -+ void (*error)(struct dma_request *req); -+}; -+ -+struct dma_request_sg { -+ struct dma_request req; -+ -+ int nr_sg; -+ struct scatterlist *sg; -+ unsigned long block_size; -+ unsigned int nr_blocks; -+ -+ dma_addr_t data_reg; -+ unsigned short periph_id; -+ -+ unsigned char direction; -+ unsigned char width; -+}; -+#define to_dma_request_sg(_req) \ -+ container_of(_req, struct dma_request_sg, req) -+ -+struct dma_request_cyclic { -+ struct dma_request req; -+ -+ int periods; -+ unsigned long buffer_size; -+ -+ dma_addr_t buffer_start; -+ dma_addr_t data_reg; -+ -+ unsigned short periph_id; -+ unsigned char direction; -+ unsigned char width; -+ -+ void *dev_id; -+}; -+#define to_dma_request_cyclic(_req) \ -+ container_of(_req, struct dma_request_cyclic, req) -+ -+struct dma_request_memcpy { -+ struct dma_request req; -+ -+ dma_addr_t src_addr; -+ unsigned int src_width; -+ unsigned int src_stride; -+ -+ dma_addr_t dst_addr; -+ unsigned int dst_width; -+ unsigned int dst_stride; -+ -+ size_t length; -+ -+ unsigned short src_reverse:1; -+ unsigned short dst_reverse:1; -+}; -+#define to_dma_request_memcpy(_req) \ -+ container_of(_req, struct dma_request_memcpy, req) -+ -+struct dma_controller { -+ struct list_head list; -+ int id; -+ struct device *dev; -+ -+ int (*alloc_channel)(struct dma_controller *dmac); -+ void (*release_channel)(struct dma_controller *dmac, -+ int channel); -+ int (*prepare_request_sg)(struct dma_controller *dmac, -+ struct dma_request_sg *req); -+ int (*prepare_request_cyclic)(struct dma_controller *dmac, -+ struct dma_request_cyclic *req); -+ int (*prepare_request_memcpy)(struct dma_controller *dmac, -+ struct dma_request_memcpy *req); -+ int (*start_request)(struct dma_controller *dmac, -+ unsigned int channel); -+ int (*stop_request)(struct dma_controller *dmac, -+ unsigned int channel); -+ dma_addr_t (*get_current_pos)(struct dma_controller *dmac, -+ unsigned int channel); -+}; -+ -+static inline int -+dma_alloc_channel(struct dma_controller *dmac) -+{ -+ return dmac->alloc_channel(dmac); -+} -+ -+static inline void -+dma_release_channel(struct dma_controller *dmac, int chan) -+{ -+ dmac->release_channel(dmac, chan); -+} -+ -+static inline int -+dma_prepare_request_sg(struct dma_controller *dmac, -+ struct dma_request_sg *req) -+{ -+ return dmac->prepare_request_sg(dmac, req); -+} -+ -+static inline int -+dma_prepare_request_cyclic(struct dma_controller *dmac, -+ struct dma_request_cyclic *req) -+{ -+ return dmac->prepare_request_cyclic(dmac, req); -+} -+ -+static inline int -+dma_prepare_request_memcpy(struct dma_controller *dmac, -+ struct dma_request_memcpy *req) -+{ -+ return dmac->prepare_request_memcpy(dmac, req); -+} -+ -+static inline int -+dma_start_request(struct dma_controller *dmac, -+ unsigned int channel) -+{ -+ return dmac->start_request(dmac, channel); -+} -+ -+static inline int -+dma_stop_request(struct dma_controller *dmac, -+ unsigned int channel) -+{ -+ return dmac->stop_request(dmac, channel); -+} -+ -+static inline dma_addr_t -+dma_get_current_pos(struct dma_controller *dmac, -+ unsigned int channel) -+{ -+ return dmac->get_current_pos(dmac, channel); -+} -+ -+extern int register_dma_controller(struct dma_controller *dmac); -+extern struct dma_controller *find_dma_controller(int id); -+ -+#endif /* __ASM_AVR32_DMA_CONTROLLER_H */ -diff -urN linux-2.6.20.4-0rig/include/asm-avr32/dma-mapping.h linux-2.6.20.4-atmel/include/asm-avr32/dma-mapping.h ---- linux-2.6.20.4-0rig/include/asm-avr32/dma-mapping.h 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/asm-avr32/dma-mapping.h 2007-03-24 16:42:28.000000000 +0100 -@@ -32,6 +32,14 @@ - return 0; - } - -+/* -+ * dma_map_single can't fail as it is implemented now. -+ */ -+static inline int dma_mapping_error(dma_addr_t addr) -+{ -+ return 0; -+} -+ - /** - * dma_alloc_coherent - allocate consistent memory for DMA - * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices -diff -urN linux-2.6.20.4-0rig/include/asm-avr32/gpio.h linux-2.6.20.4-atmel/include/asm-avr32/gpio.h ---- linux-2.6.20.4-0rig/include/asm-avr32/gpio.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/asm-avr32/gpio.h 2007-03-24 16:42:28.000000000 +0100 -@@ -0,0 +1,6 @@ -+#ifndef __ASM_AVR32_GPIO_H -+#define __ASM_AVR32_GPIO_H -+ -+#include <asm/arch/gpio.h> -+ -+#endif /* __ASM_AVR32_GPIO_H */ -diff -urN linux-2.6.20.4-0rig/include/asm-avr32/ide.h linux-2.6.20.4-atmel/include/asm-avr32/ide.h ---- linux-2.6.20.4-0rig/include/asm-avr32/ide.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/asm-avr32/ide.h 2007-03-24 16:42:29.000000000 +0100 -@@ -0,0 +1,36 @@ -+/* -+ * linux/include/asm-arm/ide.h -+ * -+ * Copyright (C) 1994-1996 Linus Torvalds & authors -+ */ -+ -+/* -+ * This file contains the ARM architecture specific IDE code. -+ */ -+ -+#ifndef __ASMAVR32_IDE_H -+#define __ASMAVR32_IDE_H -+ -+#ifdef __KERNEL__ -+ -+#ifndef MAX_HWIFS -+#define MAX_HWIFS 4 -+#endif -+ -+#if !defined(CONFIG_ARCH_L7200) -+# define IDE_ARCH_OBSOLETE_INIT -+# ifdef CONFIG_ARCH_CLPS7500 -+# define ide_default_io_ctl(base) ((base) + 0x206) /* obsolete */ -+# else -+# define ide_default_io_ctl(base) (0) -+# endif -+#endif /* !ARCH_L7200 */ -+ -+#define __ide_mm_insw(port,addr,len) readsw(port,addr,len) -+#define __ide_mm_insl(port,addr,len) readsl(port,addr,len) -+#define __ide_mm_outsw(port,addr,len) writesw(port,addr,len) -+#define __ide_mm_outsl(port,addr,len) writesl(port,addr,len) -+ -+#endif /* __KERNEL__ */ -+ -+#endif /* __ASMAVR32_IDE_H */ -diff -urN linux-2.6.20.4-0rig/include/asm-avr32/io.h linux-2.6.20.4-atmel/include/asm-avr32/io.h ---- linux-2.6.20.4-0rig/include/asm-avr32/io.h 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/asm-avr32/io.h 2007-03-24 16:42:29.000000000 +0100 -@@ -5,6 +5,8 @@ - - #ifdef __KERNEL__ - -+#include <linux/types.h> -+ - #include <asm/addrspace.h> - #include <asm/byteorder.h> - -@@ -28,45 +30,72 @@ - * Generic IO read/write. These perform native-endian accesses. Note - * that some architectures will want to re-define __raw_{read,write}w. - */ --extern void __raw_writesb(unsigned int addr, const void *data, int bytelen); --extern void __raw_writesw(unsigned int addr, const void *data, int wordlen); --extern void __raw_writesl(unsigned int addr, const void *data, int longlen); -+extern void __raw_writesb(void __iomem *addr, const void *data, int bytelen); -+extern void __raw_writesw(void __iomem *addr, const void *data, int wordlen); -+extern void __raw_writesl(void __iomem *addr, const void *data, int longlen); -+ -+extern void __raw_readsb(const void __iomem *addr, void *data, int bytelen); -+extern void __raw_readsw(const void __iomem *addr, void *data, int wordlen); -+extern void __raw_readsl(const void __iomem *addr, void *data, int longlen); -+ -+static inline void __raw_writeb(u8 v, volatile void __iomem *addr) -+{ -+ *(volatile u8 __force *)addr = v; -+} -+static inline void __raw_writew(u16 v, volatile void __iomem *addr) -+{ -+ *(volatile u16 __force *)addr = v; -+} -+static inline void __raw_writel(u32 v, volatile void __iomem *addr) -+{ -+ *(volatile u32 __force *)addr = v; -+} -+ -+static inline u8 __raw_readb(const volatile void __iomem *addr) -+{ -+ return *(const volatile u8 __force *)addr; -+} -+static inline u16 __raw_readw(const volatile void __iomem *addr) -+{ -+ return *(const volatile u16 __force *)addr; -+} -+static inline u32 __raw_readl(const volatile void __iomem *addr) -+{ -+ return *(const volatile u32 __force *)addr; -+} - --extern void __raw_readsb(unsigned int addr, void *data, int bytelen); --extern void __raw_readsw(unsigned int addr, void *data, int wordlen); --extern void __raw_readsl(unsigned int addr, void *data, int longlen); -+#define __swizzle_addr_b(addr) \ -+ ((typeof(addr))((unsigned long)(addr) ^ 3UL)) -+#define __swizzle_addr_w(addr) \ -+ ((typeof(addr))((unsigned long)(addr) ^ 2UL)) -+#define __swizzle_addr_l(addr) \ -+ (addr) - --static inline void writeb(unsigned char b, volatile void __iomem *addr) -+static inline void writeb(u8 v, volatile void __iomem *addr) - { -- *(volatile unsigned char __force *)addr = b; -+ __raw_writeb(v, __swizzle_addr_b(addr)); - } --static inline void writew(unsigned short b, volatile void __iomem *addr) -+static inline void writew(u16 v, volatile void __iomem *addr) - { -- *(volatile unsigned short __force *)addr = b; -+ __raw_writew(v, __swizzle_addr_w(addr)); - } --static inline void writel(unsigned int b, volatile void __iomem *addr) -+static inline void writel(u32 v, volatile void __iomem *addr) - { -- *(volatile unsigned int __force *)addr = b; -+ __raw_writel(v, __swizzle_addr_l(addr)); - } --#define __raw_writeb writeb --#define __raw_writew writew --#define __raw_writel writel - --static inline unsigned char readb(const volatile void __iomem *addr) -+static inline u8 readb(const volatile void __iomem *addr) - { -- return *(const volatile unsigned char __force *)addr; -+ return __raw_readb(__swizzle_addr_b(addr)); - } --static inline unsigned short readw(const volatile void __iomem *addr) -+static inline u16 readw(const volatile void __iomem *addr) - { -- return *(const volatile unsigned short __force *)addr; -+ return __raw_readw(__swizzle_addr_w(addr)); - } --static inline unsigned int readl(const volatile void __iomem *addr) -+static inline u32 readl(const volatile void __iomem *addr) - { -- return *(const volatile unsigned int __force *)addr; -+ return __raw_readl(__swizzle_addr_l(addr)); - } --#define __raw_readb readb --#define __raw_readw readw --#define __raw_readl readl - - #define writesb(p, d, l) __raw_writesb((unsigned int)p, d, l) - #define writesw(p, d, l) __raw_writesw((unsigned int)p, d, l) -@@ -108,17 +137,13 @@ - - #endif - -- --/* -- * These two are only here because ALSA _thinks_ it needs them... -- */ - static inline void memcpy_fromio(void * to, const volatile void __iomem *from, - unsigned long count) - { - char *p = to; - while (count) { - count--; -- *p = readb(from); -+ *p = __raw_readb(from); - p++; - from++; - } -@@ -130,7 +155,7 @@ - const char *p = from; - while (count) { - count--; -- writeb(*p, to); -+ __raw_writeb(*p, to); - p++; - to++; - } -@@ -252,6 +277,9 @@ - #define ioremap(offset, size) \ - __ioremap((offset), (size), 0) - -+#define ioremap_nocache(offset, size) \ -+ __ioremap((offset), (size), 0) -+ - #define iounmap(addr) \ - __iounmap(addr) - -@@ -263,6 +291,14 @@ - #define page_to_bus page_to_phys - #define bus_to_page phys_to_page - -+/* -+ * Create a virtual mapping cookie for an IO port range. There exists -+ * no such thing as port-based I/O on AVR32, so a regular ioremap() -+ * should do what we need. -+ */ -+#define ioport_map(port, nr) ioremap(port, nr) -+#define ioport_unmap(port) iounmap(port) -+ - #define dma_cache_wback_inv(_start, _size) \ - flush_dcache_region(_start, _size) - #define dma_cache_inv(_start, _size) \ -diff -urN linux-2.6.20.4-0rig/include/asm-avr32/irq.h linux-2.6.20.4-atmel/include/asm-avr32/irq.h ---- linux-2.6.20.4-0rig/include/asm-avr32/irq.h 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/asm-avr32/irq.h 2007-03-24 16:42:28.000000000 +0100 -@@ -2,8 +2,12 @@ - #define __ASM_AVR32_IRQ_H - - #define NR_INTERNAL_IRQS 64 --#define NR_EXTERNAL_IRQS 64 --#define NR_IRQS (NR_INTERNAL_IRQS + NR_EXTERNAL_IRQS) -+ -+#include <asm/arch/irq.h> -+ -+#ifndef NR_IRQS -+#define NR_IRQS (NR_INTERNAL_IRQS) -+#endif - - #define irq_canonicalize(i) (i) - -diff -urN linux-2.6.20.4-0rig/include/asm-avr32/Kbuild linux-2.6.20.4-atmel/include/asm-avr32/Kbuild ---- linux-2.6.20.4-0rig/include/asm-avr32/Kbuild 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/asm-avr32/Kbuild 2007-03-24 16:42:28.000000000 +0100 -@@ -1,3 +1,3 @@ - include include/asm-generic/Kbuild.asm - --headers-y += cachectl.h -+header-y += cachectl.h -diff -urN linux-2.6.20.4-0rig/include/asm-avr32/periph/lcdc.h linux-2.6.20.4-atmel/include/asm-avr32/periph/lcdc.h ---- linux-2.6.20.4-0rig/include/asm-avr32/periph/lcdc.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/asm-avr32/periph/lcdc.h 2007-03-24 16:42:29.000000000 +0100 -@@ -0,0 +1,271 @@ -+/* -+ * Register definitions for Atmel/SIDSA LCD Controller -+ * -+ * Copyright (C) 2004-2006 Atmel Corporation -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+#ifndef __ASM_AVR32_PERIPH_LCDC_H__ -+#define __ASM_AVR32_PERIPH_LCDC_H__ -+ -+#define LCDC_CONTRAST_CTR 0x00000840 -+# define LCDC_CONTRAST_CTR_ENA_OFFSET 3 -+# define LCDC_CONTRAST_CTR_ENA_SIZE 1 -+# define LCDC_CONTRAST_CTR_POL_OFFSET 2 -+# define LCDC_CONTRAST_CTR_POL_SIZE 1 -+# define LCDC_CONTRAST_CTR_PS_OFFSET 0 -+# define LCDC_CONTRAST_CTR_PS_SIZE 2 -+#define LCDC_CONTRAST_VAL 0x00000844 -+# define LCDC_CONTRAST_VAL_CVAL_OFFSET 0 -+# define LCDC_CONTRAST_VAL_CVAL_SIZE 8 -+#define LCDC_DMABADDR1 0x00000000 -+# define LCDC_DMABADDR1_BADDR_U_OFFSET 0 -+# define LCDC_DMABADDR1_BADDR_U_SIZE 32 -+#define LCDC_DMABADDR2 0x00000004 -+# define LCDC_DMABADDR2_BADDR_L_OFFSET 0 -+# define LCDC_DMABADDR2_BADDR_L_SIZE 32 -+#define LCDC_DMACON 0x0000001C -+# define LCDC_DMACON_DMABUSY_OFFSET 2 -+# define LCDC_DMACON_DMABUSY_SIZE 1 -+# define LCDC_DMACON_DMAEN_OFFSET 0 -+# define LCDC_DMACON_DMAEN_SIZE 1 -+# define LCDC_DMACON_DMARST_OFFSET 1 -+# define LCDC_DMACON_DMARST_SIZE 1 -+# define LCDC_DMACON_DMAUPDT_OFFSET 3 -+# define LCDC_DMACON_DMAUPDT_SIZE 1 -+# define LCDC_DMACON_DMA2DEN_OFFSET 4 -+# define LCDC_DMACON_DMA2DEN_SIZE 1 -+#define LCDC_DMAFRMADD1 0x00000010 -+# define LCDC_DMAFRMADD1_FRMADD_U_OFFSET 0 -+# define LCDC_DMAFRMADD1_FRMADD_U_SIZE 32 -+#define LCDC_DMAFRMADD2 0x00000014 -+# define LCDC_DMAFRMADD2_FRMADD_L_OFFSET 0 -+# define LCDC_DMAFRMADD2_FRMADD_L_SIZE 32 -+#define LCDC_DMAFRMCFG 0x00000018 -+# define LCDC_DMAFRMCFG_BRSTLEN_OFFSET 24 -+# define LCDC_DMAFRMCFG_BRSTLEN_SIZE 7 -+# define LCDC_DMAFRMCFG_FRMSIZE_OFFSET 0 -+# define LCDC_DMAFRMCFG_FRMSIZE_SIZE 23 -+#define LCDC_DMAFRMPT1 0x00000008 -+# define LCDC_DMAFRMPT1_FRMPT_U_OFFSET 0 -+# define LCDC_DMAFRMPT1_FRMPT_U_SIZE 23 -+#define LCDC_DMAFRMPT2 0x0000000C -+# define LCDC_DMAFRMPT2_FRMPT_L_OFFSET 0 -+# define LCDC_DMAFRMPT2_FRMPT_L_SIZE 23 -+#define LCDC_DMA2DCFG 0x00000020 -+# define LCDC_DMA2DCFG_ADDRINC_OFFSET 0 -+# define LCDC_DMA2DCFG_ADDRINC_SIZE 16 -+# define LCDC_DMA2DCFG_PIXELOFF_OFFSET 24 -+# define LCDC_DMA2DCFG_PIXELOFF_SIZE 5 -+#define LCDC_DP1_2 0x0000081C -+# define LCDC_DP1_2_DP1_2_OFFSET 0 -+# define LCDC_DP1_2_DP1_2_SIZE 8 -+#define LCDC_DP2_3 0x00000828 -+# define LCDC_DP2_3_DP2_3_OFFSET 0 -+# define LCDC_DP2_3_DP2_3_SIZE 12 -+#define LCDC_DP3_4 0x00000830 -+# define LCDC_DP3_4_DP3_4_OFFSET 0 -+# define LCDC_DP3_4_DP3_4_SIZE 16 -+#define LCDC_DP3_5 0x00000824 -+# define LCDC_DP3_5_DP3_5_OFFSET 0 -+# define LCDC_DP3_5_DP3_5_SIZE 20 -+#define LCDC_DP4_5 0x00000834 -+# define LCDC_DP4_5_DP4_5_OFFSET 0 -+# define LCDC_DP4_5_DP4_5_SIZE 20 -+#define LCDC_DP4_7 0x00000820 -+# define LCDC_DP4_7_DP4_7_OFFSET 0 -+# define LCDC_DP4_7_DP4_7_SIZE 28 -+#define LCDC_DP5_7 0x0000082C -+# define LCDC_DP5_7_DP5_7_OFFSET 0 -+# define LCDC_DP5_7_DP5_7_SIZE 28 -+#define LCDC_DP6_7 0x00000838 -+# define LCDC_DP6_7_DP6_7_OFFSET 0 -+# define LCDC_DP6_7_DP6_7_SIZE 28 -+#define LCDC_LCDCON1 0x00000800 -+# define LCDC_LCDCON1_BYPASS_OFFSET 0 -+# define LCDC_LCDCON1_BYPASS_SIZE 1 -+# define LCDC_LCDCON1_CLKVAL_OFFSET 12 -+# define LCDC_LCDCON1_CLKVAL_SIZE 9 -+# define LCDC_LCDCON1_LINECNT_OFFSET 21 -+# define LCDC_LCDCON1_LINECNT_SIZE 11 -+#define LCDC_LCDCON2 0x00000804 -+# define LCDC_LCDCON2_CLKMOD_OFFSET 15 -+# define LCDC_LCDCON2_CLKMOD_SIZE 1 -+# define LCDC_LCDCON2_DISTYPE_OFFSET 0 -+# define LCDC_LCDCON2_DISTYPE_SIZE 2 -+# define LCDC_LCDCON2_IFWIDTH_OFFSET 3 -+# define LCDC_LCDCON2_IFWIDTH_SIZE 2 -+# define LCDC_LCDCON2_INVCLK_OFFSET 11 -+# define LCDC_LCDCON2_INVCLK_SIZE 1 -+# define LCDC_LCDCON2_INVDVAL_OFFSET 12 -+# define LCDC_LCDCON2_INVDVAL_SIZE 1 -+# define LCDC_LCDCON2_INVFRAME_OFFSET 9 -+# define LCDC_LCDCON2_INVFRAME_SIZE 1 -+# define LCDC_LCDCON2_INVLINE_OFFSET 10 -+# define LCDC_LCDCON2_INVLINE_SIZE 1 -+# define LCDC_LCDCON2_INVVD_OFFSET 8 -+# define LCDC_LCDCON2_INVVD_SIZE 1 -+# define LCDC_LCDCON2_MEMOR_OFFSET 30 -+# define LCDC_LCDCON2_MEMOR_SIZE 2 -+# define LCDC_LCDCON2_PIXELSIZE_OFFSET 5 -+# define LCDC_LCDCON2_PIXELSIZE_SIZE 3 -+# define LCDC_LCDCON2_SCANMOD_OFFSET 2 -+# define LCDC_LCDCON2_SCANMOD_SIZE 1 -+#define LCDC_LCDFIFO 0x00000814 -+# define LCDC_LCDFIFO_FIFOTH_OFFSET 0 -+# define LCDC_LCDFIFO_FIFOTH_SIZE 16 -+#define LCDC_LCDFRMCFG 0x00000810 -+# define LCDC_LCDFRMCFG_LINESIZE_OFFSET 21 -+# define LCDC_LCDFRMCFG_LINESIZE_SIZE 11 -+# define LCDC_LCDFRMCFG_LINEVAL_OFFSET 0 -+# define LCDC_LCDFRMCFG_LINEVAL_SIZE 11 -+#define LCDC_LCDMVAL 0x00000818 -+# define LCDC_LCDMVAL_MMODE_OFFSET 31 -+# define LCDC_LCDMVAL_MMODE_SIZE 1 -+# define LCDC_LCDMVAL_MVAL_OFFSET 0 -+# define LCDC_LCDMVAL_MVAL_SIZE 8 -+#define LCDC_LCDTIM1 0x00000808 -+# define LCDC_LCDTIM1_VBP_OFFSET 8 -+# define LCDC_LCDTIM1_VBP_SIZE 8 -+# define LCDC_LCDTIM1_VFP_OFFSET 0 -+# define LCDC_LCDTIM1_VFP_SIZE 8 -+# define LCDC_LCDTIM1_VHDLY_OFFSET 24 -+# define LCDC_LCDTIM1_VHDLY_SIZE 4 -+# define LCDC_LCDTIM1_VPW_OFFSET 16 -+# define LCDC_LCDTIM1_VPW_SIZE 6 -+#define LCDC_LCDTIM2 0x0000080C -+# define LCDC_LCDTIM2_HBP_OFFSET 0 -+# define LCDC_LCDTIM2_HBP_SIZE 8 -+# define LCDC_LCDTIM2_HFP_OFFSET 21 -+# define LCDC_LCDTIM2_HFP_SIZE 11 -+# define LCDC_LCDTIM2_HPW_OFFSET 8 -+# define LCDC_LCDTIM2_HPW_SIZE 6 -+#define LCDC_LCD_GPR 0x0000085C -+# define LCDC_LCD_GPR_GPRB0_OFFSET 0 -+# define LCDC_LCD_GPR_GPRB0_SIZE 1 -+# define LCDC_LCD_GPR_GPRB1_OFFSET 1 -+# define LCDC_LCD_GPR_GPRB1_SIZE 1 -+# define LCDC_LCD_GPR_GPRB2_OFFSET 2 -+# define LCDC_LCD_GPR_GPRB2_SIZE 1 -+# define LCDC_LCD_GPR_GPRB3_OFFSET 3 -+# define LCDC_LCD_GPR_GPRB3_SIZE 1 -+# define LCDC_LCD_GPR_GPRB4_OFFSET 4 -+# define LCDC_LCD_GPR_GPRB4_SIZE 1 -+# define LCDC_LCD_GPR_GPRB5_OFFSET 5 -+# define LCDC_LCD_GPR_GPRB5_SIZE 1 -+# define LCDC_LCD_GPR_GPRB6_OFFSET 6 -+# define LCDC_LCD_GPR_GPRB6_SIZE 1 -+# define LCDC_LCD_GPR_GPRB7_OFFSET 7 -+# define LCDC_LCD_GPR_GPRB7_SIZE 1 -+#define LCDC_LCD_ICR 0x00000858 -+# define LCDC_LCD_ICR_EOFIC_OFFSET 2 -+# define LCDC_LCD_ICR_EOFIC_SIZE 1 -+# define LCDC_LCD_ICR_LNIC_OFFSET 0 -+# define LCDC_LCD_ICR_LNIC_SIZE 1 -+# define LCDC_LCD_ICR_LSTLNIC_OFFSET 1 -+# define LCDC_LCD_ICR_LSTLNIC_SIZE 1 -+# define LCDC_LCD_ICR_MERIC_OFFSET 6 -+# define LCDC_LCD_ICR_MERIC_SIZE 1 -+# define LCDC_LCD_ICR_OWRIC_OFFSET 5 -+# define LCDC_LCD_ICR_OWRIC_SIZE 1 -+# define LCDC_LCD_ICR_UFLWIC_OFFSET 4 -+# define LCDC_LCD_ICR_UFLWIC_SIZE 1 -+#define LCDC_LCD_IDR 0x0000084C -+# define LCDC_LCD_IDR_EOFID_OFFSET 2 -+# define LCDC_LCD_IDR_EOFID_SIZE 1 -+# define LCDC_LCD_IDR_LNID_OFFSET 0 -+# define LCDC_LCD_IDR_LNID_SIZE 1 -+# define LCDC_LCD_IDR_LSTLNID_OFFSET 1 -+# define LCDC_LCD_IDR_LSTLNID_SIZE 1 -+# define LCDC_LCD_IDR_MERID_OFFSET 6 -+# define LCDC_LCD_IDR_MERID_SIZE 1 -+# define LCDC_LCD_IDR_OWRID_OFFSET 5 -+# define LCDC_LCD_IDR_OWRID_SIZE 1 -+# define LCDC_LCD_IDR_UFLWID_OFFSET 4 -+# define LCDC_LCD_IDR_UFLWID_SIZE 1 -+#define LCDC_LCD_IER 0x00000848 -+# define LCDC_LCD_IER_EOFIE_OFFSET 2 -+# define LCDC_LCD_IER_EOFIE_SIZE 1 -+# define LCDC_LCD_IER_LNIE_OFFSET 0 -+# define LCDC_LCD_IER_LNIE_SIZE 1 -+# define LCDC_LCD_IER_LSTLNIE_OFFSET 1 -+# define LCDC_LCD_IER_LSTLNIE_SIZE 1 -+# define LCDC_LCD_IER_MERIE_OFFSET 6 -+# define LCDC_LCD_IER_MERIE_SIZE 1 -+# define LCDC_LCD_IER_OWRIE_OFFSET 5 -+# define LCDC_LCD_IER_OWRIE_SIZE 1 -+# define LCDC_LCD_IER_UFLWIE_OFFSET 4 -+# define LCDC_LCD_IER_UFLWIE_SIZE 1 -+#define LCDC_LCD_IMR 0x00000850 -+# define LCDC_LCD_IMR_EOFIM_OFFSET 2 -+# define LCDC_LCD_IMR_EOFIM_SIZE 1 -+# define LCDC_LCD_IMR_LNIM_OFFSET 0 -+# define LCDC_LCD_IMR_LNIM_SIZE 1 -+# define LCDC_LCD_IMR_LSTLNIM_OFFSET 1 -+# define LCDC_LCD_IMR_LSTLNIM_SIZE 1 -+# define LCDC_LCD_IMR_MERIM_OFFSET 6 -+# define LCDC_LCD_IMR_MERIM_SIZE 1 -+# define LCDC_LCD_IMR_OWRIM_OFFSET 5 -+# define LCDC_LCD_IMR_OWRIM_SIZE 1 -+# define LCDC_LCD_IMR_UFLWIM_OFFSET 4 -+# define LCDC_LCD_IMR_UFLWIM_SIZE 1 -+#define LCDC_LCD_IRR 0x00000864 -+# define LCDC_LCD_IRR_EOFIR_OFFSET 2 -+# define LCDC_LCD_IRR_EOFIR_SIZE 1 -+# define LCDC_LCD_IRR_LNIR_OFFSET 0 -+# define LCDC_LCD_IRR_LNIR_SIZE 1 -+# define LCDC_LCD_IRR_LSTLNIR_OFFSET 1 -+# define LCDC_LCD_IRR_LSTLNIR_SIZE 1 -+# define LCDC_LCD_IRR_MERIR_OFFSET 6 -+# define LCDC_LCD_IRR_MERIR_SIZE 1 -+# define LCDC_LCD_IRR_OWRIR_OFFSET 5 -+# define LCDC_LCD_IRR_OWRIR_SIZE 1 -+# define LCDC_LCD_IRR_UFLWIR_OFFSET 4 -+# define LCDC_LCD_IRR_UFLWIR_SIZE 1 -+#define LCDC_LCD_ISR 0x00000854 -+# define LCDC_LCD_ISR_EOFIS_OFFSET 2 -+# define LCDC_LCD_ISR_EOFIS_SIZE 1 -+# define LCDC_LCD_ISR_LNIS_OFFSET 0 -+# define LCDC_LCD_ISR_LNIS_SIZE 1 -+# define LCDC_LCD_ISR_LSTLNIS_OFFSET 1 -+# define LCDC_LCD_ISR_LSTLNIS_SIZE 1 -+# define LCDC_LCD_ISR_MERIS_OFFSET 6 -+# define LCDC_LCD_ISR_MERIS_SIZE 1 -+# define LCDC_LCD_ISR_OWRIS_OFFSET 5 -+# define LCDC_LCD_ISR_OWRIS_SIZE 1 -+# define LCDC_LCD_ISR_UFLWIS_OFFSET 4 -+# define LCDC_LCD_ISR_UFLWIS_SIZE 1 -+#define LCDC_LCD_ITR 0x00000860 -+# define LCDC_LCD_ITR_EOFIT_OFFSET 2 -+# define LCDC_LCD_ITR_EOFIT_SIZE 1 -+# define LCDC_LCD_ITR_LNIT_OFFSET 0 -+# define LCDC_LCD_ITR_LNIT_SIZE 1 -+# define LCDC_LCD_ITR_LSTLNIT_OFFSET 1 -+# define LCDC_LCD_ITR_LSTLNIT_SIZE 1 -+# define LCDC_LCD_ITR_MERIT_OFFSET 6 -+# define LCDC_LCD_ITR_MERIT_SIZE 1 -+# define LCDC_LCD_ITR_OWRIT_OFFSET 5 -+# define LCDC_LCD_ITR_OWRIT_SIZE 1 -+# define LCDC_LCD_ITR_UFLWIT_OFFSET 4 -+# define LCDC_LCD_ITR_UFLWIT_SIZE 1 -+#define LCDC_PWRCON 0x0000083C -+# define LCDC_PWRCON_GUARD_TIME_OFFSET 1 -+# define LCDC_PWRCON_GUARD_TIME_SIZE 7 -+# define LCDC_PWRCON_LCD_BUSY_OFFSET 31 -+# define LCDC_PWRCON_LCD_BUSY_SIZE 1 -+# define LCDC_PWRCON_LCD_PWR_OFFSET 0 -+# define LCDC_PWRCON_LCD_PWR_SIZE 1 -+ -+#define LCDC_BIT(name) (1 << LCDC_##name##_OFFSET) -+#define LCDC_MKBF(name,value) (((value) & ((1 << LCDC_##name##_SIZE) - 1)) << LCDC_##name##_OFFSET) -+#define LCDC_GETBF(name,value) (((value) >> LCDC_##name##_OFFSET) & ((1 << LCDC_##name##_SIZE) - 1)) -+#define LCDC_INSBF(name,value,old) (((old) & ~(((1 << LCDC_##name##_SIZE) - 1) << LCDC_##name##_OFFSET)) | LCDC_MKBF(name, value)) -+ -+#define lcdc_readl(port,reg) \ -+ __raw_readl((port)->regs + LCDC_##reg) -+#define lcdc_writel(port,reg,value) \ -+ __raw_writel((value), (port)->regs + LCDC_##reg) -+ -+#endif /* __ASM_AVR32_PERIPH_LCDC_H__ */ -diff -urN linux-2.6.20.4-0rig/include/asm-avr32/posix_types.h linux-2.6.20.4-atmel/include/asm-avr32/posix_types.h ---- linux-2.6.20.4-0rig/include/asm-avr32/posix_types.h 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/asm-avr32/posix_types.h 2007-03-24 16:42:28.000000000 +0100 -@@ -23,7 +23,7 @@ - typedef unsigned int __kernel_uid_t; - typedef unsigned int __kernel_gid_t; - typedef unsigned long __kernel_size_t; --typedef int __kernel_ssize_t; -+typedef long __kernel_ssize_t; - typedef int __kernel_ptrdiff_t; - typedef long __kernel_time_t; - typedef long __kernel_suseconds_t; -diff -urN linux-2.6.20.4-0rig/include/asm-avr32/uaccess.h linux-2.6.20.4-atmel/include/asm-avr32/uaccess.h ---- linux-2.6.20.4-0rig/include/asm-avr32/uaccess.h 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/asm-avr32/uaccess.h 2007-03-24 16:42:28.000000000 +0100 -@@ -68,12 +68,6 @@ - - #define access_ok(type, addr, size) (likely(__range_ok(addr, size) == 0)) - --static inline int --verify_area(int type, const void __user *addr, unsigned long size) --{ -- return access_ok(type, addr, size) ? 0 : -EFAULT; --} -- - /* Generic arbitrary sized copy. Return the number of bytes NOT copied */ - extern __kernel_size_t __copy_user(void *to, const void *from, - __kernel_size_t n); -diff -urN linux-2.6.20.4-0rig/include/asm-avr32/unistd.h linux-2.6.20.4-atmel/include/asm-avr32/unistd.h ---- linux-2.6.20.4-0rig/include/asm-avr32/unistd.h 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/asm-avr32/unistd.h 2007-03-24 16:42:28.000000000 +0100 -@@ -120,7 +120,7 @@ - #define __NR_getitimer 105 - #define __NR_swapoff 106 - #define __NR_sysinfo 107 --#define __NR_ipc 108 -+/* 108 was __NR_ipc for a little while */ - #define __NR_sendfile 109 - #define __NR_setdomainname 110 - #define __NR_uname 111 -@@ -282,8 +282,21 @@ - #define __NR_vmsplice 264 - #define __NR_epoll_pwait 265 - -+#define __NR_msgget 266 -+#define __NR_msgsnd 267 -+#define __NR_msgrcv 268 -+#define __NR_msgctl 269 -+#define __NR_semget 270 -+#define __NR_semop 271 -+#define __NR_semctl 272 -+#define __NR_semtimedop 273 -+#define __NR_shmat 274 -+#define __NR_shmget 275 -+#define __NR_shmdt 276 -+#define __NR_shmctl 277 -+ - #ifdef __KERNEL__ --#define NR_syscalls 266 -+#define NR_syscalls 278 - - - #define __ARCH_WANT_IPC_PARSE_VERSION -diff -urN linux-2.6.20.4-0rig/include/linux/atmel_pdc.h linux-2.6.20.4-atmel/include/linux/atmel_pdc.h ---- linux-2.6.20.4-0rig/include/linux/atmel_pdc.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/linux/atmel_pdc.h 2007-03-24 16:39:16.000000000 +0100 -@@ -0,0 +1,36 @@ -+/* -+ * include/linux/atmel_pdc.h -+ * -+ * Copyright (C) 2005 Ivan Kokshaysky -+ * Copyright (C) SAN People -+ * -+ * Peripheral Data Controller (PDC) registers. -+ * Based on AT91RM9200 datasheet revision E. -+ * -+ * 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 ATMEL_PDC_H -+#define ATMEL_PDC_H -+ -+#define ATMEL_PDC_RPR 0x100 /* Receive Pointer Register */ -+#define ATMEL_PDC_RCR 0x104 /* Receive Counter Register */ -+#define ATMEL_PDC_TPR 0x108 /* Transmit Pointer Register */ -+#define ATMEL_PDC_TCR 0x10c /* Transmit Counter Register */ -+#define ATMEL_PDC_RNPR 0x110 /* Receive Next Pointer Register */ -+#define ATMEL_PDC_RNCR 0x114 /* Receive Next Counter Register */ -+#define ATMEL_PDC_TNPR 0x118 /* Transmit Next Pointer Register */ -+#define ATMEL_PDC_TNCR 0x11c /* Transmit Next Counter Register */ -+ -+#define ATMEL_PDC_PTCR 0x120 /* Transfer Control Register */ -+#define ATMEL_PDC_RXTEN (1 << 0) /* Receiver Transfer Enable */ -+#define ATMEL_PDC_RXTDIS (1 << 1) /* Receiver Transfer Disable */ -+#define ATMEL_PDC_TXTEN (1 << 8) /* Transmitter Transfer Enable */ -+#define ATMEL_PDC_TXTDIS (1 << 9) /* Transmitter Transfer Disable */ -+ -+#define ATMEL_PDC_PTSR 0x124 /* Transfer Status Register */ -+ -+#endif -diff -urN linux-2.6.20.4-0rig/include/linux/fb.h linux-2.6.20.4-atmel/include/linux/fb.h ---- linux-2.6.20.4-0rig/include/linux/fb.h 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/linux/fb.h 2007-03-24 16:42:29.000000000 +0100 -@@ -192,6 +192,7 @@ - /* vtotal = 144d/288n/576i => PAL */ - /* vtotal = 121d/242n/484i => NTSC */ - #define FB_SYNC_ON_GREEN 32 /* sync on green */ -+#define FB_SYNC_PCLK_RISING 64 /* pixel data sampled on rising pclk */ - - #define FB_VMODE_NONINTERLACED 0 /* non interlaced */ - #define FB_VMODE_INTERLACED 1 /* interlaced */ -@@ -827,7 +828,7 @@ - #define fb_writeq sbus_writeq - #define fb_memset sbus_memset_io - --#elif defined(__i386__) || defined(__alpha__) || defined(__x86_64__) || defined(__hppa__) || (defined(__sh__) && !defined(__SH5__)) || defined(__powerpc__) -+#elif defined(__i386__) || defined(__alpha__) || defined(__x86_64__) || defined(__hppa__) || (defined(__sh__) && !defined(__SH5__)) || defined(__powerpc__) || defined(__avr32__) - - #define fb_readb __raw_readb - #define fb_readw __raw_readw -diff -urN linux-2.6.20.4-0rig/include/linux/mtd/physmap.h linux-2.6.20.4-atmel/include/linux/mtd/physmap.h ---- linux-2.6.20.4-0rig/include/linux/mtd/physmap.h 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/linux/mtd/physmap.h 2007-03-24 16:42:28.000000000 +0100 -@@ -18,9 +18,10 @@ - #define __LINUX_MTD_PHYSMAP__ - - #include <linux/mtd/mtd.h> --#include <linux/mtd/map.h> - #include <linux/mtd/partitions.h> - -+struct map_info; -+ - struct physmap_flash_data { - unsigned int width; - void (*set_vpp)(struct map_info *, int); -diff -urN linux-2.6.20.4-0rig/include/linux/spi/ads7846.h linux-2.6.20.4-atmel/include/linux/spi/ads7846.h ---- linux-2.6.20.4-0rig/include/linux/spi/ads7846.h 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/linux/spi/ads7846.h 2007-03-24 16:39:16.000000000 +0100 -@@ -5,9 +5,17 @@ - * - * It's OK if the min/max values are zero. - */ -+enum ads7846_filter { -+ ADS7846_FILTER_OK, -+ ADS7846_FILTER_REPEAT, -+ ADS7846_FILTER_IGNORE, -+}; -+ - struct ads7846_platform_data { - u16 model; /* 7843, 7845, 7846. */ - u16 vref_delay_usecs; /* 0 for external vref; etc */ -+ int keep_vref_on:1; /* set to keep vref on for differential -+ * measurements as well */ - u16 x_plate_ohms; - u16 y_plate_ohms; - -@@ -21,5 +29,9 @@ - u16 debounce_rep; /* additional consecutive good readings - * required after the first two */ - int (*get_pendown_state)(void); -+ int (*filter_init) (struct ads7846_platform_data *pdata, -+ void **filter_data); -+ int (*filter) (void *filter_data, int data_idx, int *val); -+ void (*filter_cleanup)(void *filter_data); - }; - -diff -urN linux-2.6.20.4-0rig/include/video/atmel_lcdc.h linux-2.6.20.4-atmel/include/video/atmel_lcdc.h ---- linux-2.6.20.4-0rig/include/video/atmel_lcdc.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/include/video/atmel_lcdc.h 2007-03-24 16:39:16.000000000 +0100 -@@ -0,0 +1,193 @@ -+/* -+ * include/video/atmel_lcdc.h -+ * -+ * Header file for AT91/AT32 LCD Controller -+ * -+ * Data structure and register user interface -+ * -+ * Copyright (C) 2007 Atmel Corporation -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+#ifndef __ATMEL_LCDC_H__ -+#define __ATMEL_LCDC_H__ -+ -+ /* LCD Controller info data structure */ -+struct atmel_lcdfb_info { -+ spinlock_t lock; -+ struct fb_info *info; -+ void __iomem *mmio; -+ unsigned long irq_base; -+ dma_addr_t map_dma; -+ void *map_cpu; -+ size_t map_size; -+ -+ unsigned int guard_time; -+ struct platform_device *pdev; -+ struct clk *bus_clk; -+ struct clk *lcdc_clk; -+ unsigned int default_bpp; -+ unsigned int default_lcdcon2; -+ unsigned int default_dmacon; -+ int default_flags; -+ u8 power_control_pin; -+ struct fb_monspecs *default_monspecs; -+}; -+ -+#define ATMEL_LCDC_DMABADDR1 0x00 /* DMA Base Address Register 1 */ -+#define ATMEL_LCDC_DMABADDR2 0x04 /* DMA Base Address Register 2 */ -+#define ATMEL_LCDC_DMAFRMPT1 0x08 /* DMA Frame Pointer Register 1 */ -+#define ATMEL_LCDC_DMAFRMPT2 0x0c /* DMA Frame Pointer Register 2 */ -+#define ATMEL_LCDC_DMAFRMADD1 0x10 /* DMA Frame Address Register 1 */ -+#define ATMEL_LCDC_DMAFRMADD2 0x14 /* DMA Frame Address Register 2 */ -+ -+#define ATMEL_LCDC_DMAFRMCFG 0x18 /* DMA Frame Configuration Register */ -+#define ATMEL_LCDC_FRSIZE (0x7fffff << 0) /* Frame Size */ -+#define ATMEL_LCDC_BLENGTH_OFFSET 24 /* Burst Length */ -+#define ATMEL_LCDC_BLENGTH (0x7f << ATMEL_LCDC_BLENGTH_OFFSET) -+ -+#define ATMEL_LCDC_DMACON 0x1c /* DMA Control Register */ -+#define ATMEL_LCDC_DMAEN (0x1 << 0) /* DMA Enable */ -+#define ATMEL_LCDC_DMARST (0x1 << 1) /* DMA Reset */ -+#define ATMEL_LCDC_DMABUSY (0x1 << 2) /* DMA Busy */ -+ -+#define ATMEL_LCDC_LCDCON1 0x0800 /* LCD Control Register 1 */ -+#define ATMEL_LCDC_BYPASS (1 << 0) /* Bypass lcd_dotck divider */ -+#define ATMEL_LCDC_CLKVAL_OFFSET 12 /* Clock Divider */ -+#define ATMEL_LCDC_CLKVAL (0x1ff << ATMEL_LCDC_CLKVAL_OFFSET) -+#define ATMEL_LCDC_LINCNT (0x7ff << 21) /* Line Counter */ -+ -+#define ATMEL_LCDC_LCDCON2 0x0804 /* LCD Control Register 2 */ -+#define ATMEL_LCDC_DISTYPE (3 << 0) /* Display Type */ -+#define ATMEL_LCDC_DISTYPE_STNMONO (0 << 0) -+#define ATMEL_LCDC_DISTYPE_STNCOLOR (1 << 0) -+#define ATMEL_LCDC_DISTYPE_TFT (2 << 0) -+#define ATMEL_LCDC_SCANMOD (1 << 2) /* Scan Mode */ -+#define ATMEL_LCDC_SCANMOD_SINGLE (0 << 2) -+#define ATMEL_LCDC_SCANMOD_DUAL (1 << 2) -+#define ATMEL_LCDC_IFWIDTH (3 << 3) /*Interface Width */ -+#define ATMEL_LCDC_IFWIDTH_4 (0 << 3) -+#define ATMEL_LCDC_IFWIDTH_8 (1 << 3) -+#define ATMEL_LCDC_IFWIDTH_16 (2 << 3) -+#define ATMEL_LCDC_PIXELSIZE (7 << 5) /* Bits per pixel */ -+#define ATMEL_LCDC_PIXELSIZE_1 (0 << 5) -+#define ATMEL_LCDC_PIXELSIZE_2 (1 << 5) -+#define ATMEL_LCDC_PIXELSIZE_4 (2 << 5) -+#define ATMEL_LCDC_PIXELSIZE_8 (3 << 5) -+#define ATMEL_LCDC_PIXELSIZE_16 (4 << 5) -+#define ATMEL_LCDC_PIXELSIZE_24 (5 << 5) -+#define ATMEL_LCDC_PIXELSIZE_32 (6 << 5) -+#define ATMEL_LCDC_INVVD (1 << 8) /* LCD Data polarity */ -+#define ATMEL_LCDC_INVVD_NORMAL (0 << 8) -+#define ATMEL_LCDC_INVVD_INVERTED (1 << 8) -+#define ATMEL_LCDC_INVFRAME (1 << 9 ) /* LCD VSync polarity */ -+#define ATMEL_LCDC_INVFRAME_NORMAL (0 << 9) -+#define ATMEL_LCDC_INVFRAME_INVERTED (1 << 9) -+#define ATMEL_LCDC_INVLINE (1 << 10) /* LCD HSync polarity */ -+#define ATMEL_LCDC_INVLINE_NORMAL (0 << 10) -+#define ATMEL_LCDC_INVLINE_INVERTED (1 << 10) -+#define ATMEL_LCDC_INVCLK (1 << 11) /* LCD dotclk polarity */ -+#define ATMEL_LCDC_INVCLK_NORMAL (0 << 11) -+#define ATMEL_LCDC_INVCLK_INVERTED (1 << 11) -+#define ATMEL_LCDC_INVDVAL (1 << 12) /* LCD dval polarity */ -+#define ATMEL_LCDC_INVDVAL_NORMAL (0 << 12) -+#define ATMEL_LCDC_INVDVAL_INVERTED (1 << 12) -+#define ATMEL_LCDC_CLKMOD (1 << 15) /* LCD dotclk mode */ -+#define ATMEL_LCDC_CLKMOD_ACTIVEDISPLAY (0 << 15) -+#define ATMEL_LCDC_CLKMOD_ALWAYSACTIVE (1 << 15) -+#define ATMEL_LCDC_MEMOR (1 << 31) /* Memory Ordering Format */ -+#define ATMEL_LCDC_MEMOR_BIG (0 << 31) -+#define ATMEL_LCDC_MEMOR_LITTLE (1 << 31) -+ -+#define ATMEL_LCDC_TIM1 0x0808 /* LCD Timing Register 1 */ -+#define ATMEL_LCDC_VFP (0xff << 0) /* Vertical Front Porch */ -+#define ATMEL_LCDC_VBP_OFFSET 8 /* Vertical Back Porch */ -+#define ATMEL_LCDC_VBP (0xff << ATMEL_LCDC_VBP_OFFSET) -+#define ATMEL_LCDC_VPW_OFFSET 16 /* Vertical Synchronization Pulse Width */ -+#define ATMEL_LCDC_VPW (0x3f << ATMEL_LCDC_VPW_OFFSET) -+#define ATMEL_LCDC_VHDLY_OFFSET 24 /* Vertical to Horizontal Delay */ -+#define ATMEL_LCDC_VHDLY (0xf << ATMEL_LCDC_VHDLY_OFFSET) -+ -+#define ATMEL_LCDC_TIM2 0x080c /* LCD Timing Register 2 */ -+#define ATMEL_LCDC_HBP (0xff << 0) /* Horizontal Back Porch */ -+#define ATMEL_LCDC_HPW_OFFSET 8 /* Horizontal Synchronization Pulse Width */ -+#define ATMEL_LCDC_HPW (0x3f << ATMEL_LCDC_HPW_OFFSET) -+#define ATMEL_LCDC_HFP_OFFSET 21 /* Horizontal Front Porch */ -+#define ATMEL_LCDC_HFP (0x7ff << ATMEL_LCDC_HFP_OFFSET) -+ -+#define ATMEL_LCDC_LCDFRMCFG 0x0810 /* LCD Frame Configuration Register */ -+#define ATMEL_LCDC_LINEVAL (0x7ff << 0) /* Vertical Size of LCD Module */ -+#define ATMEL_LCDC_HOZVAL_OFFSET 21 /* Horizontal Size of LCD Module */ -+#define ATMEL_LCDC_HOZVAL (0x7ff << ATMEL_LCDC_HOZVAL_OFFSET) -+ -+#define ATMEL_LCDC_FIFO 0x0814 /* LCD FIFO Register */ -+#define ATMEL_LCDC_FIFOTH (0xffff) /* FIFO Threshold */ -+ -+#define ATMEL_LCDC_MVAL 0x0818 /* LCD Mode Toggle Rate Value Register */ -+ -+#define ATMEL_LCDC_DP1_2 0x081c /* Dithering Pattern DP1_2 Register */ -+#define ATMEL_LCDC_DP4_7 0x0820 /* Dithering Pattern DP4_7 Register */ -+#define ATMEL_LCDC_DP3_5 0x0824 /* Dithering Pattern DP3_5 Register */ -+#define ATMEL_LCDC_DP2_3 0x0828 /* Dithering Pattern DP2_3 Register */ -+#define ATMEL_LCDC_DP5_7 0x082c /* Dithering Pattern DP5_7 Register */ -+#define ATMEL_LCDC_DP3_4 0x0830 /* Dithering Pattern DP3_4 Register */ -+#define ATMEL_LCDC_DP4_5 0x0834 /* Dithering Pattern DP4_5 Register */ -+#define ATMEL_LCDC_DP6_7 0x0838 /* Dithering Pattern DP6_7 Register */ -+#define ATMEL_LCDC_DP1_2_VAL (0xff) -+#define ATMEL_LCDC_DP4_7_VAL (0xfffffff) -+#define ATMEL_LCDC_DP3_5_VAL (0xfffff) -+#define ATMEL_LCDC_DP2_3_VAL (0xfff) -+#define ATMEL_LCDC_DP5_7_VAL (0xfffffff) -+#define ATMEL_LCDC_DP3_4_VAL (0xffff) -+#define ATMEL_LCDC_DP4_5_VAL (0xfffff) -+#define ATMEL_LCDC_DP6_7_VAL (0xfffffff) -+ -+#define ATMEL_LCDC_PWRCON 0x083c /* Power Control Register */ -+#define ATMEL_LCDC_PWR (1 << 0) /* LCD Module Power Control */ -+#define ATMEL_LCDC_GUARDT_OFFSET 1 /* Delay in Frame Period */ -+#define ATMEL_LCDC_GUARDT (0x7f << ATMEL_LCDC_GUARDT_OFFSET) -+#define ATMEL_LCDC_BUSY (1 << 31) /* LCD Busy */ -+ -+#define ATMEL_LCDC_CONTRAST_CTR 0x0840 /* Contrast Control Register */ -+#define ATMEL_LCDC_PS (3 << 0) /* Contrast Counter Prescaler */ -+#define ATMEL_LCDC_PS_DIV1 (0 << 0) -+#define ATMEL_LCDC_PS_DIV2 (1 << 0) -+#define ATMEL_LCDC_PS_DIV4 (2 << 0) -+#define ATMEL_LCDC_PS_DIV8 (3 << 0) -+#define ATMEL_LCDC_POL (1 << 2) /* Polarity of output Pulse */ -+#define ATMEL_LCDC_POL_NEGATIVE (0 << 2) -+#define ATMEL_LCDC_POL_POSITIVE (1 << 2) -+#define ATMEL_LCDC_ENA (1 << 3) /* PWM generator Control */ -+#define ATMEL_LCDC_ENA_PWMDISABLE (0 << 3) -+#define ATMEL_LCDC_ENA_PWMENABLE (1 << 3) -+ -+#define ATMEL_LCDC_CONTRAST_VAL 0x0844 /* Contrast Value Register */ -+#define ATMEL_LCDC_CVAL (0xff) /* PWM compare value */ -+ -+#define ATMEL_LCDC_IER 0x0848 /* Interrupt Enable Register */ -+#define ATMEL_LCDC_IDR 0x084c /* Interrupt Disable Register */ -+#define ATMEL_LCDC_IMR 0x0850 /* Interrupt Mask Register */ -+#define ATMEL_LCDC_ISR 0x0854 /* Interrupt Status Register */ -+#define ATMEL_LCDC_ICR 0x0858 /* Interrupt Clear Register */ -+#define ATMEL_LCDC_LNI (1 << 0) /* Line Interrupt */ -+#define ATMEL_LCDC_LSTLNI (1 << 1) /* Last Line Interrupt */ -+#define ATMEL_LCDC_EOFI (1 << 2) /* DMA End Of Frame Interrupt */ -+#define ATMEL_LCDC_UFLWI (1 << 4) /* FIFO Underflow Interrupt */ -+#define ATMEL_LCDC_OWRI (1 << 5) /* FIFO Overwrite Interrupt */ -+#define ATMEL_LCDC_MERI (1 << 6) /* DMA Memory Error Interrupt */ -+ -+#define ATMEL_LCDC_LUT_(n) (0x0c00 + ((n)*4)) /* Palette Entry 0..255 */ -+ -+#endif /* __ATMEL_LCDC_H__ */ -diff -urN linux-2.6.20.4-0rig/MAINTAINERS linux-2.6.20.4-atmel/MAINTAINERS ---- linux-2.6.20.4-0rig/MAINTAINERS 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/MAINTAINERS 2007-03-24 16:43:49.000000000 +0100 -@@ -602,6 +602,11 @@ - M: hskinnemoen@atmel.com - S: Supported - -+ATMEL SPI DRIVER -+P: Haavard Skinnemoen -+M: hskinnemoen@atmel.com -+S: Supported -+ - ATMEL WIRELESS DRIVER - P: Simon Kelley - M: simon@thekelleys.org.uk -diff -urN linux-2.6.20.4-0rig/scripts/checkstack.pl linux-2.6.20.4-atmel/scripts/checkstack.pl ---- linux-2.6.20.4-0rig/scripts/checkstack.pl 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/scripts/checkstack.pl 2007-03-24 16:42:29.000000000 +0100 -@@ -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; -diff -urN linux-2.6.20.4-0rig/sound/avr32/ac97c.c linux-2.6.20.4-atmel/sound/avr32/ac97c.c ---- linux-2.6.20.4-0rig/sound/avr32/ac97c.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/sound/avr32/ac97c.c 2007-03-24 16:42:29.000000000 +0100 -@@ -0,0 +1,1250 @@ -+/* -+ * Driver for the Atmel AC97 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/delay.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/mutex.h> -+ -+#include <sound/driver.h> -+#include <sound/core.h> -+#include <sound/initval.h> -+#include <sound/pcm.h> -+#include <sound/pcm_params.h> -+#include <sound/ac97_codec.h> -+#ifndef SND_ATMEL_AC97_USE_ALSA_MALLOC_CALLS -+#include <sound/memalloc.h> -+#endif -+ -+#include <asm/io.h> -+ -+#include "ac97c.h" -+ -+static DEFINE_MUTEX(opened_mutex); -+ -+/* module parameters */ -+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; -+ -+module_param_array(index, int, NULL, 0444); -+MODULE_PARM_DESC(index, "Index value for AC97 controller"); -+module_param_array(id, charp, NULL, 0444); -+MODULE_PARM_DESC(id, "ID string for AC97 controller"); -+module_param_array(enable, bool, NULL, 0444); -+MODULE_PARM_DESC(enable, "Enable AC97 controller"); -+ -+#ifndef CONFIG_SND_ATMEL_AC97C_USE_PDC -+#include <asm/dma-controller.h> -+ -+struct atmel_ac97_dma_info { -+ struct dma_request_cyclic req_tx; -+ struct dma_request_cyclic req_rx; -+ unsigned short rx_periph_id; -+ unsigned short tx_periph_id; -+}; -+#endif -+ -+ -+typedef struct atmel_ac97 { -+ spinlock_t lock; -+ void __iomem *regs; -+ int period; -+ -+ snd_pcm_substream_t *playback_substream; -+ snd_pcm_substream_t *capture_substream; -+ snd_card_t *card; -+ snd_pcm_t *pcm; -+ ac97_t *ac97; -+ ac97_bus_t *ac97_bus; -+ int irq; -+ int opened; -+ u64 cur_format; -+ unsigned int cur_rate; -+ struct clk *mck; -+ struct platform_device *pdev; -+ struct atmel_ac97_dma_info dma; -+} atmel_ac97_t; -+#define get_chip(card) ((atmel_ac97_t *)(card)->private_data) -+ -+#define ac97c_writel(chip, reg, val) \ -+ __raw_writel((val), (chip)->regs + AC97C_##reg) -+#define ac97c_readl(chip, reg) \ -+ __raw_readl((chip)->regs + AC97C_##reg) -+ -+/* PCM part */ -+ -+static snd_pcm_hardware_t snd_atmel_ac97_playback_hw = { -+ .info = (SNDRV_PCM_INFO_INTERLEAVED -+ |SNDRV_PCM_INFO_MMAP -+ |SNDRV_PCM_INFO_MMAP_VALID -+ |SNDRV_PCM_INFO_BLOCK_TRANSFER -+ |SNDRV_PCM_INFO_JOINT_DUPLEX), -+ .formats = (SNDRV_PCM_FMTBIT_S16_BE|SNDRV_PCM_FMTBIT_S16_LE), -+ .rates = (SNDRV_PCM_RATE_CONTINUOUS), -+ .rate_min = 4000, -+ .rate_max = 48000, -+ .channels_min = 1, -+ .channels_max = 6, -+ .buffer_bytes_max = 64*1024, -+ .period_bytes_min = 512, -+#ifdef CONFIG_SND_ATMEL_AC97C_USE_PDC -+ .period_bytes_max = 64*1024, -+#else -+ .period_bytes_max = 4095, -+#endif -+ .periods_min = 8, -+ .periods_max = 1024, -+}; -+ -+static snd_pcm_hardware_t snd_atmel_ac97_capture_hw = { -+ .info = (SNDRV_PCM_INFO_INTERLEAVED -+ |SNDRV_PCM_INFO_MMAP -+ |SNDRV_PCM_INFO_MMAP_VALID -+ |SNDRV_PCM_INFO_BLOCK_TRANSFER -+ |SNDRV_PCM_INFO_JOINT_DUPLEX), -+ .formats = (SNDRV_PCM_FMTBIT_S16_BE|SNDRV_PCM_FMTBIT_S16_LE), -+ .rates = (SNDRV_PCM_RATE_CONTINUOUS), -+ .rate_min = 4000, -+ .rate_max = 48000, -+ .channels_min = 1, -+ .channels_max = 2, -+ .buffer_bytes_max = 64*1024, -+ .period_bytes_min = 512, -+#ifdef CONFIG_SND_ATMEL_AC97C_USE_PDC -+ .period_bytes_max = 64*1024, -+#else -+ .period_bytes_max = 4095, -+#endif -+ .periods_min = 8, -+ .periods_max = 1024, -+}; -+ -+/* Joint full duplex variables */ -+unsigned int hw_rates[1]; -+unsigned int hw_formats[1]; -+struct snd_pcm_hw_constraint_list hw_constraint_rates; -+struct snd_pcm_hw_constraint_list hw_constraint_formats; -+ -+/* -+ * PCM functions -+ */ -+static int -+snd_atmel_ac97_playback_open(snd_pcm_substream_t *substream) -+{ -+ atmel_ac97_t *chip = snd_pcm_substream_chip(substream); -+ snd_pcm_runtime_t *runtime = substream->runtime; -+ -+ mutex_lock(&opened_mutex); -+ chip->opened++; -+ runtime->hw = snd_atmel_ac97_playback_hw; -+ if (chip->cur_rate) { -+ runtime->hw.rate_min = chip->cur_rate; -+ runtime->hw.rate_max = chip->cur_rate; -+ } -+ if (chip->cur_format) -+ runtime->hw.formats = (1ULL<<chip->cur_format); -+ mutex_unlock(&opened_mutex); -+ chip->playback_substream = substream; -+ chip->period = 0; -+ return 0; -+} -+ -+static int -+snd_atmel_ac97_capture_open(snd_pcm_substream_t *substream) -+{ -+ atmel_ac97_t *chip = snd_pcm_substream_chip(substream); -+ snd_pcm_runtime_t *runtime = substream->runtime; -+ -+ mutex_lock(&opened_mutex); -+ chip->opened++; -+ runtime->hw = snd_atmel_ac97_capture_hw; -+ if (chip->cur_rate) { -+ runtime->hw.rate_min = chip->cur_rate; -+ runtime->hw.rate_max = chip->cur_rate; -+ } -+ if (chip->cur_format) -+ runtime->hw.formats = (1ULL<<chip->cur_format); -+ mutex_unlock(&opened_mutex); -+ chip->capture_substream = substream; -+ chip->period = 0; -+ return 0; -+} -+ -+static int snd_atmel_ac97_playback_close(snd_pcm_substream_t *substream) -+{ -+ atmel_ac97_t *chip = snd_pcm_substream_chip(substream); -+ mutex_lock(&opened_mutex); -+ chip->opened--; -+ if (!chip->opened) { -+ chip->cur_rate = 0; -+ chip->cur_format = 0; -+ } -+ mutex_unlock(&opened_mutex); -+ return 0; -+} -+ -+static int snd_atmel_ac97_capture_close(snd_pcm_substream_t *substream) -+{ -+ atmel_ac97_t *chip = snd_pcm_substream_chip(substream); -+ mutex_lock(&opened_mutex); -+ chip->opened--; -+ if (!chip->opened) { -+ chip->cur_rate = 0; -+ chip->cur_format = 0; -+ } -+ mutex_unlock(&opened_mutex); -+ return 0; -+} -+ -+static int snd_atmel_ac97_playback_hw_params(snd_pcm_substream_t *substream, -+ snd_pcm_hw_params_t *hw_params) -+{ -+ atmel_ac97_t *chip = snd_pcm_substream_chip(substream); -+#ifdef SND_ATMEL_AC97_USE_ALSA_MALLOC_CALLS -+ int err; -+ err = snd_pcm_lib_malloc_pages(substream, -+ params_buffer_bytes(hw_params)); -+ -+ if (err < 0) -+ return err; -+ -+ /* Set restrictions to params */ -+ mutex_lock(&opened_mutex); -+ chip->cur_rate = params_rate(hw_params); -+ chip->cur_format = params_format(hw_params); -+ mutex_unlock(&opened_mutex); -+ -+ return err; -+#else -+ int pg; -+ size_t size = params_buffer_bytes(hw_params); -+ struct snd_pcm_runtime *runtime; -+ struct snd_dma_buffer *dmab = NULL; -+ -+ substream->dma_buffer.dev.type = SNDRV_DMA_TYPE_DEV; -+ snd_assert(substream != NULL, return -EINVAL); -+ runtime = substream->runtime; -+ snd_assert(runtime != NULL, return -EINVAL); -+ -+ /* Set restrictions to params */ -+ mutex_lock(&opened_mutex); -+ chip->cur_rate = params_rate(hw_params); -+ chip->cur_format = params_format(hw_params); -+ mutex_unlock(&opened_mutex); -+ -+ /* check if buffer is already allocated */ -+ if (runtime->dma_buffer_p) { -+ size_t size_previouse; -+ int pg_previouse; -+ -+ /* new buffer is smaler than previouse allocated buffer */ -+ if (runtime->dma_buffer_p->bytes >= size) { -+ runtime->dma_bytes = size; -+ return 0; /* don't change buffer size */ -+ } -+ -+ size_previouse = runtime->dma_buffer_p->bytes; -+ pg_previouse = get_order(size_previouse); -+ -+ dma_free_coherent(runtime->dma_buffer_p->dev.dev, -+ PAGE_SIZE << pg_previouse, -+ runtime->dma_buffer_p->area, -+ runtime->dma_buffer_p->addr); -+ -+ kfree(runtime->dma_buffer_p); -+ } -+ -+ dmab = kzalloc(sizeof(*dmab), GFP_KERNEL); -+ if (!dmab) -+ return -ENOMEM; -+ -+ dmab->dev = substream->dma_buffer.dev; -+ dmab->bytes = 0; -+ -+ pg = get_order(size); -+ -+ dmab->area = dma_alloc_coherent( -+ substream->dma_buffer.dev.dev, -+ PAGE_SIZE << pg, -+ (dma_addr_t *)&dmab->addr, -+ GFP_KERNEL); -+ -+ if (!dmab->area) { -+ kfree(dmab); -+ return -ENOMEM; -+ } -+ -+ dmab->bytes = size; -+ -+ snd_pcm_set_runtime_buffer(substream, dmab); -+ runtime->dma_bytes = size; -+ return 1; -+#endif -+} -+ -+static int snd_atmel_ac97_capture_hw_params(snd_pcm_substream_t *substream, -+ snd_pcm_hw_params_t *hw_params) -+{ -+ atmel_ac97_t *chip = snd_pcm_substream_chip(substream); -+#ifdef SND_ATMEL_AC97_USE_ALSA_MALLOC_CALLS -+ int err; -+ err = snd_pcm_lib_malloc_pages(substream, -+ params_buffer_bytes(hw_params)); -+ -+ if (err < 0) -+ return err; -+ -+ /* Set restrictions to params */ -+ mutex_lock(&opened_mutex); -+ chip->cur_rate = params_rate(hw_params); -+ chip->cur_format = params_format(hw_params); -+ mutex_unlock(&opened_mutex); -+ -+ return err; -+#else -+ int pg; -+ size_t size = params_buffer_bytes(hw_params); -+ struct snd_pcm_runtime *runtime; -+ struct snd_dma_buffer *dmab = NULL; -+ -+ substream->dma_buffer.dev.type = SNDRV_DMA_TYPE_DEV; -+ snd_assert(substream != NULL, return -EINVAL); -+ runtime = substream->runtime; -+ snd_assert(runtime != NULL, return -EINVAL); -+ -+ /* Set restrictions to params */ -+ mutex_lock(&opened_mutex); -+ chip->cur_rate = params_rate(hw_params); -+ chip->cur_format = params_format(hw_params); -+ mutex_unlock(&opened_mutex); -+ -+ /* check if buffer is already allocated */ -+ if (runtime->dma_buffer_p) { -+ size_t size_previouse; -+ int pg_previouse; -+ -+ /* new buffer is smaler than previouse allocated buffer */ -+ if (runtime->dma_buffer_p->bytes >= size) { -+ runtime->dma_bytes = size; -+ return 0; /* don't change buffer size */ -+ } -+ -+ size_previouse = runtime->dma_buffer_p->bytes; -+ pg_previouse = get_order(size_previouse); -+ -+ dma_free_coherent(runtime->dma_buffer_p->dev.dev, -+ PAGE_SIZE << pg_previouse, -+ runtime->dma_buffer_p->area, -+ runtime->dma_buffer_p->addr); -+ -+ kfree(runtime->dma_buffer_p); -+ } -+ -+ dmab = kzalloc(sizeof(*dmab), GFP_KERNEL); -+ if (!dmab) -+ return -ENOMEM; -+ -+ dmab->dev = substream->dma_buffer.dev; -+ dmab->bytes = 0; -+ -+ pg = get_order(size); -+ -+ dmab->area = dma_alloc_coherent( -+ substream->dma_buffer.dev.dev, -+ PAGE_SIZE << pg, -+ (dma_addr_t *)&dmab->addr, -+ GFP_KERNEL); -+ -+ if (!dmab->area) { -+ kfree(dmab); -+ return -ENOMEM; -+ } -+ -+ dmab->bytes = size; -+ -+ snd_pcm_set_runtime_buffer(substream, dmab); -+ runtime->dma_bytes = size; -+ return 1; -+#endif -+} -+ -+static int snd_atmel_ac97_playback_hw_free(snd_pcm_substream_t *substream) -+{ -+#ifdef SND_ATMEL_AC97_USE_ALSA_MALLOC_CALLS -+ return snd_pcm_lib_free_pages(substream); -+#else -+ int pg; -+ struct snd_pcm_runtime *runtime; -+ struct snd_dma_buffer *dmab = NULL; -+ -+ snd_assert(substream != NULL, return -EINVAL); -+ runtime = substream->runtime; -+ snd_assert(runtime != NULL, return -EINVAL); -+ dmab = runtime->dma_buffer_p; -+ -+ if (!dmab) -+ return 0; -+ -+ if (!dmab->area) -+ return 0; -+ -+ pg = get_order(dmab->bytes); -+ dma_free_coherent(dmab->dev.dev, PAGE_SIZE << pg, dmab->area, dmab->addr); -+ kfree(runtime->dma_buffer_p); -+ snd_pcm_set_runtime_buffer(substream, NULL); -+ return 0; -+#endif -+} -+ -+static int snd_atmel_ac97_capture_hw_free(snd_pcm_substream_t *substream) -+{ -+ -+#ifdef SND_ATMEL_AC97_USE_ALSA_MALLOC_CALLS -+ return snd_pcm_lib_free_pages(substream); -+#else -+ int pg; -+ struct snd_pcm_runtime *runtime; -+ struct snd_dma_buffer *dmab = NULL; -+ -+ snd_assert(substream != NULL, return -EINVAL); -+ runtime = substream->runtime; -+ snd_assert(runtime != NULL, return -EINVAL); -+ dmab = runtime->dma_buffer_p; -+ -+ if (!dmab) -+ return 0; -+ -+ if (!dmab->area) -+ return 0; -+ -+ pg = get_order(dmab->bytes); -+ dma_free_coherent(dmab->dev.dev, PAGE_SIZE << pg, dmab->area, dmab->addr); -+ kfree(runtime->dma_buffer_p); -+ snd_pcm_set_runtime_buffer(substream, NULL); -+ return 0; -+#endif -+} -+ -+static int snd_atmel_ac97_playback_prepare(snd_pcm_substream_t *substream) -+{ -+ atmel_ac97_t *chip = snd_pcm_substream_chip(substream); -+ struct platform_device *pdev = chip->pdev; -+ snd_pcm_runtime_t *runtime = substream->runtime; -+ int block_size = frames_to_bytes(runtime, runtime->period_size); -+ unsigned long word = 0; -+ unsigned long buffer_size = 0; -+ -+ dma_sync_single_for_device(&pdev->dev, runtime->dma_addr, -+ block_size * 2, DMA_TO_DEVICE); -+ -+ /* Assign slots to channels */ -+ switch (substream->runtime->channels) { -+ case 1: -+ word |= AC97C_CH_ASSIGN(PCM_LEFT, A); -+ break; -+ case 2: -+ /* Assign Left and Right slot to Channel A */ -+ word |= AC97C_CH_ASSIGN(PCM_LEFT, A) -+ | AC97C_CH_ASSIGN(PCM_RIGHT, A); -+ break; -+ default: -+ /* TODO: support more than two channels */ -+ return -EINVAL; -+ break; -+ } -+ ac97c_writel(chip, OCA, word); -+ -+ /* Configure sample format and size */ -+ word = AC97C_CMR_PDCEN | AC97C_CMR_SIZE_16; -+ -+ switch (runtime->format){ -+ case SNDRV_PCM_FORMAT_S16_LE: -+ word |= AC97C_CMR_CEM_LITTLE; -+ break; -+ case SNDRV_PCM_FORMAT_S16_BE: -+ default: -+ word &= ~AC97C_CMR_CEM_LITTLE; -+ break; -+ } -+ -+ ac97c_writel(chip, CAMR, word); -+ -+ /* Set variable rate if needed */ -+ if (runtime->rate != 48000) { -+ word = ac97c_readl(chip, MR); -+ word |= AC97C_MR_VRA; -+ ac97c_writel(chip, MR, word); -+ } else { -+ /* Clear Variable Rate Bit */ -+ word = ac97c_readl(chip, MR); -+ word &= ~AC97C_MR_VRA; -+ ac97c_writel(chip, MR, word); -+ } -+ -+ /* Set rate */ -+ snd_ac97_set_rate(chip->ac97, AC97_PCM_FRONT_DAC_RATE, runtime->rate); -+ -+#ifdef CONFIG_SND_ATMEL_AC97C_USE_PDC -+ /* Initialize and start the PDC */ -+ ac97c_writel(chip, CATPR, runtime->dma_addr); -+ ac97c_writel(chip, CATCR, block_size / 4); -+ ac97c_writel(chip, CATNPR, runtime->dma_addr + block_size); -+ ac97c_writel(chip, CATNCR, block_size / 4); -+ ac97c_writel(chip, PTCR, PDC_PTCR_TXTEN); -+ /* Enable Channel A interrupts */ -+ ac97c_writel(chip, IER, AC97C_SR_CAEVT); -+#else -+ buffer_size = frames_to_bytes(runtime, runtime->period_size) * -+ runtime->periods; -+ -+ chip->dma.req_tx.buffer_size = buffer_size; -+ chip->dma.req_tx.periods = runtime->periods; -+ -+ BUG_ON(chip->dma.req_tx.buffer_size != -+ (chip->dma.req_tx.periods * -+ frames_to_bytes(runtime, runtime->period_size))); -+ -+ chip->dma.req_tx.buffer_start = runtime->dma_addr; -+ chip->dma.req_tx.data_reg = (dma_addr_t)(chip->regs + AC97C_CATHR + 2); -+ chip->dma.req_tx.periph_id = chip->dma.tx_periph_id; -+ chip->dma.req_tx.direction = DMA_DIR_MEM_TO_PERIPH; -+ chip->dma.req_tx.width = DMA_WIDTH_16BIT; -+ chip->dma.req_tx.dev_id = chip; -+#endif -+ -+ return 0; -+} -+ -+static int snd_atmel_ac97_capture_prepare(snd_pcm_substream_t *substream) -+{ -+ atmel_ac97_t *chip = snd_pcm_substream_chip(substream); -+ struct platform_device *pdev = chip->pdev; -+ snd_pcm_runtime_t *runtime = substream->runtime; -+ int block_size = frames_to_bytes(runtime, runtime->period_size); -+ unsigned long word = 0; -+ unsigned long buffer_size = 0; -+ -+ dma_sync_single_for_device(&pdev->dev, runtime->dma_addr, -+ block_size * 2, DMA_FROM_DEVICE); -+ -+ /* Assign slots to channels */ -+ switch (substream->runtime->channels) { -+ case 1: -+ word |= AC97C_CH_ASSIGN(PCM_LEFT, A); -+ break; -+ case 2: -+ /* Assign Left and Right slot to Channel A */ -+ word |= AC97C_CH_ASSIGN(PCM_LEFT, A) -+ | AC97C_CH_ASSIGN(PCM_RIGHT, A); -+ break; -+ default: -+ /* TODO: support more than two channels */ -+ return -EINVAL; -+ break; -+ } -+ ac97c_writel(chip, ICA, word); -+ -+ /* Configure sample format and size */ -+ word = AC97C_CMR_PDCEN | AC97C_CMR_SIZE_16; -+ -+ switch (runtime->format) { -+ case SNDRV_PCM_FORMAT_S16_LE: -+ word |= AC97C_CMR_CEM_LITTLE; -+ break; -+ case SNDRV_PCM_FORMAT_S16_BE: -+ default: -+ word &= ~(AC97C_CMR_CEM_LITTLE); -+ break; -+ } -+ -+ ac97c_writel(chip, CAMR, word); -+ -+ /* Set variable rate if needed */ -+ if (runtime->rate != 48000) { -+ word = ac97c_readl(chip, MR); -+ word |= AC97C_MR_VRA; -+ ac97c_writel(chip, MR, word); -+ } else { -+ /* Clear Variable Rate Bit */ -+ word = ac97c_readl(chip, MR); -+ word &= ~(AC97C_MR_VRA); -+ ac97c_writel(chip, MR, word); -+ } -+ -+ /* Set rate */ -+ snd_ac97_set_rate(chip->ac97, AC97_PCM_LR_ADC_RATE, runtime->rate); -+ -+#ifdef CONFIG_SND_ATMEL_AC97C_USE_PDC -+ /* Initialize and start the PDC */ -+ ac97c_writel(chip, CARPR, runtime->dma_addr); -+ ac97c_writel(chip, CARCR, block_size / 4); -+ ac97c_writel(chip, CARNPR, runtime->dma_addr + block_size); -+ ac97c_writel(chip, CARNCR, block_size / 4); -+ ac97c_writel(chip, PTCR, PDC_PTCR_RXEN); -+ /* Enable Channel A interrupts */ -+ ac97c_writel(chip, IER, AC97C_SR_CAEVT); -+#else -+ buffer_size = frames_to_bytes(runtime, runtime->period_size) * -+ runtime->periods; -+ -+ chip->dma.req_rx.buffer_size = buffer_size; -+ chip->dma.req_rx.periods = runtime->periods; -+ -+ BUG_ON(chip->dma.req_rx.buffer_size != -+ (chip->dma.req_rx.periods * -+ frames_to_bytes(runtime, runtime->period_size))); -+ -+ chip->dma.req_rx.buffer_start = runtime->dma_addr; -+ chip->dma.req_rx.data_reg = (dma_addr_t)(chip->regs + AC97C_CARHR + 2); -+ chip->dma.req_rx.periph_id = chip->dma.rx_periph_id; -+ chip->dma.req_rx.direction = DMA_DIR_PERIPH_TO_MEM; -+ chip->dma.req_rx.width = DMA_WIDTH_16BIT; -+ chip->dma.req_rx.dev_id = chip; -+#endif -+ -+ return 0; -+} -+ -+static int snd_atmel_ac97_playback_trigger(snd_pcm_substream_t *substream, int cmd) -+{ -+ atmel_ac97_t *chip = snd_pcm_substream_chip(substream); -+ unsigned long camr; -+ int flags, err = 0; -+ -+ spin_lock_irqsave(&chip->lock, flags); -+ camr = ac97c_readl(chip, CAMR); -+ -+ switch (cmd) { -+ case SNDRV_PCM_TRIGGER_START: -+ err = dma_prepare_request_cyclic(chip->dma.req_tx.req.dmac, -+ &chip->dma.req_tx); -+ dma_start_request(chip->dma.req_tx.req.dmac, -+ chip->dma.req_tx.req.channel); -+ camr |= (AC97C_CMR_CENA -+#ifdef CONFIG_SND_ATMEL_AC97C_USE_PDC -+ |AC97C_CMR_TXRDY -+#endif -+ ); -+ break; -+ case SNDRV_PCM_TRIGGER_STOP: -+ err = dma_stop_request(chip->dma.req_tx.req.dmac, -+ chip->dma.req_tx.req.channel); -+ if (chip->opened <= 1) { -+ camr &= ~(AC97C_CMR_CENA -+#ifdef CONFIG_SND_ATMEL_AC97C_USE_PDC -+ |AC97C_CMR_TXRDY -+#endif -+ ); -+ } -+#ifdef CONFIG_SND_ATMEL_AC97C_USE_PDC -+ else { -+ camr &= ~(AC97C_CMR_TXRDY); -+ } -+#endif -+ break; -+ default: -+ err = -EINVAL; -+ break; -+ } -+ -+ ac97c_writel(chip, CAMR, camr); -+ -+ spin_unlock_irqrestore(&chip->lock, flags); -+ return err; -+} -+ -+static int snd_atmel_ac97_capture_trigger(snd_pcm_substream_t *substream, int cmd) -+{ -+ atmel_ac97_t *chip = snd_pcm_substream_chip(substream); -+ unsigned long camr; -+ int flags, err = 0; -+ -+ spin_lock_irqsave(&chip->lock, flags); -+ camr = ac97c_readl(chip, CAMR); -+ -+ switch (cmd) { -+ case SNDRV_PCM_TRIGGER_START: -+ err = dma_prepare_request_cyclic(chip->dma.req_rx.req.dmac, -+ &chip->dma.req_rx); -+ dma_start_request(chip->dma.req_rx.req.dmac, -+ chip->dma.req_rx.req.channel); -+ camr |= (AC97C_CMR_CENA -+#ifdef CONFIG_SND_ATMEL_AC97C_USE_PDC -+ | AC97C_CMR_RXRDY -+#endif -+ ); -+ break; -+ case SNDRV_PCM_TRIGGER_STOP: -+ err = dma_stop_request(chip->dma.req_rx.req.dmac, -+ chip->dma.req_rx.req.channel); -+ mutex_lock(&opened_mutex); -+ if (chip->opened <= 1) { -+ camr &= ~(AC97C_CMR_CENA -+#ifdef CONFIG_SND_ATMEL_AC97C_USE_PDC -+ | AC97C_CMR_RXRDY -+#endif -+ ); -+ } -+#ifdef CONFIG_SND_ATMEL_AC97C_USE_PDC -+ else { -+ camr &= ~(AC97C_CSR_RXRDY); -+ } -+#endif -+ mutex_unlock(&opened_mutex); -+ break; -+ default: -+ err = -EINVAL; -+ break; -+ } -+ -+ ac97c_writel(chip, CAMR, camr); -+ -+ spin_unlock_irqrestore(&chip->lock, flags); -+ return err; -+} -+ -+static snd_pcm_uframes_t snd_atmel_ac97_playback_pointer(snd_pcm_substream_t *substream) -+{ -+ atmel_ac97_t *chip = snd_pcm_substream_chip(substream); -+ snd_pcm_runtime_t *runtime = substream->runtime; -+ snd_pcm_uframes_t pos; -+ unsigned long bytes; -+ -+#ifdef CONFIG_SND_ATMEL_AC97C_USE_PDC -+ bytes = ac97c_readl(chip, CATPR) - runtime->dma_addr; -+#else -+ bytes = (dma_get_current_pos -+ (chip->dma.req_tx.req.dmac, -+ chip->dma.req_tx.req.channel) - runtime->dma_addr); -+#endif -+ pos = bytes_to_frames(runtime, bytes); -+ if (pos >= runtime->buffer_size) -+ pos -= runtime->buffer_size; -+ -+ return pos; -+} -+ -+static snd_pcm_uframes_t snd_atmel_ac97_capture_pointer(snd_pcm_substream_t *substream) -+{ -+ atmel_ac97_t *chip = snd_pcm_substream_chip(substream); -+ snd_pcm_runtime_t *runtime = substream->runtime; -+ snd_pcm_uframes_t pos; -+ unsigned long bytes; -+ -+#ifdef CONFIG_SND_ATMEL_AC97C_USE_PDC -+ bytes = ac97c_readl(chip, CARPR) - runtime->dma_addr; -+#else -+ bytes = (dma_get_current_pos -+ (chip->dma.req_rx.req.dmac,chip->dma.req_rx.req.channel) - -+ runtime->dma_addr); -+#endif -+ pos = bytes_to_frames(runtime, bytes); -+ if (pos >= runtime->buffer_size) -+ pos -= runtime->buffer_size; -+ -+ -+ return pos; -+} -+ -+static snd_pcm_ops_t atmel_ac97_playback_ops = { -+ .open = snd_atmel_ac97_playback_open, -+ .close = snd_atmel_ac97_playback_close, -+ .ioctl = snd_pcm_lib_ioctl, -+ .hw_params = snd_atmel_ac97_playback_hw_params, -+ .hw_free = snd_atmel_ac97_playback_hw_free, -+ .prepare = snd_atmel_ac97_playback_prepare, -+ .trigger = snd_atmel_ac97_playback_trigger, -+ .pointer = snd_atmel_ac97_playback_pointer, -+}; -+ -+static snd_pcm_ops_t atmel_ac97_capture_ops = { -+ .open = snd_atmel_ac97_capture_open, -+ .close = snd_atmel_ac97_capture_close, -+ .ioctl = snd_pcm_lib_ioctl, -+ .hw_params = snd_atmel_ac97_capture_hw_params, -+ .hw_free = snd_atmel_ac97_capture_hw_free, -+ .prepare = snd_atmel_ac97_capture_prepare, -+ .trigger = snd_atmel_ac97_capture_trigger, -+ .pointer = snd_atmel_ac97_capture_pointer, -+}; -+ -+static struct ac97_pcm atmel_ac97_pcm_defs[] __devinitdata = { -+ /* Playback */ -+ { -+ .exclusive = 1, -+ .r = { { -+ .slots = ((1 << AC97_SLOT_PCM_LEFT) -+ | (1 << AC97_SLOT_PCM_RIGHT) -+ | (1 << AC97_SLOT_PCM_CENTER) -+ | (1 << AC97_SLOT_PCM_SLEFT) -+ | (1 << AC97_SLOT_PCM_SRIGHT) -+ | (1 << AC97_SLOT_LFE)), -+ } } -+ }, -+ /* PCM in */ -+ { -+ .stream = 1, -+ .exclusive = 1, -+ .r = { { -+ .slots = ((1 << AC97_SLOT_PCM_LEFT) -+ | (1 << AC97_SLOT_PCM_RIGHT)), -+ } } -+ }, -+ /* Mic in */ -+ { -+ .stream = 1, -+ .exclusive = 1, -+ .r = { { -+ .slots = (1<<AC97_SLOT_MIC), -+ } } -+ }, -+}; -+ -+static int __devinit snd_atmel_ac97_pcm_new(atmel_ac97_t *chip) -+{ -+ snd_pcm_t *pcm; -+ int err; -+ -+ err = snd_ac97_pcm_assign(chip->ac97_bus, -+ ARRAY_SIZE(atmel_ac97_pcm_defs), -+ atmel_ac97_pcm_defs); -+ if (err) -+ return err; -+ -+ err = snd_pcm_new(chip->card, "Atmel-AC97", 0, 1, 1, &pcm); -+ if (err) -+ return err; -+ -+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, -+ &atmel_ac97_playback_ops); -+ -+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, -+ &atmel_ac97_capture_ops); -+ -+#ifdef SND_ATMEL_AC97_USE_ALSA_MALLOC_CALLS -+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, -+ &chip->pdev->dev, -+ 128 * 1024, 128 * 1024); -+#endif -+ -+ pcm->private_data = chip; -+ pcm->info_flags = 0; -+ strcpy(pcm->name, "Atmel-AC97"); -+ chip->pcm = pcm; -+ -+ return 0; -+} -+ -+/* Mixer part */ -+static int snd_atmel_ac97_mixer_new(atmel_ac97_t *chip) -+{ -+ int err; -+ ac97_template_t template; -+ -+ memset(&template, 0, sizeof(template)); -+ template.private_data = chip; -+ err = snd_ac97_mixer(chip->ac97_bus, &template, &chip->ac97); -+ -+ return err; -+} -+ -+#ifdef CONFIG_SND_ATMEL_AC97C_USE_PDC -+static irqreturn_t snd_atmel_ac97_interrupt(int irq, void *dev_id, -+ struct pt_regs *regs) -+{ -+ atmel_ac97_t *chip = dev_id; -+ unsigned long status; -+ -+ status = ac97c_readl(chip, SR); -+ -+ if (status & AC97C_SR_CAEVT) { -+ snd_pcm_runtime_t *runtime; -+ int offset, next_period, block_size; -+ unsigned long casr; -+ -+ /* FIXME: separate playback from capture */ -+ runtime = chip->playback_substream->runtime; -+ block_size = frames_to_bytes(runtime, runtime->period_size); -+ -+ casr = ac97c_readl(chip, CASR); -+ -+ if (casr & AC97C_CSR_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; -+ -+ ac97c_writel(chip, CATNPR, -+ runtime->dma_addr + offset); -+ ac97c_writel(chip, CATNCR, block_size / 4); -+ -+ snd_pcm_period_elapsed(chip->playback_substream); -+ } -+ else if (casr & AC97C_CSR_ENDRX) { -+ 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; -+ -+ ac97c_writel(chip, CARNPR, -+ runtime->dma_addr + offset); -+ ac97c_writel(chip, CARNCR, block_size / 4); -+ -+ snd_pcm_period_elapsed(chip->capture_substream); -+ } else { -+ snd_printk(KERN_INFO -+ "atmel-ac97: spurious interrupt, status = 0x%08lx\n", -+ (unsigned long)casr); -+ } -+ } else { -+ snd_printk(KERN_INFO -+ "atmel-ac97: spurious interrupt, status = 0x%08lx\n", -+ status); -+ } -+ -+ (volatile int)ac97c_readl(chip, SR); -+ -+ return IRQ_HANDLED; -+} -+ -+#else -+ -+static void atmel_ac97_error(struct dma_request *_req) -+{ -+ struct dma_request_cyclic *req = to_dma_request_cyclic(_req); -+ -+ printk(KERN_WARNING -+ "DMA Controller error, channel %d (AC97C)\n", -+ req->req.channel); -+} -+ -+static void atmel_ac97_block_complete(struct dma_request *_req) -+{ -+ struct dma_request_cyclic *req = to_dma_request_cyclic(_req); -+ atmel_ac97_t *chip = req->dev_id; -+ if (req->periph_id == chip->dma.tx_periph_id) -+ snd_pcm_period_elapsed(chip->playback_substream); -+ else -+ snd_pcm_period_elapsed(chip->capture_substream); -+} -+ -+#endif -+ -+/* CODEC part */ -+ -+static void snd_atmel_ac97_write(ac97_t *ac97, unsigned short reg, -+ unsigned short val) -+{ -+ atmel_ac97_t *chip = ac97->private_data; -+ unsigned long word; -+ int timeout = 40; -+ -+ word = (reg & 0x7f) << 16 | val; -+ -+ do { -+ if (ac97c_readl(chip, COSR) & AC97C_CSR_TXRDY) { -+ ac97c_writel(chip, COTHR, word); -+ return; -+ } -+ udelay(1); -+ } while (--timeout); -+ -+ snd_printk(KERN_WARNING "atmel-ac97: codec write timeout\n"); -+} -+ -+static unsigned short snd_atmel_ac97_read(ac97_t *ac97, -+ unsigned short reg) -+{ -+ atmel_ac97_t *chip = ac97->private_data; -+ unsigned long word; -+ int timeout = 40; -+ int write = 10; -+ -+ word = (0x80 | (reg & 0x7f)) << 16; -+ -+ if ((ac97c_readl(chip, COSR) & AC97C_CSR_RXRDY) != 0) -+ ac97c_readl(chip, CORHR); -+ -+retry_write: -+ timeout = 40; -+ -+ do { -+ if ((ac97c_readl(chip, COSR) & AC97C_CSR_TXRDY) != 0) { -+ ac97c_writel(chip, COTHR, word); -+ goto read_reg; -+ } -+ mdelay(10); -+ } while (--timeout); -+ -+ if (!--write) -+ goto timed_out; -+ goto retry_write; -+ -+read_reg: -+ do { -+ if ((ac97c_readl(chip, COSR) & AC97C_CSR_RXRDY) != 0){ -+ unsigned short val = ac97c_readl(chip, CORHR); -+ return val; -+ } -+ mdelay(10); -+ } while (--timeout); -+ -+ if (!--write) -+ goto timed_out; -+ goto retry_write; -+ -+timed_out: -+ snd_printk(KERN_INFO "atmel-ac97: codec read timeout\n"); -+ return 0xffff; -+} -+ -+static void snd_atmel_ac97_reset(atmel_ac97_t *chip) -+{ -+ /* TODO: Perform hard reset of codec as well */ -+ ac97c_writel(chip, MR, AC97C_MR_WRST); -+ mdelay(1); -+ ac97c_writel(chip, MR, AC97C_MR_ENA); -+} -+ -+static void snd_atmel_ac97_destroy(snd_card_t *card) -+{ -+ atmel_ac97_t *chip = get_chip(card); -+ -+#ifdef CONFIG_SND_ATMEL_AC97C_USE_PDC -+ if (chip->irq != -1) -+ free_irq(chip->irq, chip); -+#endif -+ if (chip->regs) -+ iounmap(chip->regs); -+ -+ if (chip->mck) { -+ clk_disable(chip->mck); -+ clk_put(chip->mck); -+ } -+ -+#ifndef CONFIG_SND_ATMEL_AC97C_USE_PDC -+ if (chip->dma.req_tx.req.dmac){ -+ dma_release_channel(chip->dma.req_tx.req.dmac, -+ chip->dma.req_tx.req.channel); -+ } -+ if (chip->dma.req_rx.req.dmac) { -+ dma_release_channel(chip->dma.req_rx.req.dmac, -+ chip->dma.req_rx.req.channel); -+ } -+#endif -+} -+ -+static int __devinit snd_atmel_ac97_create(snd_card_t *card, -+ struct platform_device *pdev) -+{ -+ static ac97_bus_ops_t ops = { -+ .write = snd_atmel_ac97_write, -+ .read = snd_atmel_ac97_read, -+ }; -+ atmel_ac97_t *chip = get_chip(card); -+ struct resource *regs; -+ struct clk *mck; -+#ifdef CONFIG_SND_ATMEL_AC97C_USE_PDC -+ int irq; -+#endif -+ int err; -+ -+ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!regs) -+ return -ENXIO; -+#ifdef CONFIG_SND_ATMEL_AC97C_USE_PDC -+ irq = platform_get_irq(pdev, 0); -+ if (irq < 0) -+ return irq; -+#endif -+ -+ mck = clk_get(&pdev->dev, "mck"); -+ if (IS_ERR(mck)) -+ return PTR_ERR(mck); -+ clk_enable(mck); -+ chip->mck = mck; -+ -+ card->private_free = snd_atmel_ac97_destroy; -+ -+ spin_lock_init(&chip->lock); -+ chip->card = card; -+ chip->pdev = pdev; -+ chip->irq = -1; -+ -+#ifdef CONFIG_SND_ATMEL_AC97C_USE_PDC -+ err = request_irq(irq, snd_atmel_ac97_interrupt, 0, -+ "ac97", chip); -+ if (err) { -+ snd_printk("unable to request IRQ%d\n", irq); -+ return err; -+ } -+ chip->irq = irq; -+#endif -+ -+ chip->regs = ioremap(regs->start, regs->end - regs->start + 1); -+ if (!chip->regs) -+ return -ENOMEM; -+ -+ snd_card_set_dev(card, &pdev->dev); -+ -+ err = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus); -+ -+ return err; -+} -+ -+static int __devinit snd_atmel_ac97_probe(struct platform_device *pdev) -+{ -+ static int dev; -+ snd_card_t *card; -+ atmel_ac97_t *chip; -+ int err; -+ int ch; -+ -+ if (dev >= SNDRV_CARDS) -+ return -ENODEV; -+ if (!enable[dev]) { -+ dev++; -+ return -ENOENT; -+ } -+ -+ err = -ENOMEM; -+ -+ mutex_init(&opened_mutex); -+ -+ card = snd_card_new(index[dev], id[dev], THIS_MODULE, -+ sizeof(atmel_ac97_t)); -+ if (!card) -+ goto out; -+ chip = get_chip(card); -+ -+ err = snd_atmel_ac97_create(card, pdev); -+ if (err) -+ goto out_free_card; -+ -+ snd_atmel_ac97_reset(chip); -+ -+ err = snd_atmel_ac97_mixer_new(chip); -+ if (err) -+ goto out_free_card; -+ -+ err = snd_atmel_ac97_pcm_new(chip); -+ if (err) -+ goto out_free_card; -+ -+#ifndef CONFIG_SND_ATMEL_AC97C_USE_PDC -+ /* TODO: Get this information from the platform device */ -+ chip->dma.req_tx.req.dmac = find_dma_controller(0); -+ if (!chip->dma.req_tx.req.dmac) { -+ printk(KERN_ERR -+ "atmel-ac97c: No DMA controller for TX, aborting\n"); -+ goto out_free_card; -+ } -+ chip->dma.req_rx.req.dmac = find_dma_controller(0); -+ if (!chip->dma.req_rx.req.dmac) { -+ snd_printk(KERN_ERR -+ "atmel-ac97c: No DMA controller available for RX, aborting\n"); -+ goto out_free_card; -+ } -+ -+ chip->dma.rx_periph_id = 3; -+ chip->dma.tx_periph_id = 4; -+ -+ ch = dma_alloc_channel(chip->dma.req_tx.req.dmac); -+ if (ch < 0) { -+ printk(KERN_ERR -+ "atmel-ac97c: Unable to allocate TX DMA channel, aborting\n"); -+ goto out_free_card; -+ } -+ chip->dma.req_tx.req.channel = ch; -+ chip->dma.req_tx.width = DMA_WIDTH_16BIT; -+ chip->dma.req_tx.req.block_complete = atmel_ac97_block_complete; -+ chip->dma.req_tx.req.error = atmel_ac97_error; -+ -+ ch = dma_alloc_channel(chip->dma.req_rx.req.dmac); -+ if (ch < 0) { -+ snd_printk(KERN_ERR -+ "atmel-ac97c: Unable to allocate RX DMA channel, aborting\n"); -+ goto out_free_card; -+ } -+ chip->dma.req_rx.req.channel = ch; -+ chip->dma.req_rx.width = DMA_WIDTH_16BIT; -+ chip->dma.req_rx.req.block_complete = atmel_ac97_block_complete; -+ chip->dma.req_rx.req.error = atmel_ac97_error; -+#endif -+ -+ strcpy(card->driver, "ac97c"); -+ strcpy(card->shortname, "Atmel-AC97"); -+#ifdef CONFIG_SND_ATMEL_AC97C_USE_PDC -+ sprintf(card->longname, "Atmel AVR32 AC97 Controller at 0x%p, irq %i", -+ chip->regs, chip->irq); -+#else -+ sprintf(card->longname, "Atmel AVR32 AC97 Controller at 0x%p, dma rx %i and tx %i", -+ chip->regs, chip->dma.rx_periph_id, chip->dma.tx_periph_id); -+#endif -+ -+ err = snd_card_register(card); -+ if (err) -+ goto out_free_card; -+ -+ platform_set_drvdata(pdev, card); -+ dev++; -+ return 0; -+ -+out_free_card: -+ snd_card_free(card); -+out: -+ return err; -+} -+ -+static int __devexit snd_atmel_ac97_remove(struct platform_device *pdev) -+{ -+ snd_card_t *card = platform_get_drvdata(pdev); -+ -+ snd_card_free(card); -+ platform_set_drvdata(pdev, NULL); -+ return 0; -+} -+ -+static struct platform_driver atmel_ac97_driver = { -+ .probe = snd_atmel_ac97_probe, -+ .remove = __devexit_p(snd_atmel_ac97_remove), -+ .driver = { -+ .name = "ac97c", -+ }, -+}; -+ -+static int __init atmel_ac97_init(void) -+{ -+ return platform_driver_register(&atmel_ac97_driver); -+} -+ -+static void __exit atmel_ac97_exit(void) -+{ -+ platform_driver_unregister(&atmel_ac97_driver); -+} -+ -+module_init(atmel_ac97_init); -+module_exit(atmel_ac97_exit); -+ -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("Driver for Atmel AC97 Controller"); -+MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>"); -diff -urN linux-2.6.20.4-0rig/sound/avr32/ac97c.h linux-2.6.20.4-atmel/sound/avr32/ac97c.h ---- linux-2.6.20.4-0rig/sound/avr32/ac97c.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/sound/avr32/ac97c.h 2007-03-24 16:42:29.000000000 +0100 -@@ -0,0 +1,71 @@ -+/* -+ * Register definitions for the Atmel AC97 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 __SOUND_AVR32_AC97C_H -+#define __SOUND_AVR32_AC97C_H -+ -+#define AC97C_MR 0x08 -+#define AC97C_ICA 0x10 -+#define AC97C_OCA 0x14 -+#define AC97C_CARHR 0x20 -+#define AC97C_CATHR 0x24 -+#define AC97C_CASR 0x28 -+#define AC97C_CAMR 0x2c -+#define AC97C_CBRHR 0x30 -+#define AC97C_CBTHR 0x34 -+#define AC97C_CBSR 0x38 -+#define AC97C_CBMR 0x3c -+#define AC97C_CORHR 0x40 -+#define AC97C_COTHR 0x44 -+#define AC97C_COSR 0x48 -+#define AC97C_COMR 0x4c -+#define AC97C_SR 0x50 -+#define AC97C_IER 0x54 -+#define AC97C_IDR 0x58 -+#define AC97C_IMR 0x5c -+#define AC97C_VERSION 0xfc -+ -+#define AC97C_CATPR PDC_TPR -+#define AC97C_CATCR PDC_TCR -+#define AC97C_CATNPR PDC_TNPR -+#define AC97C_CATNCR PDC_TNCR -+#define AC97C_CARPR PDC_RPR -+#define AC97C_CARCR PDC_RCR -+#define AC97C_CARNPR PDC_RNPR -+#define AC97C_CARNCR PDC_RNCR -+#define AC97C_PTCR PDC_PTCR -+ -+#define AC97C_MR_ENA (1 << 0) -+#define AC97C_MR_WRST (1 << 1) -+#define AC97C_MR_VRA (1 << 2) -+ -+#define AC97C_CSR_TXRDY (1 << 0) -+#define AC97C_CSR_UNRUN (1 << 2) -+#define AC97C_CSR_RXRDY (1 << 4) -+#define AC97C_CSR_ENDTX (1 << 10) -+#define AC97C_CSR_ENDRX (1 << 14) -+ -+#define AC97C_CMR_SIZE_20 (0 << 16) -+#define AC97C_CMR_SIZE_18 (1 << 16) -+#define AC97C_CMR_SIZE_16 (2 << 16) -+#define AC97C_CMR_SIZE_10 (3 << 16) -+#define AC97C_CMR_CEM_LITTLE (1 << 18) -+#define AC97C_CMR_CEM_BIG (0 << 18) -+#define AC97C_CMR_CENA (1 << 21) -+#define AC97C_CMR_PDCEN (1 << 22) -+ -+#define AC97C_SR_CAEVT (1 << 3) -+ -+#define AC97C_CH_ASSIGN(slot, channel) \ -+ (AC97C_CHANNEL_##channel << (3 * (AC97_SLOT_##slot - 3))) -+#define AC97C_CHANNEL_NONE 0x0 -+#define AC97C_CHANNEL_A 0x1 -+#define AC97C_CHANNEL_B 0x2 -+ -+#endif /* __SOUND_AVR32_AC97C_H */ -diff -urN linux-2.6.20.4-0rig/sound/avr32/at73c213.c linux-2.6.20.4-atmel/sound/avr32/at73c213.c ---- linux-2.6.20.4-0rig/sound/avr32/at73c213.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/sound/avr32/at73c213.c 2007-03-24 16:42:29.000000000 +0100 -@@ -0,0 +1,1295 @@ -+/* -+ * Driver for the at73c213 16-bit stereo DAC on Atmel ATSTK1000 -+ * -+ * Copyright (C) 2006 Atmel Norway -+ * -+ * 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. -+ */ -+#undef DEBUG -+#include <linux/clk.h> -+#include <linux/delay.h> -+#include <linux/device.h> -+#include <linux/dma-mapping.h> -+#include <linux/init.h> -+#include <linux/interrupt.h> -+#include <linux/kmod.h> -+#include <linux/module.h> -+#include <linux/platform_device.h> -+ -+#include <sound/initval.h> -+#include <sound/driver.h> -+#include <sound/control.h> -+#include <sound/core.h> -+#include <sound/pcm.h> -+#ifndef SND_AT73C213_USE_ALSA_MALLOC_CALLS -+#include <sound/memalloc.h> -+#endif -+ -+#include <linux/spi/spi.h> -+ -+#include <asm/io.h> -+#include <asm/processor.h> -+ -+#include "at73c213.h" -+ -+/* module parameters */ -+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; -+ -+/* Register defines */ -+#define PIOA_BASE 0xFFE02800 -+#define SSC0_BASE 0xFFE01C00 -+#define PM_BASE 0xFFF00000 -+ -+#define PM_CKSEL 0x04 -+#define PM_APBAMASK 0x10 -+#define PM_GCCTRL 0x60 -+ -+#define PIO_PER 0x00 -+#define PIO_PDR 0x04 -+#define PIO_PUER 0x64 -+#define PIO_ASR 0x70 -+#define PIO_BSR 0x74 -+ -+#define SSC_CMR 0x04 -+#define SSC_CR 0x00 -+#define SSC_TCMR 0x18 -+#define SSC_TFMR 0x1C -+ -+/* SSC register definitions */ -+#define SSC_CR 0x00 -+#define SSC_CMR 0x04 -+#define SSC_TCMR 0x18 -+#define SSC_TFMR 0x1C -+#define SSC_THR 0x24 -+#define SSC_SR 0x40 -+#define SSC_IER 0x44 -+#define SSC_IDR 0x48 -+#define SSC_IMR 0x4C -+ -+/* SSC fields definitions */ -+#define SSC_CR_TXEN 0x00000100 -+#define SSC_CR_TXDIS 0x00000200 -+#define SSC_CR_SWRST 0x00008000 -+ -+/* SSC interrupt definitions */ -+#define SSC0_IRQ 10 -+#define SSC_INT_ENDTX 0x00000004 -+#define SSC_INT_TXBUFE 0x00000008 -+ -+/* PDC register definitions */ -+#define PDC_RPR 0x100 -+#define PDC_RCR 0x104 -+#define PDC_TPR 0x108 -+#define PDC_TCR 0x10c -+#define PDC_RNPR 0x110 -+#define PDC_RNCR 0x114 -+#define PDC_TNPR 0x118 -+#define PDC_TNCR 0x11c -+#define PDC_PTCR 0x120 -+#define PDC_PTSR 0x124 -+ -+/* PDC fields definitions */ -+#define PDC_PTCR_RXTEN 0x0001 -+#define PDC_PTCR_RXTDIS 0x0002 -+#define PDC_PTCR_TXTEN 0x0100 -+#define PDC_PTCR_TXTDIS 0x0200 -+ -+static int bitrate; -+static int gclk_div; -+static int ssc_div; -+static int spi = 0; -+static int ssc = 1; -+ -+module_param(spi, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); -+MODULE_PARM_DESC(spi, "Which SPI interface to use to communicate with the at73c213"); -+module_param(ssc, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); -+MODULE_PARM_DESC(ssc, "Which SSC interface to use to communicate with the at73c213"); -+ -+/* Initial AT73C213 register values */ -+static unsigned char 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 */ -+}; -+ -+/* chip-specific data */ -+struct snd_at73c213 { -+ snd_card_t *card; -+ snd_pcm_t *pcm; -+ snd_pcm_substream_t *substream; -+ int irq; -+ int period; -+ void __iomem *regs; -+ struct clk *ssc_clk; -+ struct spi_device *spi; -+ u8 spi_wbuffer[2]; -+ u8 spi_rbuffer[2]; -+ /* image of the SPI registers in AT73C213 */ -+ u8 image[18]; -+ spinlock_t lock; -+ struct platform_device *pdev; -+}; -+ -+#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, -+ }; -+ -+ 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); -+ -+ return spi_sync(chip->spi, &msg); -+} -+ -+#define write_reg(_spi, reg, val) \ -+ do { \ -+ retval = snd_at73c213_write_reg(_spi, reg, val); \ -+ if (retval) \ -+ goto out; \ -+ } while (0) -+ -+static snd_pcm_hardware_t 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, /* This will be overwritten with bitrate */ -+ .rate_max = 50000, /* This will be overwritten with bitrate */ -+ .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_and_div(void) -+{ -+ extern struct avr32_cpuinfo boot_cpu_data; -+ unsigned long pll0_hz, apba_hz; -+ unsigned long apba_realdiv, gclk_realdiv, ssc_realdiv, wanted_bitrate; -+ char cpusel, ahbsel, apbasel; -+ int regval; -+ -+ regval = __raw_readl((void __iomem *)PM_BASE + PM_CKSEL); -+ wanted_bitrate = 48000; -+ -+ cpusel = regval & 0x07; -+ ahbsel = (regval>>8) & 0x07; -+ apbasel = (regval>>16) & 0x07; -+ -+ /* FIXME: Use the clk framework for this */ -+ if ((regval&(1<<7)) != 0) { -+ pll0_hz = clk_get_rate(boot_cpu_data.clk)/(1<<(cpusel+1)); -+ } else { -+ pll0_hz = clk_get_rate(boot_cpu_data.clk); -+ } -+ -+ if ((regval&(1<<23)) != 0) { -+ apba_hz = pll0_hz/(1<<(apbasel+1)); -+ apba_realdiv = (1<<(apbasel+1)); -+ } else { -+ apba_hz = pll0_hz; -+ apba_realdiv = 1; -+ } -+ -+calculate: -+ /* Adjust bitrate as close as possible to 48000 Hz */ -+ gclk_realdiv = pll0_hz/(wanted_bitrate*256); -+ ssc_realdiv = 2 * apba_realdiv * gclk_realdiv; -+ -+ if ((gclk_realdiv % 2) == 0) -+ goto setbitrates; -+ -+ if(wanted_bitrate >= 22050 && wanted_bitrate <= 48000) -+ wanted_bitrate -= 50; -+ else if (wanted_bitrate < 22050) -+ wanted_bitrate = 48050; -+ else if (wanted_bitrate <= 50000) -+ wanted_bitrate += 50; -+ else { -+ printk(KERN_ERR "at73c213 could not set dividers for a valid bitrate\n"); -+ return -EINVAL; -+ } -+ -+ goto calculate; -+ -+setbitrates: -+ bitrate = pll0_hz/(gclk_realdiv*256); -+ gclk_div = (gclk_realdiv/2)-1; -+ ssc_realdiv = 2*apba_realdiv*gclk_realdiv; -+ ssc_div = ssc_realdiv/(2*apba_realdiv); -+ -+ printk(KERN_INFO "at73c213: bitrate is %d Hz\n", bitrate); -+ -+ return 0; -+} -+ -+/* open callback */ -+static int snd_at73c213_pcm_open(snd_pcm_substream_t *substream) -+{ -+ struct snd_at73c213 *chip = snd_pcm_substream_chip(substream); -+ snd_pcm_runtime_t *runtime = substream->runtime; -+ -+ snd_at73c213_playback_hw.rate_min = bitrate; -+ snd_at73c213_playback_hw.rate_max = bitrate; -+ runtime->hw = snd_at73c213_playback_hw; -+ chip->substream = substream; -+ -+ return 0; -+} -+ -+/* close callback */ -+static int snd_at73c213_pcm_close(snd_pcm_substream_t *substream) -+{ -+ struct snd_at73c213 *chip = snd_pcm_substream_chip(substream); -+ chip->substream = NULL; -+ return 0; -+} -+ -+/* hw_params callback */ -+static int snd_at73c213_pcm_hw_params(snd_pcm_substream_t *substream, -+ snd_pcm_hw_params_t *hw_params) -+{ -+#ifdef SND_AT73C213_USE_ALSA_MALLOC_CALLS -+ return snd_pcm_lib_malloc_pages(substream, -+ params_buffer_bytes(hw_params)); -+#else -+ int pg; -+ size_t size = params_buffer_bytes(hw_params); -+ struct snd_pcm_runtime *runtime; -+ struct snd_dma_buffer *dmab = NULL; -+ -+ substream->dma_buffer.dev.type = SNDRV_DMA_TYPE_DEV; -+ snd_assert(substream != NULL, return -EINVAL); -+ runtime = substream->runtime; -+ snd_assert(runtime != NULL, return -EINVAL); -+ -+ /* check if buffer is already allocated */ -+ if (runtime->dma_buffer_p) { -+ size_t size_previouse; -+ int pg_previouse; -+ -+ /* new buffer is smaler than previouse allocated buffer */ -+ if (runtime->dma_buffer_p->bytes >= size) { -+ runtime->dma_bytes = size; -+ return 0; /* don't change buffer size */ -+ } -+ -+ size_previouse = runtime->dma_buffer_p->bytes; -+ pg_previouse = get_order(size_previouse); -+ -+ dma_free_coherent(runtime->dma_buffer_p->dev.dev, -+ PAGE_SIZE << pg_previouse, -+ runtime->dma_buffer_p->area, -+ runtime->dma_buffer_p->addr); -+ -+ kfree(runtime->dma_buffer_p); -+ } -+ -+ dmab = kzalloc(sizeof(*dmab), GFP_KERNEL); -+ if (!dmab) -+ return -ENOMEM; -+ -+ dmab->dev = substream->dma_buffer.dev; -+ dmab->bytes = 0; -+ -+ pg = get_order(size); -+ -+ dmab->area = dma_alloc_coherent( -+ substream->dma_buffer.dev.dev, -+ PAGE_SIZE << pg, -+ (dma_addr_t *)&dmab->addr, -+ GFP_KERNEL); -+ -+ if (!dmab->area) { -+ kfree(dmab); -+ return -ENOMEM; -+ } -+ -+ dmab->bytes = size; -+ snd_pcm_set_runtime_buffer(substream, dmab); -+ runtime->dma_bytes = size; -+ return 1; -+#endif -+} -+ -+/* hw_free callback */ -+static int snd_at73c213_pcm_hw_free(snd_pcm_substream_t *substream) -+{ -+#ifdef SND_AT73C213_USE_ALSA_MALLOC_CALLS -+ return snd_pcm_lib_free_pages(substream); -+#else -+ int pg; -+ struct snd_pcm_runtime *runtime; -+ struct snd_dma_buffer *dmab = NULL; -+ -+ snd_assert(substream != NULL, return -EINVAL); -+ runtime = substream->runtime; -+ snd_assert(runtime != NULL, return -EINVAL); -+ dmab = runtime->dma_buffer_p; -+ -+ if (!dmab) -+ return 0; -+ -+ if (!dmab->area) -+ return 0; -+ -+ pg = get_order(dmab->bytes); -+ dma_free_coherent(dmab->dev.dev, PAGE_SIZE << pg, dmab->area, dmab->addr); -+ kfree(runtime->dma_buffer_p); -+ snd_pcm_set_runtime_buffer(substream, NULL); -+ return 0; -+#endif -+} -+ -+/* prepare callback */ -+static int snd_at73c213_pcm_prepare(snd_pcm_substream_t *substream) -+{ -+ struct snd_at73c213 *chip = snd_pcm_substream_chip(substream); -+ struct platform_device *pdev = chip->pdev; -+ snd_pcm_runtime_t *runtime = substream->runtime; -+ int block_size; -+ -+ block_size = frames_to_bytes(runtime, runtime->period_size); -+ -+ chip->period = 0; -+ -+ /* Make sure that our data are actually readable by the SSC */ -+ dma_sync_single_for_device(&pdev->dev, runtime->dma_addr, -+ block_size, DMA_TO_DEVICE); -+ dma_sync_single_for_device(&pdev->dev, runtime->dma_addr + block_size, -+ block_size, DMA_TO_DEVICE); -+ -+ __raw_writel(runtime->dma_addr, chip->regs + PDC_TPR); -+ __raw_writel(runtime->period_size * 2, chip->regs + PDC_TCR); -+ __raw_writel(runtime->dma_addr + block_size, chip->regs + PDC_TNPR); -+ __raw_writel(runtime->period_size * 2, chip->regs + PDC_TNCR); -+ -+ return 0; -+} -+ -+/* trigger callback */ -+static int snd_at73c213_pcm_trigger(snd_pcm_substream_t *substream, -+ int cmd) -+{ -+ struct snd_at73c213 *chip = snd_pcm_substream_chip(substream); -+ int retval = 0; -+ int flags = 0; -+ -+ spin_lock_irqsave(&chip->lock, flags); -+ -+ switch (cmd) { -+ case SNDRV_PCM_TRIGGER_START: -+ __raw_writel(SSC_INT_ENDTX, chip->regs + SSC_IER); -+ __raw_writel(PDC_PTCR_TXTEN, chip->regs + PDC_PTCR); -+ break; -+ case SNDRV_PCM_TRIGGER_STOP: -+ __raw_writel(PDC_PTCR_TXTDIS, chip->regs + PDC_PTCR); -+ __raw_writel(SSC_INT_ENDTX, chip->regs + SSC_IDR); -+ break; -+ default: -+ printk(KERN_WARNING "at73c213: spuriouse command %x\n", cmd); -+ retval = -EINVAL; -+ break; -+ } -+ -+ spin_unlock_irqrestore(&chip->lock, flags); -+ -+ return retval; -+} -+ -+/* pointer callback */ -+static snd_pcm_uframes_t snd_at73c213_pcm_pointer(snd_pcm_substream_t *substream) -+{ -+ struct snd_at73c213 *chip = snd_pcm_substream_chip(substream); -+ snd_pcm_runtime_t *runtime = substream->runtime; -+ snd_pcm_uframes_t pos; -+ unsigned long bytes; -+ -+ bytes = __raw_readl(chip->regs + PDC_TPR) - runtime->dma_addr; -+ -+ pos = bytes_to_frames(runtime, bytes); -+ if (pos >= runtime->buffer_size) -+ pos -= runtime->buffer_size; -+ -+ return pos; -+} -+ -+/* operators */ -+static snd_pcm_ops_t 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, -+}; -+ -+/* free a pcm device */ -+static void snd_at73c213_pcm_free(snd_pcm_t *pcm) -+{ -+ struct snd_at73c213 *chip = snd_pcm_chip(pcm); -+ if (chip->pcm != 0 ) { -+#ifdef SND_AT73C213_USE_ALSA_MALLOC_CALLS -+ snd_pcm_lib_preallocate_free_for_all(chip->pcm); -+#endif -+ chip->pcm = NULL; -+ } -+} -+ -+/* create a new pcm device */ -+static int __devinit snd_at73c213_new_pcm(struct snd_at73c213 *chip, int device) -+{ -+ snd_pcm_t *pcm; -+ int retval; -+ -+ retval = snd_pcm_new(chip->card, chip->card->shortname, device, 1, 0, &pcm); -+ if (retval < 0) -+ return retval; -+ -+ 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); -+ -+#ifdef SND_AT73C213_USE_ALSA_MALLOC_CALLS -+ snd_pcm_lib_preallocate_pages_for_all(chip->pcm, SNDRV_DMA_TYPE_DEV, -+ &chip->pdev->dev, 64 * 1024, 64 * 1024); -+#endif -+ -+ return 0; -+} -+ -+static irqreturn_t snd_at73c213_interrupt(int irq, void *dev_id) -+{ -+ struct snd_at73c213 *chip = dev_id; -+ struct platform_device *pdev = chip->pdev; -+ snd_pcm_runtime_t *runtime = chip->substream->runtime; -+ u32 status; -+ int offset, next_period, block_size; -+ -+ spin_lock(&chip->lock); -+ -+ block_size = frames_to_bytes(runtime, runtime->period_size); -+ -+ status = __raw_readl(chip->regs + SSC_IMR); -+ -+ if (status & SSC_INT_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; -+ -+ /* Make sure that our data are actually readable by the SSC */ -+ dma_sync_single_for_device(&pdev->dev, runtime->dma_addr + offset, -+ block_size, DMA_TO_DEVICE); -+ __raw_writel(runtime->dma_addr + offset, chip->regs + PDC_TNPR); -+ __raw_writel(runtime->period_size * 2, chip->regs + PDC_TNCR); -+ -+ if (next_period == 0) { -+ (void)__raw_readl(chip->regs + PDC_TPR); -+ (void)__raw_readl(chip->regs + PDC_TCR); -+ } -+ } else { -+ printk(KERN_WARNING -+ "Spurious SSC interrupt, status = 0x%08lx\n", -+ (unsigned long)status); -+ __raw_writel(status, chip->regs + SSC_IDR); -+ } -+ -+ (void)__raw_readl(chip->regs + SSC_IMR); -+ spin_unlock(&chip->lock); -+ -+ if (status & SSC_INT_ENDTX) -+ snd_pcm_period_elapsed(chip->substream); -+ -+ return IRQ_HANDLED; -+} -+ -+/* -+ * Mixer functions -+ */ -+#if 0 /* Function not in use */ -+static int snd_at73c213_mono_info(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_info *uinfo) -+{ -+ unsigned long mask = (kcontrol->private_value >> 16) & 0xff; -+ -+ uinfo->type = (mask == 1) ? -+ SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; -+ uinfo->count = 1; -+ uinfo->value.integer.min = 0; -+ uinfo->value.integer.max = mask; -+ -+ return 0; -+} -+#endif -+ -+static int snd_at73c213_mono_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_at73c213 *chip = snd_kcontrol_chip(kcontrol); -+ unsigned long flags; -+ 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_irqsave(&chip->lock, flags); -+ -+ ucontrol->value.integer.value[0] = (chip->image[reg] >> shift) & mask; -+ -+ if (invert) -+ ucontrol->value.integer.value[0] = -+ (mask - ucontrol->value.integer.value[0]); -+ -+ spin_unlock_irqrestore(&chip->lock, flags); -+ -+ 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); -+ unsigned long flags; -+ 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_irqsave(&chip->lock, flags); -+ -+ val = (chip->image[reg] & ~(mask << shift)) | val; -+ change = val != chip->image[reg]; -+ write_reg(chip, reg, val); -+ -+ chip->image[reg] = val; -+ -+ spin_unlock_irqrestore(&chip->lock, flags); -+ -+ return change; -+ -+out: -+ return retval; -+} -+ -+static int snd_at73c213_stereo_info(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_info *uinfo) -+{ -+ int mask = (kcontrol->private_value >> 24) & 0xFF; -+ -+ uinfo->type = mask == 1 ? -+ SNDRV_CTL_ELEM_TYPE_BOOLEAN : 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); -+ unsigned long flags; -+ 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_irqsave(&chip->lock, flags); -+ -+ ucontrol->value.integer.value[0] = -+ (chip->image[left_reg] >> shift_left) & mask; -+ ucontrol->value.integer.value[1] = -+ (chip->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_irqrestore(&chip->lock, flags); -+ -+ 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); -+ unsigned long flags; -+ 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_irqsave(&chip->lock, flags); -+ -+ val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1; -+ val2 = (chip->image[right_reg] & ~(mask << shift_right)) | val2; -+ change = val1 != chip->image[left_reg] || val2 != chip->image[right_reg]; -+ write_reg(chip, left_reg, val1); -+ write_reg(chip, right_reg, val2); -+ -+ chip->image[left_reg] = val1; -+ chip->image[right_reg] = val2; -+ -+ spin_unlock_irqrestore(&chip->lock, flags); -+ -+ 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); -+ unsigned long flags; -+ int reg = kcontrol->private_value & 0xff; -+ int shift = (kcontrol->private_value >> 8) & 0xff; -+ int invert = (kcontrol->private_value >> 24) & 0xff; -+ -+ spin_lock_irqsave(&chip->lock, flags); -+ -+ ucontrol->value.integer.value[0] = (chip->image[reg] >> shift) & 0x01; -+ -+ if (invert) -+ ucontrol->value.integer.value[0] = -+ (0x01 - ucontrol->value.integer.value[0]); -+ -+ spin_unlock_irqrestore(&chip->lock, flags); -+ -+ 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); -+ unsigned long flags; -+ 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_irqsave(&chip->lock, flags); -+ -+ val |= (chip->image[reg] & ~(mask << shift)); -+ change = val != chip->image[reg]; -+ -+ write_reg(chip, reg, val); -+ -+ chip->image[reg] = val; -+ -+ spin_unlock_irqrestore(&chip->lock, flags); -+ -+ return change; -+ -+out: -+ return retval; -+} -+ -+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; -+ 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; -+ uinfo->value.integer.min = 14; -+ uinfo->value.integer.max = 31; -+ -+ return 0; -+} -+ -+#define AT73C213_MONO(xname, xindex, reg, shift, mask, invert) \ -+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ -+ .info = snd_at73c213_mono_info, \ -+ .get = snd_at73c213_mono_get, .put = snd_at73c213_mono_put, \ -+ .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) } -+ -+#define AT73C213_MONO_SWITCH(xname, xindex, reg, shift, mask, invert) \ -+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ -+ .info = snd_at73c213_mono_switch_info, \ -+ .get = snd_at73c213_mono_switch_get, .put = snd_at73c213_mono_switch_put, \ -+ .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) } -+ -+#define AT73C213_STEREO(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \ -+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ -+ .info = snd_at73c213_stereo_info, \ -+ .get = snd_at73c213_stereo_get, .put = snd_at73c213_stereo_put, \ -+ .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) } -+ -+static struct snd_kcontrol_new snd_at73c213_controls[] __devinitdata = { -+AT73C213_STEREO("Master Playback Volume", 0, DAC_LMPG, DAC_RMPG, 0, 0, 0x1F, 1), -+AT73C213_STEREO("Master Playback Switch", 0, DAC_LMPG, DAC_RMPG, 5, 5, 1, 1), -+AT73C213_STEREO("PCM Playback Volume", 0, DAC_LLOG, DAC_RLOG, 0, 0, 0x1F, 1), -+AT73C213_STEREO("PCM Playback Switch", 0, DAC_LLOG, DAC_RLOG, 5, 5, 1, 1), -+AT73C213_MONO_SWITCH("Mono PA Playback Switch", 0, DAC_CTRL, DAC_CTRL_ONPADRV, 0x01, 0), -+{ -+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, -+ .name = "PA Playback Volume", -+ .index = 0, -+ .info = snd_at73c213_pa_volume_info, -+ .get = snd_at73c213_mono_get, -+ .put = snd_at73c213_mono_put, -+ .private_value = PA_CTRL|(PA_CTRL_APAGAIN<<8)|(0x0F<<16)|(1<<24), -+}, -+AT73C213_MONO_SWITCH("PA High Gain Playback Switch", 0, PA_CTRL, PA_CTRL_APALP, 0x01, 1), -+AT73C213_MONO_SWITCH("PA Playback Switch", 0, PA_CTRL, PA_CTRL_APAON, 0x01, 0), -+{ -+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, -+ .name = "Aux Capture Volume", -+ .index = 0, -+ .info = snd_at73c213_aux_capture_volume_info, -+ .get = snd_at73c213_mono_get, -+ .put = snd_at73c213_mono_put, -+ .private_value = DAC_AUXG|(0<<8)|(0x1F<<16)|(1<<24), -+}, -+AT73C213_MONO_SWITCH("Aux Capture Switch", 0, DAC_CTRL, DAC_CTRL_ONAUXIN, 0x01, 0), -+{ -+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, -+ .name = "Line Capture Volume", -+ .index = 0, -+ .info = snd_at73c213_line_capture_volume_info, -+ .get = snd_at73c213_stereo_get, -+ .put = snd_at73c213_stereo_put, -+ .private_value = DAC_LLIG|(DAC_RLIG<<8)|(0<<16)|(0<<19)|(0x1F<<24)|(1<<22), -+}, -+AT73C213_MONO_SWITCH("Line Capture Switch", 0, DAC_CTRL, 0, 0x03, 0), -+}; -+ -+static int __devinit snd_at73c213_mixer(struct snd_at73c213 *chip) -+{ -+ struct snd_card *card; -+ int errval, idx; -+ -+ if (chip == NULL || chip->pcm == NULL) -+ return -EINVAL; -+ -+ card = chip->card; -+ -+ strcpy(card->mixername, chip->pcm->name); -+ -+ for (idx = 0; idx < ARRAY_SIZE(snd_at73c213_controls); idx++) { -+ if ((errval = snd_ctl_add(card, -+ snd_ctl_new1(&snd_at73c213_controls[idx], -+ chip))) < 0) -+ return errval; -+ } -+ -+ return 0; -+} -+ -+/* -+ * Device functions -+ */ -+static int snd_at73c213_chip_init(struct snd_at73c213 *chip) -+{ -+ int retval; -+ unsigned char dac_ctrl = 0; -+ -+ /* XXX: Unmask the APB clock for SSC0 */ -+ __raw_writel(__raw_readl((void __iomem *)PM_BASE + PM_APBAMASK)|(1<<7), -+ (void __iomem *)PM_BASE + PM_APBAMASK); -+ -+ /* Wait for clock to be stable */ -+ msleep(10); -+ -+ retval = snd_at73c213_set_bitrate_and_div(); -+ if (retval) -+ goto out; -+ -+ /* Reset the SSC */ -+ __raw_writel(SSC_CR_SWRST, chip->regs + SSC_CR); -+ -+ /* Enable GCLK0 */ -+ __raw_writel((1<<30), (void __iomem *)(PIOA_BASE + PIO_PDR)); -+ __raw_writel((1<<30), (void __iomem *)(PIOA_BASE + PIO_ASR)); -+ __raw_writel(((gclk_div<<8)|0x10|0x04|0x02), (void __iomem *)(PM_BASE + PM_GCCTRL)); -+ -+ /* Enable SSC and setup for I2S */ -+ __raw_writel(ssc_div, chip->regs + SSC_CMR); -+ -+ /* CKO, START, STTDLY, PERIOD */ -+ __raw_writel((1<<2)|(4<<8)|(1<<16)|(15<<24), chip->regs + SSC_TCMR); -+ -+ /* DATLEN, MSBF, DATNB, FSLEN, FSOS */ -+ __raw_writel((15<<0)|(1<<7)|(1<<8)|(15<<16)|(1<<20), chip->regs + SSC_TFMR); -+ -+ /* Initialize at73c213 on SPI bus */ -+ /* Reset the device */ -+ write_reg(chip, DAC_RST, 0x04); -+ msleep(1); -+ write_reg(chip, DAC_RST, 0x03); -+ -+ /* Turn on precharge */ -+ write_reg(chip, DAC_PRECH, 0xFF); -+ write_reg(chip, PA_CTRL, (1<<PA_CTRL_APAPRECH)); -+ write_reg(chip, DAC_CTRL, (1<<DAC_CTRL_ONLNOL)|(1<<DAC_CTRL_ONLNOR)); -+ -+ msleep(50); -+ -+ /* Stop precharging PA */ -+ write_reg(chip, PA_CTRL, (1<<PA_CTRL_APALP)|0x0F); -+ chip->image[PA_CTRL] = (1<<PA_CTRL_APALP)|0x0F; -+ -+ msleep(450); -+ -+ /* Stop precharging, turn on master power */ -+ write_reg(chip, DAC_PRECH, (1<<DAC_PRECH_ONMSTR)); -+ chip->image[DAC_PRECH] = (1<<DAC_PRECH_ONMSTR); -+ -+ msleep(1); -+ -+ /* Turn on DAC */ -+ dac_ctrl = (1<<DAC_CTRL_ONDACL)|(1<<DAC_CTRL_ONDACR)| -+ (1<<DAC_CTRL_ONLNOL)|(1<<DAC_CTRL_ONLNOR); -+ -+ write_reg(chip, DAC_CTRL, dac_ctrl); -+ chip->image[DAC_CTRL] = dac_ctrl; -+ -+ /* Mute sound */ -+ write_reg(chip, DAC_LMPG, 0x3F); -+ chip->image[DAC_LMPG] = 0x3F; -+ write_reg(chip, DAC_RMPG, 0x3F); -+ chip->image[DAC_RMPG] = 0x3F; -+ write_reg(chip, DAC_LLOG, 0x3F); -+ chip->image[DAC_LLOG] = 0x3F; -+ write_reg(chip, DAC_RLOG, 0x3F); -+ chip->image[DAC_RLOG] = 0x3F; -+ write_reg(chip, DAC_LLIG, 0x11); -+ chip->image[DAC_LLIG] = 0x11; -+ write_reg(chip, DAC_RLIG, 0x11); -+ chip->image[DAC_RLIG] = 0x11; -+ write_reg(chip, DAC_AUXG, 0x11); -+ chip->image[DAC_AUXG] = 0x11; -+ -+ /* Turn on SSC transmitter */ -+ __raw_writel(SSC_CR_TXEN, chip->regs + SSC_CR); -+ -+out: -+ return retval; -+} -+ -+static int snd_at73c213_dev_free(snd_device_t *device) -+{ -+ struct snd_at73c213 *chip = device->device_data; -+ -+ if (chip->regs) { -+ __raw_writel(SSC_CR_TXDIS, chip->regs + SSC_CR); -+ iounmap(chip->regs); -+ } -+ -+ if (chip->irq >= 0) -+ free_irq(chip->irq, chip); -+ -+ if (chip->ssc_clk) { -+ clk_disable(chip->ssc_clk); -+ clk_put(chip->ssc_clk); -+ } -+ -+ return 0; -+} -+ -+static int __devinit snd_at73c213_create(snd_card_t *card, -+ struct platform_device *pdev) -+{ -+ static snd_device_ops_t ops = { -+ .dev_free = snd_at73c213_dev_free, -+ }; -+ struct snd_at73c213 *chip = get_chip(card); -+ struct resource *regs; -+ struct clk *ssc_clk; -+ int irq, retval; -+ -+ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!regs) -+ return -ENXIO; -+ irq = platform_get_irq(pdev, 0); -+ if (irq < 0) -+ return irq; -+ -+ ssc_clk = clk_get(&pdev->dev, "mck"); -+ if (IS_ERR(ssc_clk)) -+ return PTR_ERR(ssc_clk); -+ clk_enable(ssc_clk); -+ chip->ssc_clk = ssc_clk; -+ -+ spin_lock_init(&chip->lock); -+ chip->card = card; -+ chip->pdev = pdev; -+ chip->irq = -1; -+ -+ retval = -ENOMEM; -+ -+ retval = spi_setup(chip->spi); -+ if (retval) -+ goto out; -+ -+ chip->regs = ioremap(regs->start, regs->end - regs->start + 1); -+ if (!chip->regs) -+ goto out; -+ -+ retval = request_irq(irq, snd_at73c213_interrupt, 0, "at73c213", chip); -+ if (retval) { -+ snd_printk("unable to request IRQ%d\n", irq); -+ goto out; -+ } -+ chip->irq = irq; -+ -+ memcpy(&chip->image, &snd_at73c213_original_image, -+ sizeof(snd_at73c213_original_image)); -+ -+ retval = snd_at73c213_chip_init(chip); -+ if (retval) -+ goto out; -+ -+ retval = snd_at73c213_new_pcm(chip, 0); -+ if (retval) -+ goto out; -+ -+ retval = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); -+ if (retval) -+ goto out; -+ -+ retval = snd_at73c213_mixer(chip); -+ if (retval) -+ goto out; -+ -+ snd_card_set_dev(card, &pdev->dev); -+ -+out: -+ return retval; -+} -+ -+static int __devinit snd_at73c213_probe(struct platform_device *pdev) -+{ -+ static int dev; -+ struct spi_board_info *binfo; -+ struct spi_master *smaster; -+ struct snd_at73c213 *chip; -+ snd_card_t *card; -+ int retval; -+ -+ if (dev >= SNDRV_CARDS) -+ return -ENODEV; -+ if (!enable[dev]) { -+ dev++; -+ return -ENOENT; -+ } -+ -+ if (spi < 0 || ssc < 0) -+ return -ENODEV; -+ -+ retval = -ENOMEM; -+ card = snd_card_new(index[dev], id[dev], THIS_MODULE, -+ sizeof(struct snd_at73c213)); -+ if (!card) -+ goto out; -+ -+ chip = card->private_data; -+ -+ retval = -ENODEV; -+ -+ /* Get the SPI bus */ -+ binfo = pdev->dev.platform_data; -+ if (!binfo) { -+ printk(KERN_WARNING "at73c213: could not get platform data\n"); -+ goto out; -+ } -+ -+ smaster = spi_busnum_to_master(spi); -+ if (!smaster) { -+ request_module("spi1"); -+ smaster = spi_busnum_to_master(spi); -+ if (!smaster) { -+ printk(KERN_WARNING -+ "at73c213: could not get " -+ "SPI bus %d, remembered to load " -+ "the spi_atmel module?\n", spi); -+ goto out; -+ } -+ } -+ -+ chip->spi = spi_new_device(smaster, binfo); -+ if (!chip->spi) { -+ printk(KERN_WARNING "at73c213: could not get SPI device %d\n", spi); -+ goto out; -+ } -+ -+ chip->spi->mode = SPI_MODE_1; -+ chip->spi->bits_per_word = 8; -+ -+ retval = snd_at73c213_create(card, pdev); -+ if (retval) -+ goto out_free_card; -+ -+ strcpy(card->driver, "at73c213"); -+ strcpy(card->shortname, "at73c213 (AVR32 STK1000)"); -+ sprintf(card->longname, "%s at %p (irq %i)", card->shortname, chip->regs, chip->irq); -+ -+ retval = snd_card_register(card); -+ if (retval) -+ goto out_free_card; -+ -+ platform_set_drvdata(pdev, card); -+ dev++; -+ return 0; -+ -+out_free_card: -+ snd_card_free(card); -+out: -+ return retval; -+} -+ -+static int __devexit snd_at73c213_remove(struct platform_device *pdev) -+{ -+ struct snd_card *card = platform_get_drvdata(pdev); -+ struct snd_at73c213 *chip = card->private_data; -+ int retval; -+ -+ /* Stop playback */ -+ __raw_writel(SSC_CR_TXDIS, chip->regs + SSC_CR); -+ -+ /* Stop GLCK0 */ -+ __raw_writel(0, (void __iomem *)PM_BASE + PM_GCCTRL); -+ -+ /* Mute sound */ -+ write_reg(chip, DAC_LMPG, 0x3F); -+ chip->image[DAC_LMPG] = 0x3F; -+ write_reg(chip, DAC_RMPG, 0x3F); -+ chip->image[DAC_RMPG] = 0x3F; -+ write_reg(chip, DAC_LLOG, 0x3F); -+ chip->image[DAC_LLOG] = 0x3F; -+ write_reg(chip, DAC_RLOG, 0x3F); -+ chip->image[DAC_RLOG] = 0x3F; -+ write_reg(chip, DAC_LLIG, 0x11); -+ chip->image[DAC_LLIG] = 0x11; -+ write_reg(chip, DAC_RLIG, 0x11); -+ chip->image[DAC_RLIG] = 0x11; -+ write_reg(chip, DAC_AUXG, 0x11); -+ chip->image[DAC_AUXG] = 0x11; -+ -+ /* Turn off PA */ -+ write_reg(chip, PA_CTRL, (chip->image[PA_CTRL]|0x0F)); -+ chip->image[PA_CTRL] |= 0x0F; -+ msleep(10); -+ write_reg(chip, PA_CTRL, (1<<PA_CTRL_APALP)|0x0F); -+ chip->image[PA_CTRL] = (1<<PA_CTRL_APALP)|0x0F; -+ -+ /* Turn off external DAC */ -+ write_reg(chip, DAC_CTRL, 0x0C); -+ chip->image[DAC_CTRL] = 0x0C; -+ msleep(2); -+ write_reg(chip, DAC_CTRL, 0x00); -+ chip->image[DAC_CTRL] = 0x00; -+ -+ /* Turn off master power */ -+ write_reg(chip, DAC_PRECH, 0x00); -+ chip->image[DAC_PRECH] = 0x00; -+ -+ msleep(10); -+ -+out: -+ if (chip->spi) -+ spi_unregister_device(chip->spi); -+ -+ if (card) { -+ snd_card_free(card); -+ platform_set_drvdata(pdev, NULL); -+ } -+ -+ return 0; -+} -+ -+#ifdef CONFIG_PM -+static int snd_at73c213_suspend(struct platform_device *pdev, pm_message_t state, u32 level) -+{ -+ struct snd_card *card = at32_get_drvdata(pdev); -+ struct snd_at73c213 *chip = card->private_data; -+ -+ printk(KERN_DEBUG "at73c213: suspending\n"); -+ -+ /* Stop SSC and GCLK0 */ -+ -+ spi_suspend(chip->spi, state); -+ -+ return 0; -+} -+ -+static int snd_at73c213_resume(struct platform_device *pdev, u32 level) -+{ -+ struct snd_card *card = at32_get_drvdata(pdev); -+ struct snd_at73c213 *chip = card->private_data; -+ -+ printk(KERN_DEBUG "at73c213: resuming\n"); -+ -+ /* Start GLCK0 and SSC */ -+ -+ spi_resume(chip->spi); -+ -+ return 0; -+} -+#endif /* CONFIG_PM */ -+ -+/* Driver core initialization */ -+static struct platform_driver at73c213_driver = { -+ .probe = snd_at73c213_probe, -+ .remove = __devexit_p(snd_at73c213_remove), -+ .driver = { -+ .name = "at73c213", -+ } -+#ifdef CONFIG_PM -+ .resume = snd_at73c213_resume, -+ .suspend = snd_at73c213_suspend, -+#endif -+}; -+ -+static int __init at73c213_init(void) -+{ -+ return platform_driver_register(&at73c213_driver); -+} -+ -+static void __exit at73c213_exit(void) -+{ -+ platform_driver_unregister(&at73c213_driver); -+} -+ -+MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>"); -+MODULE_DESCRIPTION("Sound driver for at73c213 on STK1000"); -+MODULE_LICENSE("GPL"); -+ -+module_init(at73c213_init); -+module_exit(at73c213_exit); -+ -diff -urN linux-2.6.20.4-0rig/sound/avr32/at73c213.h linux-2.6.20.4-atmel/sound/avr32/at73c213.h ---- linux-2.6.20.4-0rig/sound/avr32/at73c213.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/sound/avr32/at73c213.h 2007-03-24 16:42:29.000000000 +0100 -@@ -0,0 +1,120 @@ -+/* -+ * Driver for the AT73C213 16-bit stereo DAC on Atmel ATSTK1000 -+ * -+ * Copyright (C) 2006 Atmel Norway -+ * -+ * 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_MIXER_H_ -+#define _SND_AT73C213_MIXER_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 -+ -diff -urN linux-2.6.20.4-0rig/sound/avr32/Kconfig linux-2.6.20.4-atmel/sound/avr32/Kconfig ---- linux-2.6.20.4-0rig/sound/avr32/Kconfig 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/sound/avr32/Kconfig 2007-03-24 16:42:29.000000000 +0100 -@@ -0,0 +1,51 @@ -+# ALSA AVR32 drivers -+ -+menu "ALSA AVR32 devices" -+ depends on SND != n && AVR32 -+ -+config SND_ATMEL_AC97 -+ tristate "Atmel AC97 Controller Driver" -+ depends on SND -+ select SND_PCM -+ select SND_AC97_CODEC -+ help -+ ALSA sound driver for the Atmel AC97 controller. -+ -+config SND_ATMEL_AC97_USE_ALSA_MALLOC_CALLS -+ bool "Use the built-in malloc calls in the alsa driver" -+ default n -+ depends on SND_ATMEL_AC97 -+ help -+ Say Y if the built-in malloc calls in the alsa driver should be -+ used instead of the native dma_alloc_coherent and dma_free_coherent -+ function calls. Enabling this feature may break the rmmod feature. -+ -+config SND_ATMEL_AC97C_USE_PDC -+ bool "Use PDC for DMA transfers to/from the Atmel AC97 Controller" -+ default n -+ depends on SND_ATMEL_AC97 -+ help -+ Say Y if PDC (Peripheral DMA Controller) is used for DMA transfers -+ to/from the Atmel AC97C instead of using the generic DMA framework. -+ -+config SND_AT73C213 -+ tristate "Atmel AT73C213 DAC driver" -+ depends on SND && SPI_ATMEL -+ select SND_PCM -+ help -+ Say Y here if you want to use the Atmel AT73C213 external -+ DAC on the ATSTK1000 development board. -+ -+ To compile this driver as a module, choose M here: the -+ module will be called snd-at73c213. -+ -+config SND_AT73C213_USE_ALSA_MALLOC_CALLS -+ bool "Use the built-in malloc calls in the alsa driver" -+ default n -+ depends on SND_AT73C213 -+ help -+ Say Y if the built-in malloc calls in the alsa driver should be -+ used instead of the native dma_alloc_coherent and dma_free_coherent -+ function calls. Enabling this feature may brake the rmmod feature. -+ -+endmenu -diff -urN linux-2.6.20.4-0rig/sound/avr32/Makefile linux-2.6.20.4-atmel/sound/avr32/Makefile ---- linux-2.6.20.4-0rig/sound/avr32/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/sound/avr32/Makefile 2007-03-24 16:42:29.000000000 +0100 -@@ -0,0 +1,9 @@ -+# -+# Makefile for ALSA -+# -+ -+snd-atmel-ac97-objs := ac97c.o -+obj-$(CONFIG_SND_ATMEL_AC97) += snd-atmel-ac97.o -+ -+snd-at73c213-objs := at73c213.o -+obj-$(CONFIG_SND_AT73C213) += snd-at73c213.o -diff -urN linux-2.6.20.4-0rig/sound/Kconfig linux-2.6.20.4-atmel/sound/Kconfig ---- linux-2.6.20.4-0rig/sound/Kconfig 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/sound/Kconfig 2007-03-24 16:42:29.000000000 +0100 -@@ -62,6 +62,8 @@ - - source "sound/arm/Kconfig" - -+source "sound/avr32/Kconfig" -+ - source "sound/mips/Kconfig" - - # the following will depend on the order of config. -diff -urN linux-2.6.20.4-0rig/sound/Makefile linux-2.6.20.4-atmel/sound/Makefile ---- linux-2.6.20.4-0rig/sound/Makefile 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/sound/Makefile 2007-03-24 16:42:29.000000000 +0100 -@@ -6,6 +6,7 @@ - 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/ -+obj-$(CONFIG_SND) += avr32/ - obj-$(CONFIG_SND_AOA) += aoa/ - - # This one must be compilable even if sound is configured out -diff -urN linux-2.6.20.4-0rig/sound/oss/at32dac.c linux-2.6.20.4-atmel/sound/oss/at32dac.c ---- linux-2.6.20.4-0rig/sound/oss/at32dac.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/sound/oss/at32dac.c 2007-03-24 16:42:29.000000000 +0100 -@@ -0,0 +1,720 @@ -+/* -+ * OSS Sound Driver for the Atmel AT32 on-chip DAC. -+ * -+ * 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. -+ */ -+#include <linux/clk.h> -+#include <linux/dma-mapping.h> -+#include <linux/fs.h> -+#include <linux/init.h> -+#include <linux/interrupt.h> -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/platform_device.h> -+#include <linux/sound.h> -+#include <linux/soundcard.h> -+ -+#include <asm/byteorder.h> -+#include <asm/dma-controller.h> -+#include <asm/io.h> -+#include <asm/uaccess.h> -+ -+/* We want to use the "bizarre" swap-bytes-in-each-halfword macro */ -+#include <linux/byteorder/swabb.h> -+ -+#include "at32dac.h" -+ -+#define DMA_BUFFER_SIZE 32768 -+#define DMA_PERIOD_SHIFT 10 -+#define DMA_PERIOD_SIZE (1 << DMA_PERIOD_SHIFT) -+#define DMA_WRITE_THRESHOLD DMA_PERIOD_SIZE -+ -+struct sound_settings { -+ unsigned int format; -+ unsigned int channels; -+ unsigned int sample_rate; -+ /* log2(bytes per sample) */ -+ unsigned int input_order; -+}; -+ -+struct at32_dac { -+ spinlock_t lock; -+ void __iomem *regs; -+ -+ /* head and tail refer to number of words */ -+ struct { -+ u32 *buf; -+ int head; -+ int tail; -+ } dma; -+ -+ struct semaphore sem; -+ wait_queue_head_t write_wait; -+ -+ /* -+ * Read at most ucount bytes from ubuf, translate to 2-channel -+ * signed 16-bit big endian format and write to the DMA buffer -+ * as long as there is room left. Return the number of bytes -+ * successfully copied from ubuf, or -EFAULT if the first -+ * sample from ubuf couldn't be read. This function is not -+ * called unless there is room for at least one sample (4 -+ * bytes) in the DMA buffer. -+ */ -+ ssize_t (*trans)(struct at32_dac *dac, const char __user *ubuf, -+ size_t ucount); -+ -+ struct sound_settings dsp_settings; -+ struct dma_request_cyclic req; -+ -+ struct clk *mck; -+ struct clk *sample_clk; -+ struct platform_device *pdev; -+ int busy; -+ int playing; -+ int dev_dsp; -+}; -+static struct at32_dac *the_dac; -+ -+static inline unsigned int at32dac_get_head(struct at32_dac *dac) -+{ -+ return dac->dma.head & ((DMA_BUFFER_SIZE / 4) - 1); -+} -+ -+static inline unsigned int at32dac_get_tail(struct at32_dac *dac) -+{ -+ return dac->dma.tail & ((DMA_BUFFER_SIZE / 4) - 1); -+} -+ -+static inline unsigned int at32dac_dma_space(struct at32_dac *dac) -+{ -+ unsigned int space; -+ -+ space = ((dac->dma.tail - dac->dma.head - 1) -+ & ((DMA_BUFFER_SIZE / 4) - 1)); -+ return space; -+} -+ -+static void at32dac_update_dma_tail(struct at32_dac *dac) -+{ -+ dma_addr_t dma_addr; -+ unsigned int new_tail; -+ -+ if (dac->playing) { -+ dma_addr = dma_get_current_pos(dac->req.req.dmac, -+ dac->req.req.channel); -+ new_tail = (dma_addr - dac->req.buffer_start) / 4; -+ if (new_tail >= dac->dma.head -+ && (dac->dma.tail < dac->dma.head -+ || dac->dma.tail > new_tail)) -+ printk(KERN_NOTICE "at32dac: underrun\n"); -+ dac->dma.tail = new_tail; -+ pr_debug("update tail: 0x%x - 0x%x = %u\n", -+ dma_addr, dac->req.buffer_start, dac->dma.tail); -+ } -+} -+ -+static int at32dac_start(struct at32_dac *dac) -+{ -+ int ret; -+ -+ if (dac->playing) -+ return 0; -+ -+ memset(dac->dma.buf, 0, DMA_BUFFER_SIZE); -+ -+ clk_enable(dac->sample_clk); -+ -+ ret = dma_prepare_request_cyclic(dac->req.req.dmac, &dac->req); -+ if (ret) -+ goto out_stop_clock; -+ -+ pr_debug("Starting DMA...\n"); -+ ret = dma_start_request(dac->req.req.dmac, dac->req.req.channel); -+ if (ret) -+ goto out_stop_request; -+ -+ dac_writel(dac, CTRL, DAC_BIT(EN)); -+ dac->playing = 1; -+ -+ return 0; -+ -+out_stop_request: -+ dma_stop_request(dac->req.req.dmac, -+ dac->req.req.channel); -+out_stop_clock: -+ clk_disable(dac->sample_clk); -+ return ret; -+} -+ -+static int at32dac_stop(struct at32_dac *dac) -+{ -+ if (dac->playing) { -+ dma_stop_request(dac->req.req.dmac, dac->req.req.channel); -+ dac_writel(dac, DATA, 0); -+ dac_writel(dac, CTRL, 0); -+ dac->playing = 0; -+ clk_disable(dac->sample_clk); -+ } -+ -+ return 0; -+} -+ -+static int at32dac_dma_prepare(struct at32_dac *dac) -+{ -+ dac->dma.buf = dma_alloc_coherent(&dac->pdev->dev, DMA_BUFFER_SIZE, -+ &dac->req.buffer_start, GFP_KERNEL); -+ if (!dac->dma.buf) -+ return -ENOMEM; -+ -+ dac->dma.head = dac->dma.tail = 0; -+ dac->req.periods = DMA_BUFFER_SIZE / DMA_PERIOD_SIZE; -+ dac->req.buffer_size = DMA_BUFFER_SIZE; -+ -+ return 0; -+} -+ -+static void at32dac_dma_cleanup(struct at32_dac *dac) -+{ -+ if (dac->dma.buf) -+ dma_free_coherent(&dac->pdev->dev, DMA_BUFFER_SIZE, -+ dac->dma.buf, dac->req.buffer_start); -+ dac->dma.buf = NULL; -+} -+ -+static void at32dac_dma_block_complete(struct dma_request *req) -+{ -+ struct dma_request_cyclic *creq = to_dma_request_cyclic(req); -+ struct at32_dac *dac = container_of(creq, struct at32_dac, req); -+ -+ wake_up(&dac->write_wait); -+} -+ -+static void at32dac_dma_error(struct dma_request *req) -+{ -+ printk(KERN_ERR "at32dac: DMA error\n"); -+} -+ -+static irqreturn_t at32dac_interrupt(int irq, void *dev_id) -+{ -+ struct at32_dac *dac = dev_id; -+ u32 status; -+ -+ status = dac_readl(dac, INT_STATUS); -+ if (status & DAC_BIT(UNDERRUN)) { -+ printk(KERN_ERR "at32dac: Underrun detected\n"); -+ dac_writel(dac, INT_CLR, DAC_BIT(UNDERRUN)); -+ } else { -+ printk(KERN_ERR "at32dac: Spurious interrupt: status=0x%x\n", -+ status); -+ dac_writel(dac, INT_CLR, status); -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+static ssize_t trans_s16be(struct at32_dac *dac, const char __user *ubuf, -+ size_t ucount) -+{ -+ ssize_t ret; -+ -+ if (dac->dsp_settings.channels == 2) { -+ const u32 __user *up = (const u32 __user *)ubuf; -+ u32 sample; -+ -+ for (ret = 0; ret < (ssize_t)(ucount - 3); ret += 4) { -+ if (!at32dac_dma_space(dac)) -+ break; -+ -+ if (unlikely(__get_user(sample, up++))) { -+ if (ret == 0) -+ ret = -EFAULT; -+ break; -+ } -+ dac->dma.buf[at32dac_get_head(dac)] = sample; -+ dac->dma.head++; -+ } -+ } else { -+ const u16 __user *up = (const u16 __user *)ubuf; -+ u16 sample; -+ -+ for (ret = 0; ret < (ssize_t)(ucount - 1); ret += 2) { -+ if (!at32dac_dma_space(dac)) -+ break; -+ -+ if (unlikely(__get_user(sample, up++))) { -+ if (ret == 0) -+ ret = -EFAULT; -+ break; -+ } -+ dac->dma.buf[at32dac_get_head(dac)] -+ = (sample << 16) | sample; -+ dac->dma.head++; -+ } -+ } -+ -+ return ret; -+} -+ -+static ssize_t trans_s16le(struct at32_dac *dac, const char __user *ubuf, -+ size_t ucount) -+{ -+ ssize_t ret; -+ -+ if (dac->dsp_settings.channels == 2) { -+ const u32 __user *up = (const u32 __user *)ubuf; -+ u32 sample; -+ -+ for (ret = 0; ret < (ssize_t)(ucount - 3); ret += 4) { -+ if (!at32dac_dma_space(dac)) -+ break; -+ -+ if (unlikely(__get_user(sample, up++))) { -+ if (ret == 0) -+ ret = -EFAULT; -+ break; -+ } -+ /* Swap bytes in each halfword */ -+ dac->dma.buf[at32dac_get_head(dac)] = swahb32(sample); -+ dac->dma.head++; -+ } -+ } else { -+ const u16 __user *up = (const u16 __user *)ubuf; -+ u16 sample; -+ -+ for (ret = 0; ret < (ssize_t)(ucount - 1); ret += 2) { -+ if (!at32dac_dma_space(dac)) -+ break; -+ -+ if (unlikely(__get_user(sample, up++))) { -+ if (ret == 0) -+ ret = -EFAULT; -+ break; -+ } -+ sample = swab16(sample); -+ dac->dma.buf[at32dac_get_head(dac)] -+ = (sample << 16) | sample; -+ dac->dma.head++; -+ } -+ } -+ -+ return ret; -+} -+ -+static ssize_t at32dac_dma_translate_from_user(struct at32_dac *dac, -+ const char __user *buffer, -+ size_t count) -+{ -+ /* At least one buffer must be available at this point */ -+ pr_debug("at32dac: Copying %zu bytes from user...\n", count); -+ -+ return dac->trans(dac, buffer, count); -+} -+ -+static int at32dac_set_format(struct at32_dac *dac, int format) -+{ -+ unsigned int order; -+ -+ switch (format) { -+ case AFMT_S16_BE: -+ order = 1; -+ dac->trans = trans_s16be; -+ break; -+ case AFMT_S16_LE: -+ order = 1; -+ dac->trans = trans_s16le; -+ break; -+ default: -+ printk("at32dac: Unsupported format: %d\n", format); -+ return -EINVAL; -+ } -+ -+ if (dac->dsp_settings.channels == 2) -+ order++; -+ -+ dac->dsp_settings.input_order = order; -+ dac->dsp_settings.format = format; -+ return 0; -+} -+ -+static int at32dac_set_sample_rate(struct at32_dac *dac, unsigned long rate) -+{ -+ unsigned long new_rate; -+ int ret; -+ -+ ret = clk_set_rate(dac->sample_clk, 256 * rate); -+ if (ret < 0) -+ return ret; -+ -+ /* TODO: mplayer seems to have a problem with this */ -+#if 0 -+ new_rate = clk_get_rate(dac->sample_clk); -+ dac->dsp_settings.sample_rate = new_rate / 256; -+#else -+ dac->dsp_settings.sample_rate = rate; -+#endif -+ -+ return 0; -+} -+ -+static ssize_t at32dac_dsp_write(struct file *file, -+ const char __user *buffer, -+ size_t count, loff_t *ppos) -+{ -+ struct at32_dac *dac = file->private_data; -+ DECLARE_WAITQUEUE(wait, current); -+ unsigned int avail; -+ ssize_t copied; -+ ssize_t ret; -+ -+ /* Avoid address space checking in the translation functions */ -+ if (!access_ok(buffer, count, VERIFY_READ)) -+ return -EFAULT; -+ -+ down(&dac->sem); -+ -+ if (!dac->dma.buf) { -+ ret = at32dac_dma_prepare(dac); -+ if (ret) -+ goto out; -+ } -+ -+ add_wait_queue(&dac->write_wait, &wait); -+ ret = 0; -+ while (count > 0) { -+ do { -+ at32dac_update_dma_tail(dac); -+ avail = at32dac_dma_space(dac); -+ set_current_state(TASK_INTERRUPTIBLE); -+ if (avail >= DMA_WRITE_THRESHOLD) -+ break; -+ -+ if (file->f_flags & O_NONBLOCK) { -+ if (!ret) -+ ret = -EAGAIN; -+ goto out; -+ } -+ -+ pr_debug("Going to wait (avail = %u, count = %zu)\n", -+ avail, count); -+ -+ up(&dac->sem); -+ schedule(); -+ if (signal_pending(current)) { -+ if (!ret) -+ ret = -ERESTARTSYS; -+ goto out_nosem; -+ } -+ down(&dac->sem); -+ } while (1); -+ -+ copied = at32dac_dma_translate_from_user(dac, buffer, count); -+ if (copied < 0) { -+ if (!ret) -+ ret = -EFAULT; -+ goto out; -+ } -+ -+ at32dac_start(dac); -+ -+ count -= copied; -+ ret += copied; -+ } -+ -+out: -+ up(&dac->sem); -+out_nosem: -+ remove_wait_queue(&dac->write_wait, &wait); -+ set_current_state(TASK_RUNNING); -+ return ret; -+} -+ -+static int at32dac_dsp_ioctl(struct inode *inode, struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ struct at32_dac *dac = file->private_data; -+ int __user *up = (int __user *)arg; -+ struct audio_buf_info abinfo; -+ int val, ret; -+ -+ switch (cmd) { -+ case OSS_GETVERSION: -+ return put_user(SOUND_VERSION, up); -+ -+ case SNDCTL_DSP_SPEED: -+ if (get_user(val, up)) -+ return -EFAULT; -+ if (val >= 0) { -+ at32dac_stop(dac); -+ ret = at32dac_set_sample_rate(dac, val); -+ if (ret) -+ return ret; -+ } -+ return put_user(dac->dsp_settings.sample_rate, up); -+ -+ case SNDCTL_DSP_STEREO: -+ if (get_user(val, up)) -+ return -EFAULT; -+ at32dac_stop(dac); -+ if (val && dac->dsp_settings.channels == 1) -+ dac->dsp_settings.input_order++; -+ else if (!val && dac->dsp_settings.channels != 1) -+ dac->dsp_settings.input_order--; -+ dac->dsp_settings.channels = val ? 2 : 1; -+ return 0; -+ -+ case SNDCTL_DSP_CHANNELS: -+ if (get_user(val, up)) -+ return -EFAULT; -+ -+ if (val) { -+ if (val < 0 || val > 2) -+ return -EINVAL; -+ -+ at32dac_stop(dac); -+ dac->dsp_settings.input_order -+ += val - dac->dsp_settings.channels; -+ dac->dsp_settings.channels = val; -+ } -+ return put_user(val, (int *)arg); -+ -+ case SNDCTL_DSP_GETFMTS: -+ return put_user(AFMT_S16_BE | AFMT_S16_BE, up); -+ -+ case SNDCTL_DSP_SETFMT: -+ if (get_user(val, up)) -+ return -EFAULT; -+ -+ if (val == AFMT_QUERY) { -+ val = dac->dsp_settings.format; -+ } else { -+ ret = at32dac_set_format(dac, val); -+ if (ret) -+ return ret; -+ } -+ return put_user(val, up); -+ -+ case SNDCTL_DSP_GETOSPACE: -+ at32dac_update_dma_tail(dac); -+ abinfo.fragsize = ((1 << dac->dsp_settings.input_order) -+ * (DMA_PERIOD_SIZE / 4)); -+ abinfo.bytes = (at32dac_dma_space(dac) -+ << dac->dsp_settings.input_order); -+ abinfo.fragstotal = ((DMA_BUFFER_SIZE * 4) -+ >> (DMA_PERIOD_SHIFT -+ + dac->dsp_settings.input_order)); -+ abinfo.fragments = ((abinfo.bytes -+ >> dac->dsp_settings.input_order) -+ / (DMA_PERIOD_SIZE / 4)); -+ pr_debug("fragments=%d fragstotal=%d fragsize=%d bytes=%d\n", -+ abinfo.fragments, abinfo.fragstotal, abinfo.fragsize, -+ abinfo.bytes); -+ return copy_to_user(up, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; -+ -+ default: -+ printk("at32dac: Unimplemented ioctl cmd: 0x%x\n", cmd); -+ return -EINVAL; -+ } -+} -+ -+static int at32dac_dsp_open(struct inode *inode, struct file *file) -+{ -+ struct at32_dac *dac = the_dac; -+ int ret; -+ -+ if (file->f_mode & FMODE_READ) -+ return -ENXIO; -+ -+ down(&dac->sem); -+ ret = -EBUSY; -+ if (dac->busy) -+ goto out; -+ -+ dac->dma.head = dac->dma.tail = 0; -+ -+ /* FIXME: What are the correct defaults? */ -+ dac->dsp_settings.channels = 2; -+ at32dac_set_format(dac, AFMT_S16_BE); -+ ret = at32dac_set_sample_rate(dac, 8000); -+ if (ret) -+ goto out; -+ -+ file->private_data = dac; -+ dac->busy = 1; -+ -+ ret = 0; -+ -+out: -+ up(&dac->sem); -+ return ret; -+} -+ -+static int at32dac_dsp_release(struct inode *inode, struct file *file) -+{ -+ struct at32_dac *dac = file->private_data; -+ -+ down(&dac->sem); -+ -+ at32dac_stop(dac); -+ at32dac_dma_cleanup(dac); -+ dac->busy = 0; -+ -+ up(&dac->sem); -+ -+ return 0; -+} -+ -+static struct file_operations at32dac_dsp_fops = { -+ .owner = THIS_MODULE, -+ .llseek = no_llseek, -+ .write = at32dac_dsp_write, -+ .ioctl = at32dac_dsp_ioctl, -+ .open = at32dac_dsp_open, -+ .release = at32dac_dsp_release, -+}; -+ -+static int __devinit at32dac_probe(struct platform_device *pdev) -+{ -+ struct at32_dac *dac; -+ struct resource *regs; -+ struct clk *mck; -+ struct clk *sample_clk; -+ int irq; -+ int ret; -+ -+ if (the_dac) -+ return -EBUSY; -+ -+ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!regs) -+ return -ENXIO; -+ irq = platform_get_irq(pdev, 0); -+ if (irq < 0) -+ return irq; -+ -+ mck = clk_get(&pdev->dev, "mck"); -+ if (IS_ERR(mck)) -+ return PTR_ERR(mck); -+ sample_clk = clk_get(&pdev->dev, "sample_clk"); -+ if (IS_ERR(sample_clk)) { -+ ret = PTR_ERR(sample_clk); -+ goto out_put_mck; -+ } -+ clk_enable(mck); -+ -+ ret = -ENOMEM; -+ dac = kzalloc(sizeof(struct at32_dac), GFP_KERNEL); -+ if (!dac) -+ goto out_disable_clk; -+ -+ spin_lock_init(&dac->lock); -+ init_MUTEX(&dac->sem); -+ init_waitqueue_head(&dac->write_wait); -+ dac->pdev = pdev; -+ dac->mck = mck; -+ dac->sample_clk = sample_clk; -+ -+ dac->regs = ioremap(regs->start, regs->end - regs->start + 1); -+ if (!dac->regs) -+ goto out_free_dac; -+ -+ ret = request_irq(irq, at32dac_interrupt, 0, "dac", dac); -+ if (ret) -+ goto out_unmap_regs; -+ -+ /* FIXME */ -+ dac->req.req.dmac = find_dma_controller(0); -+ if (!dac->req.req.dmac) -+ goto out_free_irq; -+ -+ ret = dma_alloc_channel(dac->req.req.dmac); -+ if (ret < 0) -+ goto out_free_irq; -+ -+ dac->req.req.channel = ret; -+ dac->req.req.block_complete = at32dac_dma_block_complete; -+ dac->req.req.error = at32dac_dma_error; -+ dac->req.data_reg = regs->start + DAC_DATA; -+ dac->req.periph_id = 2; /* FIXME */ -+ dac->req.direction = DMA_DIR_MEM_TO_PERIPH; -+ dac->req.width = DMA_WIDTH_32BIT; -+ -+ /* Make sure the DAC is silent and disabled */ -+ dac_writel(dac, DATA, 0); -+ dac_writel(dac, CTRL, 0); -+ -+ ret = register_sound_dsp(&at32dac_dsp_fops, -1); -+ if (ret < 0) -+ goto out_free_dma; -+ dac->dev_dsp = ret; -+ -+ /* TODO: Register mixer */ -+ -+ the_dac = dac; -+ platform_set_drvdata(pdev, dac); -+ -+ return 0; -+ -+out_free_dma: -+ dma_release_channel(dac->req.req.dmac, dac->req.req.channel); -+out_free_irq: -+ free_irq(irq, dac); -+out_unmap_regs: -+ iounmap(dac->regs); -+out_free_dac: -+ kfree(dac); -+out_disable_clk: -+ clk_disable(mck); -+ clk_put(sample_clk); -+out_put_mck: -+ clk_put(mck); -+ return ret; -+} -+ -+static int __devexit at32dac_remove(struct platform_device *pdev) -+{ -+ struct at32_dac *dac; -+ -+ dac = platform_get_drvdata(pdev); -+ if (dac) { -+ unregister_sound_dsp(dac->dev_dsp); -+ dma_release_channel(dac->req.req.dmac, dac->req.req.channel); -+ free_irq(platform_get_irq(pdev, 0), dac); -+ iounmap(dac->regs); -+ clk_disable(dac->mck); -+ clk_put(dac->sample_clk); -+ clk_put(dac->mck); -+ kfree(dac); -+ platform_set_drvdata(pdev, NULL); -+ the_dac = NULL; -+ } -+ -+ return 0; -+} -+ -+static struct platform_driver at32dac_driver = { -+ .probe = at32dac_probe, -+ .remove = __devexit_p(at32dac_remove), -+ .driver = { -+ .name = "dac", -+ }, -+}; -+ -+static int __init at32dac_init(void) -+{ -+ return platform_driver_register(&at32dac_driver); -+} -+module_init(at32dac_init); -+ -+static void __exit at32dac_exit(void) -+{ -+ platform_driver_unregister(&at32dac_driver); -+} -+module_exit(at32dac_exit); -+ -+MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>"); -+MODULE_DESCRIPTION("DMA Sound Driver for the Atmel AT32 on-chip DAC"); -+MODULE_LICENSE("GPL"); -diff -urN linux-2.6.20.4-0rig/sound/oss/at32dac.h linux-2.6.20.4-atmel/sound/oss/at32dac.h ---- linux-2.6.20.4-0rig/sound/oss/at32dac.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.20.4-atmel/sound/oss/at32dac.h 2007-03-24 16:42:29.000000000 +0100 -@@ -0,0 +1,65 @@ -+/* -+ * Register definitions for the Atmel AT32 on-chip DAC. -+ * -+ * 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_DAC_H__ -+#define __ASM_AVR32_DAC_H__ -+ -+/* DAC register offsets */ -+#define DAC_DATA 0x0000 -+#define DAC_CTRL 0x0008 -+#define DAC_INT_MASK 0x000c -+#define DAC_INT_EN 0x0010 -+#define DAC_INT_DIS 0x0014 -+#define DAC_INT_CLR 0x0018 -+#define DAC_INT_STATUS 0x001c -+#define DAC_PDC_DATA 0x0020 -+ -+/* Bitfields in DATA */ -+#define DAC_DATA_OFFSET 0 -+#define DAC_DATA_SIZE 32 -+ -+/* Bitfields in CTRL */ -+#define DAC_SWAP_OFFSET 30 -+#define DAC_SWAP_SIZE 1 -+#define DAC_EN_OFFSET 31 -+#define DAC_EN_SIZE 1 -+ -+/* Bitfields in INT_MASK */ -+ -+/* Bitfields in INT_EN */ -+ -+/* Bitfields in INT_DIS */ -+#define DAC_TX_READY_OFFSET 29 -+#define DAC_TX_READY_SIZE 1 -+#define DAC_TX_BUFFER_EMPTY_OFFSET 30 -+#define DAC_TX_BUFFER_EMPTY_SIZE 1 -+#define DAC_CHANNEL_TX_END_OFFSET 31 -+#define DAC_CHANNEL_TX_END_SIZE 1 -+ -+/* Bitfields in INT_CLR */ -+#define DAC_UNDERRUN_OFFSET 28 -+#define DAC_UNDERRUN_SIZE 1 -+ -+/* Bitfields in INT_STATUS */ -+ -+/* Bitfields in PDC_DATA */ -+ -+/* Bit manipulation macros */ -+#define DAC_BIT(name) (1 << DAC_##name##_OFFSET) -+#define DAC_BF(name,value) (((value) & ((1 << DAC_##name##_SIZE) - 1)) << DAC_##name##_OFFSET) -+#define DAC_BFEXT(name,value) (((value) >> DAC_##name##_OFFSET) & ((1 << DAC_##name##_SIZE) - 1)) -+#define DAC_BFINS(name,value,old) (((old) & ~(((1 << DAC_##name##_SIZE) - 1) << DAC_##name##_OFFSET)) | DAC_BF(name,value)) -+ -+/* Register access macros */ -+#define dac_readl(port,reg) \ -+ __raw_readl((port)->regs + DAC_##reg) -+#define dac_writel(port,reg,value) \ -+ __raw_writel((value), (port)->regs + DAC_##reg) -+ -+#endif /* __ASM_AVR32_DAC_H__ */ -diff -urN linux-2.6.20.4-0rig/sound/oss/Kconfig linux-2.6.20.4-atmel/sound/oss/Kconfig ---- linux-2.6.20.4-0rig/sound/oss/Kconfig 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/sound/oss/Kconfig 2007-03-24 16:42:29.000000000 +0100 -@@ -750,3 +750,7 @@ - int "DAC channel" - default "1" - depends on SOUND_SH_DAC_AUDIO -+ -+config SOUND_AT32_DAC -+ tristate "Atmel AT32 On-chip DAC support" -+ depends on SOUND_PRIME && AVR32 -diff -urN linux-2.6.20.4-0rig/sound/oss/Makefile linux-2.6.20.4-atmel/sound/oss/Makefile ---- linux-2.6.20.4-0rig/sound/oss/Makefile 2007-03-23 20:52:51.000000000 +0100 -+++ linux-2.6.20.4-atmel/sound/oss/Makefile 2007-03-24 16:42:29.000000000 +0100 -@@ -10,6 +10,7 @@ - - # Please leave it as is, cause the link order is significant ! - -+obj-$(CONFIG_SOUND_AT32_DAC) += at32dac.o - obj-$(CONFIG_SOUND_SH_DAC_AUDIO) += sh_dac_audio.o - obj-$(CONFIG_SOUND_HAL2) += hal2.o - obj-$(CONFIG_SOUND_AEDSP16) += aedsp16.o diff --git a/target/device/Atmel/Linux/kernel-patches-2.6.21.1/2.6.21.1-at91.patch b/target/device/Atmel/arch-arm/kernel-patches-2.6.21.1/2.6.21.1-at91.patch index 90e7dfd51..90e7dfd51 100644 --- a/target/device/Atmel/Linux/kernel-patches-2.6.21.1/2.6.21.1-at91.patch +++ b/target/device/Atmel/arch-arm/kernel-patches-2.6.21.1/2.6.21.1-at91.patch diff --git a/target/device/Atmel/Linux/kernel-patches-2.6.21.1/linux-2.6.21.1-at91-1-update.patch b/target/device/Atmel/arch-arm/kernel-patches-2.6.21.1/linux-2.6.21.1-at91-1-update.patch index 7809c2463..7809c2463 100644 --- a/target/device/Atmel/Linux/kernel-patches-2.6.21.1/linux-2.6.21.1-at91-1-update.patch +++ b/target/device/Atmel/arch-arm/kernel-patches-2.6.21.1/linux-2.6.21.1-at91-1-update.patch |