]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge mainline v2.6.27-rc2 tree into linux-omap tree
authorTony Lindgren <tony@atomide.com>
Mon, 11 Aug 2008 14:16:24 +0000 (17:16 +0300)
committerTony Lindgren <tony@atomide.com>
Mon, 11 Aug 2008 14:16:24 +0000 (17:16 +0300)
Merge branch 'master'; commit 'linus'

Conflicts:

arch/arm/mach-omap1/board-nokia770.c
arch/arm/mach-omap1/mcbsp.c
arch/arm/mach-omap2/Makefile
arch/arm/mach-omap2/board-apollon.c
arch/arm/mach-omap2/clock.c
arch/arm/mach-omap2/clock.h
arch/arm/mach-omap2/clock24xx.c
arch/arm/mach-omap2/clock24xx.h
arch/arm/mach-omap2/clock34xx.c
arch/arm/mach-omap2/clock34xx.h
arch/arm/mach-omap2/id.c
arch/arm/mach-omap2/mcbsp.c
arch/arm/mach-omap2/memory.c
arch/arm/mach-omap2/pm.c
arch/arm/mach-omap2/prm.h
arch/arm/mach-omap2/sram242x.S
arch/arm/mach-omap2/sram243x.S
arch/arm/plat-omap/common.c
arch/arm/plat-omap/devices.c
arch/arm/plat-omap/mcbsp.c
arch/arm/plat-omap/sram.c
drivers/i2c/busses/Kconfig
drivers/i2c/chips/isp1301_omap.c
drivers/input/touchscreen/Kconfig
drivers/misc/Makefile
drivers/mtd/nand/Makefile
drivers/net/Kconfig
drivers/net/smc911x.h
drivers/power/Kconfig
drivers/power/Makefile
drivers/usb/gadget/omap_udc.c
include/asm-arm/arch-omap/board-2430sdp.h
include/asm-arm/arch-omap/board.h
include/asm-arm/arch-omap/clock.h
include/asm-arm/arch-omap/common.h
include/asm-arm/arch-omap/hardware.h
include/asm-arm/arch-omap/io.h
include/asm-arm/arch-omap/mcbsp.h
include/asm-arm/arch-omap/omap34xx.h
include/asm-arm/arch-omap/sram.h
include/asm-arm/cpu-multi32.h
include/asm-arm/pgtable.h
include/asm-arm/setup.h
include/linux/i2c-id.h
kernel/printk.c
security/Makefile
sound/arm/Kconfig

71 files changed:
1  2 
MAINTAINERS
Makefile
arch/arm/Kconfig
arch/arm/Makefile
arch/arm/boot/compressed/Makefile
arch/arm/boot/compressed/head.S
arch/arm/include/asm/pgtable.h
arch/arm/include/asm/setup.h
arch/arm/mach-omap1/board-nokia770.c
arch/arm/mach-omap1/board-voiceblue.c
arch/arm/mach-omap2/board-n800.c
arch/arm/mm/Kconfig
arch/arm/plat-omap/gpio-switch.c
drivers/Makefile
drivers/bluetooth/Kconfig
drivers/bluetooth/brf6150.c
drivers/cbus/retu.c
drivers/cbus/tahvo.c
drivers/crypto/Kconfig
drivers/crypto/Makefile
drivers/dsp/dspgateway/task.c
drivers/hwmon/Kconfig
drivers/i2c/busses/Kconfig
drivers/i2c/busses/Makefile
drivers/i2c/chips/Kconfig
drivers/i2c/chips/Makefile
drivers/i2c/chips/twl4030-core.c
drivers/input/keyboard/tsc2301_kp.c
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/Makefile
drivers/input/touchscreen/ads7846.c
drivers/leds/Kconfig
drivers/leds/Makefile
drivers/media/video/Kconfig
drivers/media/video/Makefile
drivers/media/video/omap24xxcam.c
drivers/misc/Kconfig
drivers/misc/Makefile
drivers/mmc/host/Kconfig
drivers/mmc/host/Makefile
drivers/mtd/cmdlinepart.c
drivers/mtd/nand/Kconfig
drivers/mtd/nand/Makefile
drivers/mtd/onenand/omap2.c
drivers/net/Kconfig
drivers/net/smc911x.h
drivers/net/smc91x.c
drivers/power/Kconfig
drivers/power/Makefile
drivers/rtc/Kconfig
drivers/rtc/Makefile
drivers/serial/8250.c
drivers/spi/Kconfig
drivers/spi/Makefile
drivers/usb/gadget/Kconfig
drivers/usb/gadget/omap_udc.c
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ohci-omap.c
drivers/video/backlight/Kconfig
drivers/video/omap/dispc.c
drivers/video/omap/omapfb_main.c
drivers/video/omap/sossi.c
drivers/watchdog/Kconfig
include/linux/connector.h
kernel/printk.c
net/ipv4/netfilter/Kconfig
net/ipv4/netfilter/Makefile
security/Kconfig
security/Makefile
sound/arm/Kconfig
sound/oss/Makefile

diff --combined MAINTAINERS
index f9961cec3ab7cbdc6a4199237e8031360a29d316,8223a521d7c3f2198c19d7065469b7f1484f714f..061826165034665dd82fa956ecacbb290b5bc2de
@@@ -216,8 -216,8 +216,8 @@@ W: http://code.google.com/p/aceracp
  S:    Maintained
  
  ACPI
- P:    Len Brown
- M:    len.brown@intel.com
+ P:    Andi Kleen
+ M:    ak@linux.intel.com
  M:    lenb@kernel.org
  L:    linux-acpi@vger.kernel.org
  W:    http://www.lesswatts.org/projects/acpi/
@@@ -239,8 -239,8 +239,8 @@@ W: http://www.lesswatts.org/projects/ac
  S:    Supported
  
  ACPI FAN DRIVER
- P:    Len Brown
- M:    len.brown@intel.com
+ P:    Zhang Rui
+ M:    rui.zhang@intel.com
  L:    linux-acpi@vger.kernel.org
  W:    http://www.lesswatts.org/projects/acpi/
  S:    Supported
  ACPI PCI HOTPLUG DRIVER
  P:    Kristen Carlson Accardi
  M:    kristen.c.accardi@intel.com
- L:    pcihpd-discuss@lists.sourceforge.net
+ L:    linux-pci@vger.kernel.org
  S:    Supported
  
  ACPI THERMAL DRIVER
- P:    Len Brown
- M:    len.brown@intel.com
+ P:    Zhang Rui
+ M:    rui.zhang@intel.com
  L:    linux-acpi@vger.kernel.org
  W:    http://www.lesswatts.org/projects/acpi/
  S:    Supported
  
  ACPI VIDEO DRIVER
- P:    Rui Zhang
+ P:    Zhang Rui
  M:    rui.zhang@intel.com
  L:    linux-acpi@vger.kernel.org
  W:    http://www.lesswatts.org/projects/acpi/
@@@ -348,7 -348,9 +348,9 @@@ W: http://www.linux-usb.org/SpeedTouch
  S:    Maintained
  
  ALCHEMY AU1XX0 MMC DRIVER
- S:    Orphan
+ P:    Manuel Lauss
+ M:    manuel.lauss@gmail.com
+ S:    Maintained
  
  ALI1563 I2C DRIVER
  P:    Rudolf Marek
@@@ -376,6 -378,12 +378,12 @@@ L:       linux-geode@lists.infradead.org (mod
  W:    http://www.amd.com/us-en/ConnectivitySolutions/TechnicalResources/0,,50_2334_2452_11363,00.html
  S:    Supported
  
+ AMD IOMMU (AMD-VI)
+ P:    Joerg Roedel
+ M:    joerg.roedel@amd.com
+ L:    iommu@lists.linux-foundation.org
+ S:    Supported
  AMS (Apple Motion Sensor) DRIVER
  P:    Stelian Pop
  M:    stelian@popies.net
@@@ -433,10 -441,7 +441,7 @@@ M:        spyro@f2s.co
  S:    Maintained
  
  ARM PRIMECELL MMCI PL180/1 DRIVER
- P:    Russell King
- M:    rmk@arm.linux.org.uk
- L:    linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
- S:    Maintained
+ S:    Orphan
  
  ARM/ADI ROADRUNNER MACHINE SUPPORT
  P:    Lennert Buytenhek
@@@ -475,11 -480,34 +480,34 @@@ M:      kernel@wantstofly.or
  L:    linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
  S:    Maintained
  
+ ARM/COMPULAB CM-X270/EM-X270 MACHINE SUPPORT
+ P:    Mike Rapoport
+ M:    mike@compulab.co.il
+ L:    linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+ S:    Maintained
  ARM/CORGI MACHINE SUPPORT
  P:    Richard Purdie
  M:    rpurdie@rpsys.net
  S:    Maintained
  
+ ARM/EZX SMARTPHONES (A780, A910, A1200, E680, ROKR E2 and ROKR E6)
+ P:    Daniel Ribeiro
+ M:    drwyrm@gmail.com
+ P:    Stefan Schmidt
+ M:    stefan@openezx.org
+ P:    Harald Welte
+ M:    laforge@openezx.org
+ L:    openezx-devel@lists.openezx.org (subscribers-only)
+ W:    http://www.openezx.org/
+ S:    Maintained
+ ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
+ P:    Sascha Hauer
+ M:    kernel@pengutronix.de
+ L:    linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+ S:    Maintained
  ARM/GLOMATION GESBC9312SX MACHINE SUPPORT
  P:    Lennert Buytenhek
  M:    kernel@wantstofly.org
@@@ -567,10 -595,18 +595,18 @@@ L:      linux-arm-kernel@lists.arm.linux.org
  S:    Maintained
  
  ARM/TOSA MACHINE SUPPORT
+ P:    Dmitry Baryshkov
+ M:    dbaryshkov@gmail.com
  P:    Dirk Opfer
  M:    dirk@opfer-online.de
  S:    Maintained
  
+ ARM/PALMTX SUPPORT
+ P:    Marek Vasut
+ M:    marek.vasut@gmail.com
+ W:    http://hackndev.com
+ S:    Maintained
  ARM/PLEB SUPPORT
  P:    Peter Chubb
  M:    pleb@gelato.unsw.edu.au
@@@ -1013,6 -1049,12 +1049,12 @@@ M:    fujita.tomonori@lab.ntt.co.j
  L:    linux-scsi@vger.kernel.org
  S:    Supported
  
+ BT8XXGPIO DRIVER
+ P:    Michael Buesch
+ M:    mb@bu3sch.de
+ W:    http://bu3sch.de/btgpio.php
+ S:    Maintained
  BTTV VIDEO4LINUX DRIVER
  P:    Mauro Carvalho Chehab
  M:    mchehab@infradead.org
@@@ -1137,23 -1179,28 +1179,28 @@@ COMPACTPCI HOTPLUG COR
  P:    Scott Murray
  M:    scottm@somanetworks.com
  M:    scott@spiteful.org
- L:    pcihpd-discuss@lists.sourceforge.net
+ L:    linux-pci@vger.kernel.org
  S:    Supported
  
  COMPACTPCI HOTPLUG ZIATECH ZT5550 DRIVER
  P:    Scott Murray
  M:    scottm@somanetworks.com
  M:    scott@spiteful.org
- L:    pcihpd-discuss@lists.sourceforge.net
+ L:    linux-pci@vger.kernel.org
  S:    Supported
  
  COMPACTPCI HOTPLUG GENERIC DRIVER
  P:    Scott Murray
  M:    scottm@somanetworks.com
  M:    scott@spiteful.org
- L:    pcihpd-discuss@lists.sourceforge.net
+ L:    linux-pci@vger.kernel.org
  S:    Supported
  
+ COMPAL LAPTOP SUPPORT
+ P:    Cezary Jackiewicz
+ M:    cezary.jackiewicz@gmail.com
+ S:    Maintained
  COMPUTONE INTELLIPORT MULTIPORT CARD
  P:    Michael H. Warfield
  M:    mhw@wittsend.com
@@@ -1680,6 -1727,13 +1727,13 @@@ L:    linuxppc-embedded@ozlabs.or
  L:    linux-kernel@vger.kernel.org
  S:    Maintained
  
+ FREESCALE I2C CPM DRIVER
+ P:    Jochen Friedrich
+ M:    jochen@scram.de
+ L:    linuxppc-dev@ozlabs.org
+ L:    i2c@lm-sensors.org
+ S:    Maintained
  FREESCALE SOC FS_ENET DRIVER
  P:    Pantelis Antoniou
  M:    pantelis.antoniou@gmail.com
@@@ -1764,11 -1818,22 +1818,22 @@@ M:   hch@infradead.or
  W:    ftp://ftp.openlinux.org/pub/people/hch/vxfs
  S:    Maintained
  
+ FTRACE
+ P:    Steven Rostedt
+ M:    srostedt@redhat.com
+ S:    Maintained
  FUJITSU FR-V (FRV) PORT
  P:    David Howells
  M:    dhowells@redhat.com
  S:    Maintained
  
+ FUJITSU LAPTOP EXTRAS
+ P:    Jonathan Woithe
+ M:    jwoithe@physics.adelaide.edu.au
+ L:    linux-acpi@vger.kernel.org
+ S:    Maintained
  FUSE: FILESYSTEM IN USERSPACE
  P:    Miklos Szeredi
  M:    miklos@szeredi.hu
@@@ -1819,13 -1884,9 +1884,9 @@@ W:     http://gigaset307x.sourceforge.net
  S:    Maintained
  
  HARDWARE MONITORING
- P:    Mark M. Hoffman
- M:    mhoffman@lightlink.com
  L:    lm-sensors@lm-sensors.org
  W:    http://www.lm-sensors.org/
- T:    git lm-sensors.org:/kernel/mhoffman/hwmon-2.6.git testing
- T:    git lm-sensors.org:/kernel/mhoffman/hwmon-2.6.git release
- S:    Maintained
+ S:    Orphaned
  
  HARDWARE RANDOM NUMBER GENERATOR CORE
  S:    Orphaned
@@@ -1931,7 -1992,7 +1992,7 @@@ P:      Carlos Corbach
  M:    carlos@strangeworlds.co.uk
  S:    Odd Fixes
  
- HPET: High Precision Event Timers driver (hpet.c)
+ HPET: High Precision Event Timers driver (drivers/char/hpet.c)
  P:    Clemens Ladisch
  M:    clemens@ladisch.de
  S:    Maintained
@@@ -1957,6 -2018,12 +2018,12 @@@ M:    mikulas@artax.karlin.mff.cuni.c
  W:    http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi
  S:    Maintained
  
+ HTCPEN TOUCHSCREEN DRIVER
+ P:    Pau Oliva Fora
+ M:    pof@eslack.org
+ L:    linux-input@vger.kernel.org
+ S:    Maintained
  HUGETLB FILESYSTEM
  P:    William Irwin
  M:    wli@holomorphy.com
@@@ -2158,6 -2225,8 +2225,8 @@@ P:      Jesse Brandebur
  M:    jesse.brandeburg@intel.com
  P:    Bruce Allan
  M:    bruce.w.allan@intel.com
+ P:    PJ Waskiewicz
+ M:    peter.p.waskiewicz.jr@intel.com
  P:    John Ronciak
  M:    john.ronciak@intel.com
  L:    e1000-devel@lists.sourceforge.net
@@@ -2307,6 -2376,16 +2376,16 @@@ L:    linux-mtd@lists.infradead.or
  W:    http://www.linux-mtd.infradead.org/doc/jffs2.html
  S:    Maintained
  
+ UBI FILE SYSTEM (UBIFS)
+ P:    Artem Bityutskiy
+ M:    dedekind@infradead.org
+ P:    Adrian Hunter
+ M:    ext-adrian.hunter@nokia.com
+ L:    linux-mtd@lists.infradead.org
+ T:    git git://git.infradead.org/~dedekind/ubifs-2.6.git
+ W:    http://www.linux-mtd.infradead.org/doc/ubifs.html
+ S:    Maintained
  JFS FILESYSTEM
  P:    Dave Kleikamp
  M:    shaggy@austin.ibm.com
@@@ -2503,13 -2582,11 +2582,11 @@@ W:   http://www.penguinppc.org
  L:    linuxppc-dev@ozlabs.org
  S:    Maintained
  
- LINUX FOR POWERPC EMBEDDED MPC52XX
+ LINUX FOR POWERPC EMBEDDED MPC5XXX
  P:    Sylvain Munaut
  M:    tnt@246tNt.com
  P:    Grant Likely
  M:    grant.likely@secretlab.ca
- W:    http://www.246tNt.com/mpc52xx/
- W:    http://www.penguinppc.org/
  L:    linuxppc-dev@ozlabs.org
  S:    Maintained
  
@@@ -2686,12 -2763,10 +2763,10 @@@ L:   libertas-dev@lists.infradead.or
  S:    Maintained
  
  MARVELL MV643XX ETHERNET DRIVER
- P:    Dale Farnsworth
- M:    dale@farnsworth.org
- P:    Manish Lachwani
- M:    mlachwani@mvista.com
+ P:    Lennert Buytenhek
+ M:    buytenh@marvell.com
  L:    netdev@vger.kernel.org
- S:    Odd Fixes for 2.4; Maintained for 2.6.
+ S:    Supported
  
  MATROX FRAMEBUFFER DRIVER
  P:    Petr Vandrovec
@@@ -2870,8 -2945,6 +2945,6 @@@ P:      Faisal Lati
  M:    flatif@neteffect.com
  P:    Chien Tung
  M:    ctung@neteffect.com
- P:    Glenn Streiff
- M:    gstreiff@neteffect.com
  L:    general@lists.openfabrics.org
  W:    http://www.neteffect.com
  S:    Supported
@@@ -3052,6 -3125,12 +3125,12 @@@ W:    http://oss.oracle.com/projects/ocfs2
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/mfasheh/ocfs2.git
  S:    Supported
  
+ OMFS FILESYSTEM
+ P:    Bob Copeland
+ M:    me@bobcopeland.com
+ L:    linux-karma-devel@lists.sourceforge.net
+ S:    Maintained
  OMNIKEY CARDMAN 4000 DRIVER
  P:    Harald Welte
  M:    laforge@gnumonks.org
@@@ -3180,7 -3259,7 +3259,7 @@@ S:      Supporte
  PCIE HOTPLUG DRIVER
  P:    Kristen Carlson Accardi
  M:    kristen.c.accardi@intel.com
- L:    pcihpd-discuss@lists.sourceforge.net
+ L:    linux-pci@vger.kernel.org
  S:    Supported
  
  PCMCIA SUBSYSTEM
@@@ -3235,14 -3314,6 +3314,6 @@@ L:     linux-kernel@vger.kernel.or
  T:    git git.infradead.org/battery-2.6.git
  S:    Maintained
  
- POWERPC 4xx EMAC DRIVER
- P:    Eugene Surovegin
- M:    ebs@ebshome.net
- W:    http://kernel.ebshome.net/emac/
- L:    linuxppc-dev@ozlabs.org
- L:    netdev@vger.kernel.org
- S:    Maintained
  PNP SUPPORT
  P:    Adam Belay
  M:    ambx1@neo.rr.com
@@@ -3496,7 -3567,7 +3567,7 @@@ S:      Supporte
  
  S390 NETWORK DRIVERS
  P:    Ursula Braun
- M:    ubraun@linux.vnet.ibm.com
+ M:    ursula.braun@de.ibm.com
  P:    Frank Blaschka
  M:    blaschka@linux.vnet.ibm.com
  M:    linux390@de.ibm.com
@@@ -3516,12 -3587,19 +3587,19 @@@ S:   Supporte
  
  S390 IUCV NETWORK LAYER
  P:    Ursula Braun
- M:    ubraun@linux.vnet.ibm.com
+ M:    ursula.braun@de.ibm.com
  M:    linux390@de.ibm.com
  L:    linux-s390@vger.kernel.org
  W:    http://www.ibm.com/developerworks/linux/linux390/
  S:    Supported
  
+ S3C24XX SD/MMC Driver
+ P:    Ben Dooks
+ M:    ben-linux@fluff.org
+ L:    linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+ L:    linux-kernel@vger.kernel.org
+ S:    Supported
  SAA7146 VIDEO4LINUX-2 DRIVER
  P:    Michael Hunold
  M:    michael@mihu.de
@@@ -3594,6 -3672,12 +3672,12 @@@ P:    Jim Cromi
  M:    jim.cromie@gmail.com
  S:    Maintained
  
+ SDRICOH_CS MMC/SD HOST CONTROLLER INTERFACE DRIVER
+ P:    Sascha Sommer
+ M:    saschasommer@freenet.de
+ L:    sdricohcs-devel@lists.sourceforge.net (subscribers-only)
+ S:    Maintained
  SECURITY CONTACT
  P:    Security Officers
  M:    security@kernel.org
@@@ -3714,6 -3798,12 +3798,12 @@@ P:    Ben Nizett
  M:    bn@niasdigital.com
  S:    Maintained
  
+ SOC-CAMERA V4L2 SUBSYSTEM
+ P:     Guennadi Liakhovetski
+ M:     g.liakhovetski@gmx.de
+ L:     video4linux-list@redhat.com
+ S:     Maintained
  SOFTWARE RAID (Multiple Disks) SUPPORT
  P:    Ingo Molnar
  M:    mingo@redhat.com
@@@ -3813,7 -3903,7 +3903,7 @@@ S:      Maintaine
  SHPC HOTPLUG DRIVER
  P:    Kristen Carlson Accardi
  M:    kristen.c.accardi@intel.com
- L:    pcihpd-discuss@lists.sourceforge.net
+ L:    linux-pci@vger.kernel.org
  S:    Supported
  
  SECURE DIGITAL HOST CONTROLLER INTERFACE DRIVER
@@@ -3880,7 -3970,7 +3970,7 @@@ M:      lethal@linux-sh.or
  L:    linux-sh@vger.kernel.org
  W:    http://www.linux-sh.org
  T:    git kernel.org:/pub/scm/linux/kernel/git/lethal/sh-2.6.git
- S:    Maintained
+ S:    Supported
  
  SUN3/3X
  P:    Sam Creasey
@@@ -3953,7 -4043,7 +4043,7 @@@ S:      Maintaine
  
  TI OMAP MMC INTERFACE DRIVER
  P:    Carlos Aguiar, Anderson Briglia and Syed Khasim
 -M:    linux-omap-open-source@linux.omap.com (subscribers only)
 +M:    linux-omap@vger.kernel.org
  W:    http://linux.omap.com
  W:    http://www.muru.com/linux/omap/
  S:    Maintained
@@@ -3997,9 -4087,10 +4087,10 @@@ W:    http://www.buzzard.org.uk/toshiba
  S:    Maintained
  
  TPM DEVICE DRIVER
- P:     Debora Velarde
- P:     Rajiv Andrade
- M:    tpmdd-devel@lists.sourceforge.net
+ P:    Debora Velarde
+ M:    debora@linux.vnet.ibm.com
+ P:    Rajiv Andrade
+ M:    srajiv@linux.vnet.ibm.com
  W:    http://tpmdd.sourceforge.net
  P:    Marcel Selhorst
  M:    tpm@selhorst.net
@@@ -4007,12 -4098,6 +4098,6 @@@ W:     http://www.prosec.rub.de/tpm
  L:    tpmdd-devel@lists.sourceforge.net
  S:    Maintained
  
- TRIDENT 4DWAVE/SIS 7018 PCI AUDIO CORE
- P:    Muli Ben-Yehuda
- M:    mulix@mulix.org
- L:    linux-kernel@vger.kernel.org
- S:    Maintained
  TRIVIAL PATCHES
  P:    Jesper Juhl
  M:    trivial@kernel.org
@@@ -4058,9 -4143,6 +4143,6 @@@ W:      http://www.uclinux.org
  L:    uclinux-dev@uclinux.org  (subscribers-only)
  S:    Maintained
  
- UCLINUX FOR NEC V850
- P:    Miles Bader
  UCLINUX FOR RENESAS H8/300
  P:    Yoshinori Sato
  M:    ysato@users.sourceforge.jp
@@@ -4424,6 -4506,15 +4506,15 @@@ M:    kaber@trash.ne
  L:    netdev@vger.kernel.org
  S:    Maintained
  
+ VOLTAGE AND CURRENT REGULATOR FRAMEWORK
+ P:    Liam Girdwood
+ M:    lg@opensource.wolfsonmicro.com
+ P:    Mark Brown
+ M:    broonie@opensource.wolfsonmicro.com
+ W:    http://opensource.wolfsonmicro.com/node/15
+ T:    git kernel.org/pub/scm/linux/kernel/git/lrg/voltage-2.6.git
+ S:    Supported
  VT1211 HARDWARE MONITOR DRIVER
  P:    Juerg Haefliger
  M:    juergh@gmail.com
diff --combined Makefile
index 739a4c7cd2a998c38e83d382bf92cf81a89230cd,ea413fa03e4e84868591048e6191be19031f6176..e6c886038cf38bb960263aecc7b5237f530d37a9
+++ b/Makefile
@@@ -1,7 -1,7 +1,7 @@@
  VERSION = 2
  PATCHLEVEL = 6
- SUBLEVEL = 26
- EXTRAVERSION =
+ SUBLEVEL = 27
+ EXTRAVERSION = -rc2
  NAME = Rotary Wombat
  
  # *DOCUMENTATION*
@@@ -16,9 -16,6 +16,9 @@@
  # o  print "Entering directory ...";
  MAKEFLAGS += -rR --no-print-directory
  
 +# Add custom flags here to avoid conflict with updates
 +EXTRAVERSION := $(EXTRAVERSION)-omap1
 +
  # We are using a recursive build, so we need to do a little thinking
  # to get the ordering right.
  #
@@@ -174,8 -171,6 +174,8 @@@ SUBARCH := $(shell uname -m | sed -e s/
                                  -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
                                  -e s/sh.*/sh/ )
  
 +SUBARCH := arm
 +
  # Cross compiling and selecting different set of gcc/bin-utils
  # ---------------------------------------------------------------------------
  #
  # Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile
  export KBUILD_BUILDHOST := $(SUBARCH)
  ARCH          ?= $(SUBARCH)
 -CROSS_COMPILE ?=
 +CROSS_COMPILE ?= arm-linux-
  
  # Architecture as present in compile.h
  UTS_MACHINE   := $(ARCH)
@@@ -210,6 -205,13 +210,13 @@@ ifeq ($(ARCH),x86_64
          SRCARCH := x86
  endif
  
+ # Where to locate arch specific headers
+ ifeq ($(ARCH),sparc64)
+        hdr-arch  := sparc
+ else
+        hdr-arch  := $(SRCARCH)
+ endif
  KCONFIG_CONFIG        ?= .config
  
  # SHELL used by kbuild
@@@ -331,7 -333,8 +338,8 @@@ AFLAGS_KERNEL      
  # Needed to be compatible with the O= option
  LINUXINCLUDE    := -Iinclude \
                     $(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include) \
-                  -include include/linux/autoconf.h
+                    -I$(srctree)/arch/$(hdr-arch)/include               \
+                    -include include/linux/autoconf.h
  
  KBUILD_CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE)
  
@@@ -455,7 -458,7 +463,7 @@@ scripts: scripts_basic include/config/a
  
  # Objects we will link into vmlinux / subdirs we need to visit
  init-y                := init/
- drivers-y     := drivers/ sound/
+ drivers-y     := drivers/ sound/ firmware/
  net-y         := net/
  libs-y                := lib/
  core-y                := usr/
@@@ -512,6 -515,8 +520,8 @@@ els
  KBUILD_CFLAGS += -O2
  endif
  
+ include $(srctree)/arch/$(SRCARCH)/Makefile
  ifneq (CONFIG_FRAME_WARN,0)
  KBUILD_CFLAGS += $(call cc-option,-Wframe-larger-than=${CONFIG_FRAME_WARN})
  endif
  # Arch Makefiles may override this setting
  KBUILD_CFLAGS += $(call cc-option, -fno-stack-protector)
  
- include $(srctree)/arch/$(SRCARCH)/Makefile
  ifdef CONFIG_FRAME_POINTER
  KBUILD_CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls
  else
@@@ -533,6 -536,10 +541,10 @@@ KBUILD_CFLAGS    += -
  KBUILD_AFLAGS += -gdwarf-2
  endif
  
+ ifdef CONFIG_FTRACE
+ KBUILD_CFLAGS += -pg
+ endif
  # We trigger additional mismatches with less inlining
  ifdef CONFIG_DEBUG_SECTION_MISMATCH
  KBUILD_CFLAGS += $(call cc-option, -fno-inline-functions-called-once)
@@@ -923,7 -930,9 +935,9 @@@ ifneq ($(KBUILD_SRC),
                /bin/false; \
        fi;
        $(Q)if [ ! -d include2 ]; then mkdir -p include2; fi;
-       $(Q)ln -fsn $(srctree)/include/asm-$(SRCARCH) include2/asm
+       $(Q)if [ -e $(srctree)/include/asm-$(SRCARCH)/errno.h ]; then  \
+           ln -fsn $(srctree)/include/asm-$(SRCARCH) include2/asm;     \
+           fi
  endif
  
  # prepare2 creates a makefile if using a separate output directory
@@@ -949,22 -958,34 +963,34 @@@ export CPPFLAGS_vmlinux.lds += -P -C -U
  
  # The asm symlink changes when $(ARCH) changes.
  # Detect this and ask user to run make mrproper
- include/asm: FORCE
-       $(Q)set -e; asmlink=`readlink include/asm | cut -d '-' -f 2`;   \
-       if [ -L include/asm ]; then                                     \
-               if [ "$$asmlink" != "$(SRCARCH)" ]; then                \
+ define check-symlink
+       set -e;                                                            \
+       if [ -L include/asm ]; then                                        \
+               asmlink=`readlink include/asm | cut -d '-' -f 2`;          \
+               if [ "$$asmlink" != "$(SRCARCH)" ]; then                   \
                        echo "ERROR: the symlink $@ points to asm-$$asmlink but asm-$(SRCARCH) was expected"; \
                        echo "       set ARCH or save .config and run 'make mrproper' to fix it";             \
-                       exit 1;                                         \
-               fi;                                                     \
-       else                                                            \
-               echo '  SYMLINK $@ -> include/asm-$(SRCARCH)';          \
-               if [ ! -d include ]; then                               \
-                       mkdir -p include;                               \
-               fi;                                                     \
-               ln -fsn asm-$(SRCARCH) $@;                              \
+                       exit 1;                                            \
+               fi;                                                        \
        fi
+ endef
+ # We create the target directory of the symlink if it does
+ # not exist so the test in chack-symlink works and we have a
+ # directory for generated filesas used by some architectures.
+ define create-symlink
+       if [ ! -L include/asm ]; then                                      \
+                       echo '  SYMLINK $@ -> include/asm-$(SRCARCH)';     \
+                       if [ ! -d include/asm-$(SRCARCH) ]; then           \
+                               mkdir -p include/asm-$(SRCARCH);           \
+                       fi;                                                \
+                       ln -fsn asm-$(SRCARCH) $@;                         \
+       fi
+ endef
+ include/asm: FORCE
+       $(Q)$(check-symlink)
+       $(Q)$(create-symlink)
  
  # Generate some files
  # ---------------------------------------------------------------------------
@@@ -999,38 -1020,55 +1025,55 @@@ PHONY += depend de
  depend dep:
        @echo '*** Warning: make $@ is unnecessary now.'
  
+ # ---------------------------------------------------------------------------
+ # Firmware install
+ INSTALL_FW_PATH=$(INSTALL_MOD_PATH)/lib/firmware
+ export INSTALL_FW_PATH
+ PHONY += firmware_install
+ firmware_install: FORCE
+       @mkdir -p $(objtree)/firmware
+       $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_install
  # ---------------------------------------------------------------------------
  # Kernel headers
- INSTALL_HDR_PATH=$(objtree)/usr
- export INSTALL_HDR_PATH
  
- HDRFILTER=generic i386 x86_64
- HDRARCHES=$(filter-out $(HDRFILTER),$(patsubst $(srctree)/include/asm-%/Kbuild,%,$(wildcard $(srctree)/include/asm-*/Kbuild)))
+ #Default location for installed headers
+ export INSTALL_HDR_PATH = $(objtree)/usr
  
- PHONY += headers_install_all
- headers_install_all: include/linux/version.h scripts_basic FORCE
+ hdr-inst := -rR -f $(srctree)/scripts/Makefile.headersinst obj
+ # Find out where the Kbuild file is located to support
+ # arch/$(ARCH)/include/asm
+ hdr-dir = $(strip                                                         \
+           $(if $(wildcard $(srctree)/arch/$(hdr-arch)/include/asm/Kbuild), \
+                arch/$(hdr-arch)/include/asm, include/asm-$(hdr-arch)))
+ # If we do an all arch process set dst to asm-$(hdr-arch)
+ hdr-dst = $(if $(KBUILD_HEADERS), dst=include/asm-$(hdr-arch), dst=include/asm)
+ PHONY += __headers
+ __headers: include/linux/version.h scripts_basic FORCE
        $(Q)$(MAKE) $(build)=scripts scripts/unifdef
-       $(Q)for arch in $(HDRARCHES); do \
-        $(MAKE) ARCH=$$arch -f $(srctree)/scripts/Makefile.headersinst obj=include BIASMDIR=-bi-$$arch ;\
-        done
+ PHONY += headers_install_all
+ headers_install_all:
+       $(Q)$(CONFIG_SHELL) $(srctree)/scripts/headers.sh install
  
  PHONY += headers_install
- headers_install: include/linux/version.h scripts_basic FORCE
-       @if [ ! -r $(srctree)/include/asm-$(SRCARCH)/Kbuild ]; then \
-         echo '*** Error: Headers not exportable for this architecture ($(SRCARCH))'; \
-         exit 1 ; fi
-       $(Q)$(MAKE) $(build)=scripts scripts/unifdef
-       $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.headersinst ARCH=$(SRCARCH) obj=include
+ headers_install: __headers
+       $(if $(wildcard $(srctree)/$(hdr-dir)/Kbuild),, \
+       $(error Headers not exportable for the $(SRCARCH) architecture))
+       $(Q)$(MAKE) $(hdr-inst)=include
+       $(Q)$(MAKE) $(hdr-inst)=$(hdr-dir) $(hdr-dst)
  
  PHONY += headers_check_all
  headers_check_all: headers_install_all
-       $(Q)for arch in $(HDRARCHES); do \
-        $(MAKE) ARCH=$$arch -f $(srctree)/scripts/Makefile.headersinst obj=include BIASMDIR=-bi-$$arch HDRCHECK=1 ;\
-        done
+       $(Q)$(CONFIG_SHELL) $(srctree)/scripts/headers.sh check
  
  PHONY += headers_check
  headers_check: headers_install
-       $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.headersinst ARCH=$(SRCARCH) obj=include HDRCHECK=1
+       $(Q)$(MAKE) $(hdr-inst)=include HDRCHECK=1
+       $(Q)$(MAKE) $(hdr-inst)=$(hdr-dir) $(hdr-dst) HDRCHECK=1
  
  # ---------------------------------------------------------------------------
  # Modules
@@@ -1052,6 -1090,7 +1095,7 @@@ modules: $(vmlinux-dirs) $(if $(KBUILD_
        $(Q)$(AWK) '!x[$$0]++' $(vmlinux-dirs:%=$(objtree)/%/modules.order) > $(objtree)/modules.order
        @echo '  Building modules, stage 2.';
        $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
+       $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_modbuild
  
  
  # Target to prepare building external modules
@@@ -1085,6 -1124,7 +1129,7 @@@ _modinst_
  # boot script depmod is the master version.
  PHONY += _modinst_post
  _modinst_post: _modinst_
+       $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_modinst
        $(call cmd,depmod)
  
  else # CONFIG_MODULES
@@@ -1120,7 -1160,7 +1165,7 @@@ MRPROPER_FILES += .config .config.old i
                    include/linux/autoconf.h include/linux/version.h      \
                    include/linux/utsrelease.h                            \
                    include/linux/bounds.h include/asm*/asm-offsets.h     \
-                 Module.symvers tags TAGS cscope*
+                 Module.symvers Module.markers tags TAGS cscope*
  
  # clean - Delete most, but leave enough to build external modules
  #
@@@ -1138,7 -1178,8 +1183,8 @@@ clean: archclean $(clean-dirs
        @find . $(RCS_FIND_IGNORE) \
                \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
                -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
-               -o -name '*.symtypes' -o -name 'modules.order' \) \
+               -o -name '*.symtypes' -o -name 'modules.order' \
+               -o -name 'Module.markers' -o -name '.tmp_*.o.*' \) \
                -type f -print | xargs rm -f
  
  # mrproper - Delete all generated files, including .config
@@@ -1202,6 -1243,8 +1248,8 @@@ help
        @echo  '* vmlinux         - Build the bare kernel'
        @echo  '* modules         - Build all modules'
        @echo  '  modules_install - Install all modules to INSTALL_MOD_PATH (default: /)'
+       @echo  '  firmware_install- Install all firmware to INSTALL_FW_PATH'
+       @echo  '                    (default: $$(INSTALL_MOD_PATH)/lib/firmware)'
        @echo  '  dir/            - Build all files in dir and below'
        @echo  '  dir/file.[ois]  - Build specified target only'
        @echo  '  dir/file.ko     - Build module including final link'
        @echo  '  cscope          - Generate cscope index'
        @echo  '  kernelrelease   - Output the release version string'
        @echo  '  kernelversion   - Output the version stored in Makefile'
-       @if [ -r $(srctree)/include/asm-$(SRCARCH)/Kbuild ]; then \
-        echo  '  headers_install - Install sanitised kernel headers to INSTALL_HDR_PATH'; \
+       @echo  '  headers_install - Install sanitised kernel headers to INSTALL_HDR_PATH'; \
         echo  '                    (default: $(INSTALL_HDR_PATH))'; \
-        fi
-       @echo  ''
+        echo  ''
        @echo  'Static analysers'
        @echo  '  checkstack      - Generate a list of stack hogs'
        @echo  '  namespacecheck  - Name space analysis on compiled kernel'
        @echo  '  versioncheck    - Sanity check on version.h usage'
        @echo  '  includecheck    - Check for duplicate included header files'
        @echo  '  export_report   - List the usages of all exported symbols'
-       @if [ -r $(srctree)/include/asm-$(SRCARCH)/Kbuild ]; then \
-        echo  '  headers_check   - Sanity check on exported headers'; \
-        fi
-       @echo  ''
+       @echo  '  headers_check   - Sanity check on exported headers'; \
+        echo  ''
        @echo  'Kernel packaging:'
        @$(MAKE) $(build)=$(package-dir) help
        @echo  ''
@@@ -1397,7 -1436,11 +1441,11 @@@ define find-source
               \( -name config -o -name 'asm-*' \) -prune \
               -o -name $1 -print; \
          for arch in $(ALLINCLUDE_ARCHS) ; do \
-              find $(__srctree)include/asm-$${arch} $(RCS_FIND_IGNORE) \
+              test -e $(__srctree)include/asm-$${arch} && \
+                  find $(__srctree)include/asm-$${arch} $(RCS_FIND_IGNORE) \
+                   -name $1 -print; \
+              test -e $(__srctree)arch/$${arch}/include/asm && \
+                find $(__srctree)arch/$${arch}/include/asm $(RCS_FIND_IGNORE) \
                    -name $1 -print; \
          done ; \
          find $(__srctree)include/asm-generic $(RCS_FIND_IGNORE) \
diff --combined arch/arm/Kconfig
index 28f15c4a7253042eddfd613340f378d6595d9e43,4b8acd2851f48e4a7e42bd6f8886fae30aae930c..cbc8406eaf2e55b8150d7e760baa34de54b39e1d
@@@ -12,8 -12,12 +12,12 @@@ config AR
        select RTC_LIB
        select SYS_SUPPORTS_APM_EMULATION
        select HAVE_OPROFILE
+       select HAVE_ARCH_KGDB
        select HAVE_KPROBES if (!XIP_KERNEL)
        select HAVE_KRETPROBES if (HAVE_KPROBES)
+       select HAVE_FTRACE if (!XIP_KERNEL)
+       select HAVE_DYNAMIC_FTRACE if (HAVE_FTRACE)
+       select HAVE_GENERIC_DMA_COHERENT
        help
          The ARM series is a line of low-power-consumption RISC chip designs
          licensed by ARM Ltd and targeted at embedded applications and
@@@ -22,6 -26,9 +26,9 @@@
          Europe.  There is an ARM Linux project with a web page at
          <http://www.arm.linux.org.uk/>.
  
+ config HAVE_PWM
+       bool
  config SYS_SUPPORTS_APM_EMULATION
        bool
  
@@@ -84,6 -91,11 +91,11 @@@ config STACKTRACE_SUPPOR
        bool
        default y
  
+ config HAVE_LATENCYTOP_SUPPORT
+       bool
+       depends on !SMP
+       default y
  config LOCKDEP_SUPPORT
        bool
        default y
@@@ -147,6 -159,10 +159,10 @@@ config FI
  config ARCH_MTD_XIP
        bool
  
+ config GENERIC_HARDIRQS_NO__DO_IRQ
+       bool
+       def_bool y
  if OPROFILE
  
  config OPROFILE_ARMV6
@@@ -183,12 -199,14 +199,14 @@@ choic
  config ARCH_AAEC2000
        bool "Agilent AAEC-2000 based"
        select ARM_AMBA
+       select HAVE_CLK
        help
          This enables support for systems based on the Agilent AAEC-2000
  
  config ARCH_INTEGRATOR
        bool "ARM Ltd. Integrator family"
        select ARM_AMBA
+       select HAVE_CLK
        select ICST525
        help
          Support for ARM's Integrator platform.
  config ARCH_REALVIEW
        bool "ARM Ltd. RealView family"
        select ARM_AMBA
+       select HAVE_CLK
        select ICST307
        select GENERIC_TIME
        select GENERIC_CLOCKEVENTS
@@@ -206,6 -225,7 +225,7 @@@ config ARCH_VERSATIL
        bool "ARM Ltd. Versatile family"
        select ARM_AMBA
        select ARM_VIC
+       select HAVE_CLK
        select ICST307
        select GENERIC_TIME
        select GENERIC_CLOCKEVENTS
  config ARCH_AT91
        bool "Atmel AT91"
        select GENERIC_GPIO
+       select HAVE_CLK
        help
          This enables support for systems based on the Atmel AT91RM9200,
          AT91SAM9 and AT91CAP9 processors.
@@@ -232,13 -253,6 +253,6 @@@ config ARCH_CLPS711
        help
          Support for Cirrus Logic 711x/721x based boards.
  
- config ARCH_CO285
-       bool "Co-EBSA285"
-       select FOOTBRIDGE
-       select FOOTBRIDGE_ADDIN
-       help
-         Support for Intel's EBSA285 companion chip.
  config ARCH_EBSA110
        bool "EBSA-110"
        select ISA
@@@ -254,7 -268,8 +268,8 @@@ config ARCH_EP93X
        select ARM_AMBA
        select ARM_VIC
        select GENERIC_GPIO
-       select HAVE_GPIO_LIB
+       select HAVE_CLK
+       select ARCH_REQUIRE_GPIOLIB
        help
          This enables support for the Cirrus EP93xx series of CPUs.
  
@@@ -299,6 -314,8 +314,8 @@@ config ARCH_IOP32
        depends on MMU
        select PLAT_IOP
        select PCI
+       select GENERIC_GPIO
+       select ARCH_REQUIRE_GPIOLIB
        help
          Support for Intel's 80219 and IOP32X (XScale) family of
          processors.
@@@ -308,6 -325,8 +325,8 @@@ config ARCH_IOP33
        depends on MMU
        select PLAT_IOP
        select PCI
+       select GENERIC_GPIO
+       select ARCH_REQUIRE_GPIOLIB
        help
          Support for Intel's IOP33X (XScale) family of processors.
  
@@@ -347,6 -366,16 +366,16 @@@ config ARCH_L720
          If you have any questions or comments about the Linux kernel port
          to this board, send e-mail to <sjhill@cotw.com>.
  
+ config ARCH_KIRKWOOD
+       bool "Marvell Kirkwood"
+       select PCI
+       select GENERIC_TIME
+       select GENERIC_CLOCKEVENTS
+       select PLAT_ORION
+       help
+         Support for the following Marvell Kirkwood series SoCs:
+         88F6180, 88F6192 and 88F6281.
  config ARCH_KS8695
        bool "Micrel/Kendin KS8695"
        select GENERIC_GPIO
@@@ -359,15 -388,38 +388,38 @@@ config ARCH_NS9XX
        select GENERIC_GPIO
        select GENERIC_TIME
        select GENERIC_CLOCKEVENTS
+       select HAVE_CLK
        help
          Say Y here if you intend to run this kernel on a NetSilicon NS9xxx
          System.
  
          <http://www.digi.com/products/microprocessors/index.jsp>
  
+ config ARCH_LOKI
+       bool "Marvell Loki (88RC8480)"
+       select GENERIC_TIME
+       select GENERIC_CLOCKEVENTS
+       select PLAT_ORION
+       help
+         Support for the Marvell Loki (88RC8480) SoC.
+ config ARCH_MV78XX0
+       bool "Marvell MV78xx0"
+       select PCI
+       select GENERIC_TIME
+       select GENERIC_CLOCKEVENTS
+       select PLAT_ORION
+       help
+         Support for the following Marvell MV78xx0 series SoCs:
+         MV781x0, MV782x0.
  config ARCH_MXC
        bool "Freescale MXC/iMX-based"
+       select GENERIC_TIME
+       select GENERIC_CLOCKEVENTS
        select ARCH_MTD_XIP
+       select GENERIC_GPIO
+       select ARCH_REQUIRE_GPIOLIB
        help
          Support for Freescale MXC/iMX-based family of processors
  
@@@ -381,10 -433,12 +433,12 @@@ config ARCH_ORION5
        select PLAT_ORION
        help
          Support for the following Marvell Orion 5x series SoCs:
-         Orion-1 (5181), Orion-NAS (5182), Orion-2 (5281.)
+         Orion-1 (5181), Orion-VoIP (5181L), Orion-NAS (5182),
+         Orion-2 (5281).
  
  config ARCH_PNX4008
        bool "Philips Nexperia PNX4008 Mobile"
+       select HAVE_CLK
        help
          This enables support for Philips PNX4008 mobile platform.
  
@@@ -393,7 -447,8 +447,8 @@@ config ARCH_PX
        depends on MMU
        select ARCH_MTD_XIP
        select GENERIC_GPIO
-       select HAVE_GPIO_LIB
+       select HAVE_CLK
+       select ARCH_REQUIRE_GPIOLIB
        select GENERIC_TIME
        select GENERIC_CLOCKEVENTS
        select TICK_ONESHOT
@@@ -406,6 -461,7 +461,7 @@@ config ARCH_RP
        select FIQ
        select TIMER_ACORN
        select ARCH_MAY_HAVE_PC_FDC
+       select HAVE_PATA_PLATFORM
        select ISA_DMA_API
        select NO_IOPORT
        help
@@@ -422,14 -478,16 +478,16 @@@ config ARCH_SA110
        select GENERIC_GPIO
        select GENERIC_TIME
        select GENERIC_CLOCKEVENTS
+       select HAVE_CLK
        select TICK_ONESHOT
-       select HAVE_GPIO_LIB
+       select ARCH_REQUIRE_GPIOLIB
        help
          Support for StrongARM 11x0 based boards.
  
  config ARCH_S3C2410
        bool "Samsung S3C2410, S3C2412, S3C2413, S3C2440, S3C2442, S3C2443"
        select GENERIC_GPIO
+       select HAVE_CLK
        help
          Samsung S3C2410X CPU based systems, such as the Simtec Electronics
          BAST (<http://www.simtec.co.uk/products/EB110ITX/>), the IPAQ 1940 or
@@@ -457,13 -515,15 +515,15 @@@ config ARCH_DAVINC
        select GENERIC_TIME
        select GENERIC_CLOCKEVENTS
        select GENERIC_GPIO
+       select HAVE_CLK
        help
          Support for TI's DaVinci platform.
  
  config ARCH_OMAP
        bool "TI OMAP"
        select GENERIC_GPIO
-       select HAVE_GPIO_LIB
+       select HAVE_CLK
+       select ARCH_REQUIRE_GPIOLIB
        select GENERIC_TIME
        select GENERIC_CLOCKEVENTS
        help
@@@ -502,6 -562,10 +562,10 @@@ source "arch/arm/mach-ixp2000/Kconfig
  
  source "arch/arm/mach-ixp23xx/Kconfig"
  
+ source "arch/arm/mach-loki/Kconfig"
+ source "arch/arm/mach-mv78xx0/Kconfig"
  source "arch/arm/mach-pxa/Kconfig"
  
  source "arch/arm/mach-sa1100/Kconfig"
@@@ -514,6 -578,8 +578,8 @@@ source "arch/arm/mach-omap2/Kconfig
  
  source "arch/arm/mach-orion5x/Kconfig"
  
+ source "arch/arm/mach-kirkwood/Kconfig"
  source "arch/arm/plat-s3c24xx/Kconfig"
  source "arch/arm/plat-s3c/Kconfig"
  
@@@ -650,6 -716,7 +716,7 @@@ source "kernel/time/Kconfig
  config SMP
        bool "Symmetric Multi-Processing (EXPERIMENTAL)"
        depends on EXPERIMENTAL && (REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP)
+       select USE_GENERIC_SMP_HELPERS
        help
          This enables support for systems with more than one CPU. If you have
          a system with only one CPU, like most personal computers, say N. If
@@@ -703,27 -770,6 +770,6 @@@ config PREEMP
          Say Y here if you are building a kernel for a desktop, embedded
          or real-time system.  Say N if you are unsure.
  
- config NO_IDLE_HZ
-       bool "Dynamic tick timer"
-       depends on !GENERIC_CLOCKEVENTS
-       help
-         Select this option if you want to disable continuous timer ticks
-         and have them programmed to occur as required. This option saves
-         power as the system can remain in idle state for longer.
-         By default dynamic tick is disabled during the boot, and can be
-         manually enabled with:
-           echo 1 > /sys/devices/system/timer/timer0/dyn_tick
-         Alternatively, if you want dynamic tick automatically enabled
-         during boot, pass "dyntick=enable" via the kernel command string.
-         Please note that dynamic tick may affect the accuracy of
-         timekeeping on some platforms depending on the implementation.
-         Currently at least OMAP, PXA2xx and SA11x0 platforms are known
-         to have accurate timekeeping with dynamic tick.
  config HZ
        int
        default 128 if ARCH_L7200
@@@ -789,7 -835,7 +835,7 @@@ source "mm/Kconfig
  
  config LEDS
        bool "Timer and CPU usage LEDs"
-       depends on ARCH_CDB89712 || ARCH_CO285 || ARCH_EBSA110 || \
+       depends on ARCH_CDB89712 || ARCH_EBSA110 || \
                   ARCH_EBSA285 || ARCH_IMX || ARCH_INTEGRATOR || \
                   ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_NETWINDER || \
                   ARCH_OMAP || ARCH_P720T || ARCH_PXA_IDP || \
@@@ -1179,13 -1225,10 +1225,15 @@@ source "drivers/dma/Kconfig
  
  source "drivers/dca/Kconfig"
  
+ source "drivers/regulator/Kconfig"
  source "drivers/uio/Kconfig"
  
 +if ARCH_OMAP
 +source "drivers/cbus/Kconfig"
 +source "drivers/dsp/dspgateway/Kconfig"
 +endif
 +
  endmenu
  
  source "fs/Kconfig"
diff --combined arch/arm/Makefile
index 40a0b44434735cca3b55fe1acc35fcb9f3931721,2f07477442369ee44b88cbd7fe3a57bcea8ec774..c595df316365d4f23c88ac5278a1c1b63ee5f0af
@@@ -67,7 -67,7 +67,7 @@@ tune-$(CONFIG_CPU_ARM720T)    :=-mtune=arm
  tune-$(CONFIG_CPU_ARM740T)    :=-mtune=arm7tdmi
  tune-$(CONFIG_CPU_ARM9TDMI)   :=-mtune=arm9tdmi
  tune-$(CONFIG_CPU_ARM940T)    :=-mtune=arm9tdmi
- tune-$(CONFIG_CPU_ARM946T)    :=$(call cc-option,-mtune=arm9e,-mtune=arm9tdmi)
+ tune-$(CONFIG_CPU_ARM946E)    :=$(call cc-option,-mtune=arm9e,-mtune=arm9tdmi)
  tune-$(CONFIG_CPU_ARM920T)    :=-mtune=arm9tdmi
  tune-$(CONFIG_CPU_ARM922T)    :=-mtune=arm9tdmi
  tune-$(CONFIG_CPU_ARM925T)    :=-mtune=arm9tdmi
@@@ -100,8 -100,6 +100,6 @@@ textofs-y  := 0x0000800
    incdir-$(CONFIG_ARCH_CLPS7500)   := cl7500
   machine-$(CONFIG_FOOTBRIDGE)    := footbridge
    incdir-$(CONFIG_FOOTBRIDGE)    := ebsa285
-  machine-$(CONFIG_ARCH_CO285)    := footbridge
-   incdir-$(CONFIG_ARCH_CO285)    := ebsa285
   machine-$(CONFIG_ARCH_SHARK)    := shark
   machine-$(CONFIG_ARCH_SA1100)           := sa1100
  ifeq ($(CONFIG_ARCH_SA1100),y)
@@@ -121,7 -119,6 +119,7 @@@ endi
   machine-$(CONFIG_ARCH_IXP23XX)    := ixp23xx
   machine-$(CONFIG_ARCH_OMAP1)    := omap1
   machine-$(CONFIG_ARCH_OMAP2)    := omap2
 + machine-$(CONFIG_ARCH_OMAP3)         := omap2
    incdir-$(CONFIG_ARCH_OMAP)     := omap
   machine-$(CONFIG_ARCH_S3C2410)          := s3c2410
   machine-$(CONFIG_ARCH_LH7A40X)          := lh7a40x
   machine-$(CONFIG_ARCH_NETX)     := netx
   machine-$(CONFIG_ARCH_NS9XXX)           := ns9xxx
   machine-$(CONFIG_ARCH_DAVINCI)          := davinci
+  machine-$(CONFIG_ARCH_KIRKWOOD)   := kirkwood
   machine-$(CONFIG_ARCH_KS8695)     := ks8695
    incdir-$(CONFIG_ARCH_MXC)      := mxc
+  machine-$(CONFIG_ARCH_MX2)      := mx2
   machine-$(CONFIG_ARCH_MX3)      := mx3
   machine-$(CONFIG_ARCH_ORION5X)          := orion5x
   machine-$(CONFIG_ARCH_MSM7X00A)   := msm
+  machine-$(CONFIG_ARCH_LOKI)       := loki
+  machine-$(CONFIG_ARCH_MV78XX0)    := mv78xx0
  
  ifeq ($(CONFIG_ARCH_EBSA110),y)
  # This is what happens if you forget the IOCS16 line.
@@@ -191,8 -192,6 +193,6 @@@ core-$(CONFIG_PLAT_S3C24XX)                += arch/ar
  core-$(CONFIG_ARCH_MXC)               += arch/arm/plat-mxc/
  
  drivers-$(CONFIG_OPROFILE)      += arch/arm/oprofile/
- drivers-$(CONFIG_ARCH_CLPS7500)       += drivers/acorn/char/
- drivers-$(CONFIG_ARCH_L7200)  += drivers/acorn/char/
  
  libs-y                                := arch/arm/lib/ $(libs-y)
  
index 2980faf53313ace2dca31fa5e56690f04bf757e9,94462a097f86697ce51558bd9389a4886b904318..b6f850223cf7c99b043ec46c9a395e01e1375e2a
@@@ -44,10 -44,6 +44,10 @@@ ifeq ($(CONFIG_PXA_SHARPSL),y
  OBJS          += head-sharpsl.o
  endif
  
 +ifeq ($(CONFIG_MACH_OMAP_PERSEUS2),y)
 +OBJS          += head-omap.o
 +endif
 +
  ifeq ($(CONFIG_CPU_BIG_ENDIAN),y)
  ifeq ($(CONFIG_CPU_CP15),y)
  OBJS          += big-endian.o
@@@ -73,6 -69,12 +73,12 @@@ SEDFLAGS    = s/TEXT_START/$(ZTEXTADDR)/;s
  
  targets       := vmlinux vmlinux.lds piggy.gz piggy.o font.o font.c \
                 head.o misc.o $(OBJS)
+ ifeq ($(CONFIG_FTRACE),y)
+ ORIG_CFLAGS := $(KBUILD_CFLAGS)
+ KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS))
+ endif
  EXTRA_CFLAGS  := -fpic -fno-builtin
  EXTRA_AFLAGS  :=
  
@@@ -110,6 -112,3 +116,3 @@@ $(obj)/font.c: $(FONTC
  
  $(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in arch/arm/boot/Makefile .config
        @sed "$(SEDFLAGS)" < $< > $@
- $(obj)/misc.o: $(obj)/misc.c include/asm/arch/uncompress.h lib/inflate.c
index 32be06189ca63345cbb8781d52beae3ed38b4b5e,de41daeab5e9832416218a0ca3e07b9a15cb219f..d32b721eddb447bb98380250f305a960995b5221
@@@ -55,7 -55,7 +55,7 @@@
  #elif defined(CONFIG_ARCH_S3C2410)
                .macro loadsp, rb
                mov     \rb, #0x50000000
 -              add     \rb, \rb, #0x4000 * CONFIG_S3C_LOWLEVEL_UART_PORT
 +              add     \rb, \rb, #0x4000 * CONFIG_S3C2410_LOWLEVEL_UART_PORT
                .endm
  #else
                .macro  loadsp, rb
@@@ -623,8 -623,8 +623,8 @@@ proc_types
                b       __armv4_mmu_cache_off
                b       __armv4_mmu_cache_flush
  
-               .word   0x56055310              @ Feroceon
-               .word   0xfffffff0
+               .word   0x56050000              @ Feroceon
+               .word   0xff0f0000
                b       __armv4_mmu_cache_on
                b       __armv4_mmu_cache_off
                b       __armv5tej_mmu_cache_flush
@@@ -782,7 -782,6 +782,7 @@@ __armv7_mmu_cache_flush
                mcr     p15, 0, r10, c7, c14, 0 @ clean+invalidate D
                b       iflush
  hierarchical:
 +              adr     sp, no_cache_id         @ non-v7 code is temp stack
                stmfd   sp!, {r0-r5, r7, r9-r11}
                mrc     p15, 1, r0, c0, c0, 1   @ read clidr
                ands    r3, r0, #0x7000000      @ extract loc from clidr
index 0000000000000000000000000000000000000000,8ab060a53ab0a9cb4913de95048e4a1b6fd79028..53f7acb1719166cac75f710cb9e942b5883a0ac3
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,401 +1,402 @@@
+ /*
+  *  arch/arm/include/asm/pgtable.h
+  *
+  *  Copyright (C) 1995-2002 Russell King
+  *
+  * 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 _ASMARM_PGTABLE_H
+ #define _ASMARM_PGTABLE_H
+ #include <asm-generic/4level-fixup.h>
+ #include <asm/proc-fns.h>
+ #ifndef CONFIG_MMU
+ #include "pgtable-nommu.h"
+ #else
+ #include <asm/memory.h>
+ #include <asm/arch/vmalloc.h>
+ #include <asm/pgtable-hwdef.h>
+ /*
+  * Just any arbitrary offset to the start of the vmalloc VM area: the
+  * current 8MB value just means that there will be a 8MB "hole" after the
+  * physical memory until the kernel virtual memory starts.  That means that
+  * any out-of-bounds memory accesses will hopefully be caught.
+  * The vmalloc() routines leaves a hole of 4kB between each vmalloced
+  * area for the same reason. ;)
+  *
+  * Note that platforms may override VMALLOC_START, but they must provide
+  * VMALLOC_END.  VMALLOC_END defines the (exclusive) limit of this space,
+  * which may not overlap IO space.
+  */
+ #ifndef VMALLOC_START
+ #define VMALLOC_OFFSET                (8*1024*1024)
+ #define VMALLOC_START         (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+ #endif
+ /*
+  * Hardware-wise, we have a two level page table structure, where the first
+  * level has 4096 entries, and the second level has 256 entries.  Each entry
+  * is one 32-bit word.  Most of the bits in the second level entry are used
+  * by hardware, and there aren't any "accessed" and "dirty" bits.
+  *
+  * Linux on the other hand has a three level page table structure, which can
+  * be wrapped to fit a two level page table structure easily - using the PGD
+  * and PTE only.  However, Linux also expects one "PTE" table per page, and
+  * at least a "dirty" bit.
+  *
+  * Therefore, we tweak the implementation slightly - we tell Linux that we
+  * have 2048 entries in the first level, each of which is 8 bytes (iow, two
+  * hardware pointers to the second level.)  The second level contains two
+  * hardware PTE tables arranged contiguously, followed by Linux versions
+  * which contain the state information Linux needs.  We, therefore, end up
+  * with 512 entries in the "PTE" level.
+  *
+  * This leads to the page tables having the following layout:
+  *
+  *    pgd             pte
+  * |        |
+  * +--------+ +0
+  * |        |-----> +------------+ +0
+  * +- - - - + +4    |  h/w pt 0  |
+  * |        |-----> +------------+ +1024
+  * +--------+ +8    |  h/w pt 1  |
+  * |        |       +------------+ +2048
+  * +- - - - +       | Linux pt 0 |
+  * |        |       +------------+ +3072
+  * +--------+       | Linux pt 1 |
+  * |        |       +------------+ +4096
+  *
+  * See L_PTE_xxx below for definitions of bits in the "Linux pt", and
+  * PTE_xxx for definitions of bits appearing in the "h/w pt".
+  *
+  * PMD_xxx definitions refer to bits in the first level page table.
+  *
+  * The "dirty" bit is emulated by only granting hardware write permission
+  * iff the page is marked "writable" and "dirty" in the Linux PTE.  This
+  * means that a write to a clean page will cause a permission fault, and
+  * the Linux MM layer will mark the page dirty via handle_pte_fault().
+  * For the hardware to notice the permission change, the TLB entry must
+  * be flushed, and ptep_set_access_flags() does that for us.
+  *
+  * The "accessed" or "young" bit is emulated by a similar method; we only
+  * allow accesses to the page if the "young" bit is set.  Accesses to the
+  * page will cause a fault, and handle_pte_fault() will set the young bit
+  * for us as long as the page is marked present in the corresponding Linux
+  * PTE entry.  Again, ptep_set_access_flags() will ensure that the TLB is
+  * up to date.
+  *
+  * However, when the "young" bit is cleared, we deny access to the page
+  * by clearing the hardware PTE.  Currently Linux does not flush the TLB
+  * for us in this case, which means the TLB will retain the transation
+  * until either the TLB entry is evicted under pressure, or a context
+  * switch which changes the user space mapping occurs.
+  */
+ #define PTRS_PER_PTE          512
+ #define PTRS_PER_PMD          1
+ #define PTRS_PER_PGD          2048
+ /*
+  * PMD_SHIFT determines the size of the area a second-level page table can map
+  * PGDIR_SHIFT determines what a third-level page table entry can map
+  */
+ #define PMD_SHIFT             21
+ #define PGDIR_SHIFT           21
+ #define LIBRARY_TEXT_START    0x0c000000
+ #ifndef __ASSEMBLY__
+ extern void __pte_error(const char *file, int line, unsigned long val);
+ extern void __pmd_error(const char *file, int line, unsigned long val);
+ extern void __pgd_error(const char *file, int line, unsigned long val);
+ #define pte_ERROR(pte)                __pte_error(__FILE__, __LINE__, pte_val(pte))
+ #define pmd_ERROR(pmd)                __pmd_error(__FILE__, __LINE__, pmd_val(pmd))
+ #define pgd_ERROR(pgd)                __pgd_error(__FILE__, __LINE__, pgd_val(pgd))
+ #endif /* !__ASSEMBLY__ */
+ #define PMD_SIZE              (1UL << PMD_SHIFT)
+ #define PMD_MASK              (~(PMD_SIZE-1))
+ #define PGDIR_SIZE            (1UL << PGDIR_SHIFT)
+ #define PGDIR_MASK            (~(PGDIR_SIZE-1))
+ /*
+  * This is the lowest virtual address we can permit any user space
+  * mapping to be mapped at.  This is particularly important for
+  * non-high vector CPUs.
+  */
+ #define FIRST_USER_ADDRESS    PAGE_SIZE
+ #define FIRST_USER_PGD_NR     1
+ #define USER_PTRS_PER_PGD     ((TASK_SIZE/PGDIR_SIZE) - FIRST_USER_PGD_NR)
+ /*
+  * section address mask and size definitions.
+  */
+ #define SECTION_SHIFT         20
+ #define SECTION_SIZE          (1UL << SECTION_SHIFT)
+ #define SECTION_MASK          (~(SECTION_SIZE-1))
+ /*
+  * ARMv6 supersection address mask and size definitions.
+  */
+ #define SUPERSECTION_SHIFT    24
+ #define SUPERSECTION_SIZE     (1UL << SUPERSECTION_SHIFT)
+ #define SUPERSECTION_MASK     (~(SUPERSECTION_SIZE-1))
+ /*
+  * "Linux" PTE definitions.
+  *
+  * We keep two sets of PTEs - the hardware and the linux version.
+  * This allows greater flexibility in the way we map the Linux bits
+  * onto the hardware tables, and allows us to have YOUNG and DIRTY
+  * bits.
+  *
+  * The PTE table pointer refers to the hardware entries; the "Linux"
+  * entries are stored 1024 bytes below.
+  */
+ #define L_PTE_PRESENT         (1 << 0)
+ #define L_PTE_FILE            (1 << 1)        /* only when !PRESENT */
+ #define L_PTE_YOUNG           (1 << 1)
+ #define L_PTE_BUFFERABLE      (1 << 2)        /* matches PTE */
+ #define L_PTE_CACHEABLE               (1 << 3)        /* matches PTE */
+ #define L_PTE_USER            (1 << 4)
+ #define L_PTE_WRITE           (1 << 5)
+ #define L_PTE_EXEC            (1 << 6)
+ #define L_PTE_DIRTY           (1 << 7)
+ #define L_PTE_SHARED          (1 << 10)       /* shared(v6), coherent(xsc3) */
+ #ifndef __ASSEMBLY__
+ /*
+  * The pgprot_* and protection_map entries will be fixed up in runtime
+  * to include the cachable and bufferable bits based on memory policy,
+  * as well as any architecture dependent bits like global/ASID and SMP
+  * shared mapping bits.
+  */
+ #define _L_PTE_DEFAULT        L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_CACHEABLE | L_PTE_BUFFERABLE
+ #define _L_PTE_READ   L_PTE_USER | L_PTE_EXEC
+ extern pgprot_t               pgprot_user;
+ extern pgprot_t               pgprot_kernel;
+ #define PAGE_NONE     pgprot_user
+ #define PAGE_COPY     __pgprot(pgprot_val(pgprot_user) | _L_PTE_READ)
+ #define PAGE_SHARED   __pgprot(pgprot_val(pgprot_user) | _L_PTE_READ | \
+                                L_PTE_WRITE)
+ #define PAGE_READONLY __pgprot(pgprot_val(pgprot_user) | _L_PTE_READ)
+ #define PAGE_KERNEL   pgprot_kernel
+ #define __PAGE_NONE   __pgprot(_L_PTE_DEFAULT)
+ #define __PAGE_COPY   __pgprot(_L_PTE_DEFAULT | _L_PTE_READ)
+ #define __PAGE_SHARED __pgprot(_L_PTE_DEFAULT | _L_PTE_READ | L_PTE_WRITE)
+ #define __PAGE_READONLY       __pgprot(_L_PTE_DEFAULT | _L_PTE_READ)
+ #endif /* __ASSEMBLY__ */
+ /*
+  * The table below defines the page protection levels that we insert into our
+  * Linux page table version.  These get translated into the best that the
+  * architecture can perform.  Note that on most ARM hardware:
+  *  1) We cannot do execute protection
+  *  2) If we could do execute protection, then read is implied
+  *  3) write implies read permissions
+  */
+ #define __P000  __PAGE_NONE
+ #define __P001  __PAGE_READONLY
+ #define __P010  __PAGE_COPY
+ #define __P011  __PAGE_COPY
+ #define __P100  __PAGE_READONLY
+ #define __P101  __PAGE_READONLY
+ #define __P110  __PAGE_COPY
+ #define __P111  __PAGE_COPY
+ #define __S000  __PAGE_NONE
+ #define __S001  __PAGE_READONLY
+ #define __S010  __PAGE_SHARED
+ #define __S011  __PAGE_SHARED
+ #define __S100  __PAGE_READONLY
+ #define __S101  __PAGE_READONLY
+ #define __S110  __PAGE_SHARED
+ #define __S111  __PAGE_SHARED
+ #ifndef __ASSEMBLY__
+ /*
+  * ZERO_PAGE is a global shared page that is always zero: used
+  * for zero-mapped memory areas etc..
+  */
+ extern struct page *empty_zero_page;
+ #define ZERO_PAGE(vaddr)      (empty_zero_page)
+ #define pte_pfn(pte)          (pte_val(pte) >> PAGE_SHIFT)
+ #define pfn_pte(pfn,prot)     (__pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot)))
+ #define pte_none(pte)         (!pte_val(pte))
+ #define pte_clear(mm,addr,ptep)       set_pte_ext(ptep, __pte(0), 0)
+ #define pte_page(pte)         (pfn_to_page(pte_pfn(pte)))
+ #define pte_offset_kernel(dir,addr)   (pmd_page_vaddr(*(dir)) + __pte_index(addr))
+ #define pte_offset_map(dir,addr)      (pmd_page_vaddr(*(dir)) + __pte_index(addr))
+ #define pte_offset_map_nested(dir,addr)       (pmd_page_vaddr(*(dir)) + __pte_index(addr))
+ #define pte_unmap(pte)                do { } while (0)
+ #define pte_unmap_nested(pte) do { } while (0)
+ #define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,pte,ext)
+ #define set_pte_at(mm,addr,ptep,pteval) do { \
+       set_pte_ext(ptep, pteval, (addr) >= TASK_SIZE ? 0 : PTE_EXT_NG); \
+  } while (0)
+ /*
+  * The following only work if pte_present() is true.
+  * Undefined behaviour if not..
+  */
+ #define pte_present(pte)      (pte_val(pte) & L_PTE_PRESENT)
+ #define pte_write(pte)                (pte_val(pte) & L_PTE_WRITE)
+ #define pte_dirty(pte)                (pte_val(pte) & L_PTE_DIRTY)
+ #define pte_young(pte)                (pte_val(pte) & L_PTE_YOUNG)
+ #define pte_special(pte)      (0)
+ /*
+  * The following only works if pte_present() is not true.
+  */
+ #define pte_file(pte)         (pte_val(pte) & L_PTE_FILE)
+ #define pte_to_pgoff(x)               (pte_val(x) >> 2)
+ #define pgoff_to_pte(x)               __pte(((x) << 2) | L_PTE_FILE)
+ #define PTE_FILE_MAX_BITS     30
+ #define PTE_BIT_FUNC(fn,op) \
+ static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; }
+ PTE_BIT_FUNC(wrprotect, &= ~L_PTE_WRITE);
+ PTE_BIT_FUNC(mkwrite,   |= L_PTE_WRITE);
+ PTE_BIT_FUNC(mkclean,   &= ~L_PTE_DIRTY);
+ PTE_BIT_FUNC(mkdirty,   |= L_PTE_DIRTY);
+ PTE_BIT_FUNC(mkold,     &= ~L_PTE_YOUNG);
+ PTE_BIT_FUNC(mkyoung,   |= L_PTE_YOUNG);
+ static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
+ /*
+  * Mark the prot value as uncacheable and unbufferable.
+  */
+ #define pgprot_noncached(prot)        __pgprot(pgprot_val(prot) & ~(L_PTE_CACHEABLE | L_PTE_BUFFERABLE))
+ #define pgprot_writecombine(prot) __pgprot(pgprot_val(prot) & ~L_PTE_CACHEABLE)
+ #define pmd_none(pmd)         (!pmd_val(pmd))
+ #define pmd_present(pmd)      (pmd_val(pmd))
+ #define pmd_bad(pmd)          (pmd_val(pmd) & 2)
++#define pmd_table(pmd)                ((pmd_val(pmd) & PMD_TYPE_MASK) == PMD_TYPE_TABLE)
+ #define copy_pmd(pmdpd,pmdps)         \
+       do {                            \
+               pmdpd[0] = pmdps[0];    \
+               pmdpd[1] = pmdps[1];    \
+               flush_pmd_entry(pmdpd); \
+       } while (0)
+ #define pmd_clear(pmdp)                       \
+       do {                            \
+               pmdp[0] = __pmd(0);     \
+               pmdp[1] = __pmd(0);     \
+               clean_pmd_entry(pmdp);  \
+       } while (0)
+ static inline pte_t *pmd_page_vaddr(pmd_t pmd)
+ {
+       unsigned long ptr;
+       ptr = pmd_val(pmd) & ~(PTRS_PER_PTE * sizeof(void *) - 1);
+       ptr += PTRS_PER_PTE * sizeof(void *);
+       return __va(ptr);
+ }
+ #define pmd_page(pmd) virt_to_page(__va(pmd_val(pmd)))
+ /*
+  * Permanent address of a page. We never have highmem, so this is trivial.
+  */
+ #define pages_to_mb(x)                ((x) >> (20 - PAGE_SHIFT))
+ /*
+  * Conversion functions: convert a page and protection to a page entry,
+  * and a page entry and page directory to the page they refer to.
+  */
+ #define mk_pte(page,prot)     pfn_pte(page_to_pfn(page),prot)
+ /*
+  * The "pgd_xxx()" functions here are trivial for a folded two-level
+  * setup: the pgd is never bad, and a pmd always exists (as it's folded
+  * into the pgd entry)
+  */
+ #define pgd_none(pgd)         (0)
+ #define pgd_bad(pgd)          (0)
+ #define pgd_present(pgd)      (1)
+ #define pgd_clear(pgdp)               do { } while (0)
+ #define set_pgd(pgd,pgdp)     do { } while (0)
+ /* to find an entry in a page-table-directory */
+ #define pgd_index(addr)               ((addr) >> PGDIR_SHIFT)
+ #define pgd_offset(mm, addr)  ((mm)->pgd+pgd_index(addr))
+ /* to find an entry in a kernel page-table-directory */
+ #define pgd_offset_k(addr)    pgd_offset(&init_mm, addr)
+ /* Find an entry in the second-level page table.. */
+ #define pmd_offset(dir, addr) ((pmd_t *)(dir))
+ /* Find an entry in the third-level page table.. */
+ #define __pte_index(addr)     (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+ {
+       const unsigned long mask = L_PTE_EXEC | L_PTE_WRITE | L_PTE_USER;
+       pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask);
+       return pte;
+ }
+ extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
+ /* Encode and decode a swap entry.
+  *
+  * We support up to 32GB of swap on 4k machines
+  */
+ #define __swp_type(x)         (((x).val >> 2) & 0x7f)
+ #define __swp_offset(x)               ((x).val >> 9)
+ #define __swp_entry(type,offset) ((swp_entry_t) { ((type) << 2) | ((offset) << 9) })
+ #define __pte_to_swp_entry(pte)       ((swp_entry_t) { pte_val(pte) })
+ #define __swp_entry_to_pte(swp)       ((pte_t) { (swp).val })
+ /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
+ /* FIXME: this is not correct */
+ #define kern_addr_valid(addr) (1)
+ #include <asm-generic/pgtable.h>
+ /*
+  * We provide our own arch_get_unmapped_area to cope with VIPT caches.
+  */
+ #define HAVE_ARCH_UNMAPPED_AREA
+ /*
+  * remap a physical page `pfn' of size `size' with page protection `prot'
+  * into virtual address `from'
+  */
+ #define io_remap_pfn_range(vma,from,pfn,size,prot) \
+               remap_pfn_range(vma, from, pfn, size, prot)
+ #define pgtable_cache_init() do { } while (0)
+ #endif /* !__ASSEMBLY__ */
+ #endif /* CONFIG_MMU */
+ #endif /* _ASMARM_PGTABLE_H */
index da786171d15cbb827c99a702aaced46cf1ef2a88,7bbf105463f1adf8fd9cdaf68283cc87f3cb8c97..da786171d15cbb827c99a702aaced46cf1ef2a88
@@@ -136,13 -136,6 +136,13 @@@ struct tag_acorn 
        __u8 adfsdrives;
  };
  
 +/* TI OMAP specific information */
 +#define ATAG_BOARD       0x414f4d50
 +
 +struct tag_omap {
 +      u8 data[0];
 +};
 +
  /* footbridge memory clock, see arch/arm/mach-footbridge/arch.c */
  #define ATAG_MEMCLK   0x41000402
  
@@@ -168,11 -161,6 +168,11 @@@ struct tag 
                 */
                struct tag_acorn        acorn;
  
 +              /*
 +               * OMAP specific
 +                 */
 +                struct tag_omap         omap;
 +
                /*
                 * DC21285 specific
                 */
index 08f533eced7583d30bb50cc02148894621a7a286,3f39e0e79c9f6eecc3207cc0dbbea9972e0a727a..33a987739b44dd244dccb94a94ec75c5c1e0b434
@@@ -10,6 -10,7 +10,7 @@@
  
  #include <linux/kernel.h>
  #include <linux/init.h>
+ #include <linux/mutex.h>
  #include <linux/platform_device.h>
  #include <linux/input.h>
  #include <linux/clk.h>
@@@ -18,7 -19,6 +19,6 @@@
  #include <linux/spi/ads7846.h>
  #include <linux/workqueue.h>
  #include <linux/delay.h>
- #include <linux/mutex.h>
  
  #include <asm/hardware.h>
  #include <asm/mach-types.h>
@@@ -34,7 -34,6 +34,7 @@@
  #include <asm/arch/dsp_common.h>
  #include <asm/arch/aic23.h>
  #include <asm/arch/omapfb.h>
 +#include <asm/arch/hwa742.h>
  #include <asm/arch/lcd_mipid.h>
  
  #define ADS7846_PENDOWN_GPIO  15
@@@ -163,47 -162,6 +163,47 @@@ static struct spi_board_info nokia770_s
        },
  };
  
 +static struct {
 +      struct clk *sys_ck;
 +} hwa742;
 +
 +static int hwa742_get_clocks(void)
 +{
 +      hwa742.sys_ck = clk_get(NULL, "bclk");
 +      if (IS_ERR(hwa742.sys_ck)) {
 +              printk(KERN_ERR "can't get HWA742 clock\n");
 +              return PTR_ERR(hwa742.sys_ck);
 +      }
 +      return 0;
 +}
 +
 +static unsigned long hwa742_get_clock_rate(struct device *dev)
 +{
 +      return clk_get_rate(hwa742.sys_ck);
 +}
 +
 +static void hwa742_power_up(struct device *dev)
 +{
 +      clk_enable(hwa742.sys_ck);
 +}
 +
 +static void hwa742_power_down(struct device *dev)
 +{
 +      clk_disable(hwa742.sys_ck);
 +}
 +
 +static struct hwa742_platform_data nokia770_hwa742_platform_data = {
 +      .get_clock_rate = hwa742_get_clock_rate,
 +      .power_up       = hwa742_power_up,
 +      .power_down     = hwa742_power_down,
 +      .te_connected   = 1,
 +};
 +
 +static void hwa742_dev_init(void)
 +{
 +      hwa742_get_clocks();
 +      omapfb_set_ctrl_platform_data(&nokia770_hwa742_platform_data);
 +}
  
  /* assume no Mini-AB port */
  
@@@ -245,7 -203,7 +245,7 @@@ static struct omap_board_config_kernel 
  #define       AMPLIFIER_CTRL_GPIO     58
  
  static struct clk *dspxor_ck;
- static DEFINE_MUTEX(audio_pwr_mutex);
+ static DEFINE_MUTEX(audio_pwr_lock);
  /*
   * audio_pwr_state
   * +--+-------------------------+---------------------------------------+
  static int audio_pwr_state = -1;
  
  /*
-  * audio_pwr_up / down should be called under audio_pwr_mutex
+  * audio_pwr_up / down should be called under audio_pwr_lock
   */
  static void nokia770_audio_pwr_up(void)
  {
  
  static void codec_delayed_power_down(struct work_struct *work)
  {
-       mutex_lock(&audio_pwr_mutex);
+       mutex_lock(&audio_pwr_lock);
        if (audio_pwr_state == -1)
                aic23_power_down();
        clk_disable(dspxor_ck);
-       mutex_unlock(&audio_pwr_mutex);
+       mutex_unlock(&audio_pwr_lock);
  }
  
  static DECLARE_DELAYED_WORK(codec_power_down_work, codec_delayed_power_down);
@@@ -301,19 -259,19 +301,19 @@@ static void nokia770_audio_pwr_down(voi
  static int
  nokia770_audio_pwr_up_request(struct dsp_kfunc_device *kdev, int stage)
  {
-       mutex_lock(&audio_pwr_mutex);
+       mutex_lock(&audio_pwr_lock);
        if (audio_pwr_state == -1)
                nokia770_audio_pwr_up();
        /* force audio_pwr_state = 0, even if it was 1. */
        audio_pwr_state = 0;
-       mutex_unlock(&audio_pwr_mutex);
+       mutex_unlock(&audio_pwr_lock);
        return 0;
  }
  
  static int
  nokia770_audio_pwr_down_request(struct dsp_kfunc_device *kdev, int stage)
  {
-       mutex_lock(&audio_pwr_mutex);
+       mutex_lock(&audio_pwr_lock);
        switch (stage) {
        case 1:
                if (audio_pwr_state == 0)
                }
                break;
        }
-       mutex_unlock(&audio_pwr_mutex);
+       mutex_unlock(&audio_pwr_lock);
        return 0;
  }
  
@@@ -375,7 -333,6 +375,7 @@@ static void __init omap_nokia770_init(v
        omap_serial_init();
        omap_register_i2c_bus(1, 100, NULL, 0);
        omap_dsp_init();
 +      hwa742_dev_init();
        ads7846_dev_init();
        mipid_dev_init();
  }
index 86f672a9406e4a98822dd53d7ccbac5f27bf00a9,8948d45a27695c64db1e228ed2f1e7be7518880f..ecd3219180495299ec08a73b251a3a09486195b3
@@@ -15,7 -15,6 +15,7 @@@
  #include <linux/delay.h>
  #include <linux/platform_device.h>
  #include <linux/interrupt.h>
 +#include <linux/irq.h>
  #include <linux/init.h>
  #include <linux/kernel.h>
  #include <linux/notifier.h>
@@@ -187,10 -186,10 +187,10 @@@ static void __init voiceblue_init(void
        omap_request_gpio(13);
        omap_request_gpio(14);
        omap_request_gpio(15);
-       set_irq_type(OMAP_GPIO_IRQ(12), IRQT_RISING);
-       set_irq_type(OMAP_GPIO_IRQ(13), IRQT_RISING);
-       set_irq_type(OMAP_GPIO_IRQ(14), IRQT_RISING);
-       set_irq_type(OMAP_GPIO_IRQ(15), IRQT_RISING);
+       set_irq_type(OMAP_GPIO_IRQ(12), IRQ_TYPE_EDGE_RISING);
+       set_irq_type(OMAP_GPIO_IRQ(13), IRQ_TYPE_EDGE_RISING);
+       set_irq_type(OMAP_GPIO_IRQ(14), IRQ_TYPE_EDGE_RISING);
+       set_irq_type(OMAP_GPIO_IRQ(15), IRQ_TYPE_EDGE_RISING);
  
        platform_add_devices(voiceblue_devices, ARRAY_SIZE(voiceblue_devices));
        omap_board_config = voiceblue_config;
index 433bd8e6b5a332275945d401ec7c50b9eb6cad1d,0000000000000000000000000000000000000000..90909630b9200a131b7c5ffdcedd569dd559349e
mode 100644,000000..100644
--- /dev/null
@@@ -1,736 -1,0 +1,738 @@@
 +/*
 + * linux/arch/arm/mach-omap2/board-n800.c
 + *
 + * Copyright (C) 2005-2007 Nokia Corporation
 + * Author: Juha Yrjola <juha.yrjola@nokia.com>
 + *
 + * Modified from mach-omap2/board-generic.c
 + *
 + * 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/device.h>
 +#include <linux/platform_device.h>
 +#include <linux/spi/spi.h>
 +#include <linux/spi/tsc2301.h>
 +#include <linux/spi/tsc2005.h>
 +#include <linux/input.h>
 +#include <linux/delay.h>
 +#include <linux/interrupt.h>
 +#include <linux/irq.h>
 +#include <linux/i2c.h>
 +#include <linux/i2c/lm8323.h>
 +#include <linux/i2c/menelaus.h>
 +#include <asm/hardware.h>
 +#include <asm/mach-types.h>
 +#include <asm/mach/arch.h>
 +#include <asm/mach/map.h>
 +#include <asm/arch/gpio.h>
 +#include <asm/arch/usb.h>
 +#include <asm/arch/board.h>
 +#include <asm/arch/common.h>
 +#include <asm/arch/mcspi.h>
 +#include <asm/arch/lcd_mipid.h>
 +#include <asm/arch/clock.h>
 +#include <asm/arch/gpio-switch.h>
 +#include <asm/arch/omapfb.h>
 +#include <asm/arch/blizzard.h>
 +
 +#include <../drivers/cbus/tahvo.h>
 +#include <../drivers/media/video/tcm825x.h>
 +
 +#define N800_BLIZZARD_POWERDOWN_GPIO  15
 +#define N800_STI_GPIO                 62
 +#define N800_KEYB_IRQ_GPIO            109
 +#define N800_DAV_IRQ_GPIO             103
 +#define N800_TSC2301_RESET_GPIO               118
 +
 +#ifdef CONFIG_MACH_NOKIA_N810
 +static s16 rx44_keymap[LM8323_KEYMAP_SIZE] = {
 +      [0x01] = KEY_Q,
 +      [0x02] = KEY_K,
 +      [0x03] = KEY_O,
 +      [0x04] = KEY_P,
 +      [0x05] = KEY_BACKSPACE,
 +      [0x06] = KEY_A,
 +      [0x07] = KEY_S,
 +      [0x08] = KEY_D,
 +      [0x09] = KEY_F,
 +      [0x0a] = KEY_G,
 +      [0x0b] = KEY_H,
 +      [0x0c] = KEY_J,
 +
 +      [0x11] = KEY_W,
 +      [0x12] = KEY_F4,
 +      [0x13] = KEY_L,
 +      [0x14] = KEY_APOSTROPHE,
 +      [0x16] = KEY_Z,
 +      [0x17] = KEY_X,
 +      [0x18] = KEY_C,
 +      [0x19] = KEY_V,
 +      [0x1a] = KEY_B,
 +      [0x1b] = KEY_N,
 +      [0x1c] = KEY_LEFTSHIFT, /* Actually, this is both shift keys */
 +      [0x1f] = KEY_F7,
 +
 +      [0x21] = KEY_E,
 +      [0x22] = KEY_SEMICOLON,
 +      [0x23] = KEY_MINUS,
 +      [0x24] = KEY_EQUAL,
 +      [0x2b] = KEY_FN,
 +      [0x2c] = KEY_M,
 +      [0x2f] = KEY_F8,
 +
 +      [0x31] = KEY_R,
 +      [0x32] = KEY_RIGHTCTRL,
 +      [0x34] = KEY_SPACE,
 +      [0x35] = KEY_COMMA,
 +      [0x37] = KEY_UP,
 +      [0x3c] = KEY_COMPOSE,
 +      [0x3f] = KEY_F6,
 +
 +      [0x41] = KEY_T,
 +      [0x44] = KEY_DOT,
 +      [0x46] = KEY_RIGHT,
 +      [0x4f] = KEY_F5,
 +      [0x51] = KEY_Y,
 +      [0x53] = KEY_DOWN,
 +      [0x55] = KEY_ENTER,
 +      [0x5f] = KEY_ESC,
 +
 +      [0x61] = KEY_U,
 +      [0x64] = KEY_LEFT,
 +
 +      [0x71] = KEY_I,
 +      [0x75] = KEY_KPENTER,
 +};
 +
 +static struct lm8323_platform_data lm8323_pdata = {
 +      .repeat = 0, /* Repeat is handled in userspace for now. */
 +      .keymap = rx44_keymap,
 +
 +      .name = "Internal keyboard",
 +      .pwm1_name = "keyboard",
 +      .pwm2_name = "cover",
 +};
 +#endif
 +
 +void __init nokia_n800_init_irq(void)
 +{
 +      omap2_init_common_hw(NULL);
 +      omap_init_irq();
 +      omap_gpio_init();
 +
 +#ifdef CONFIG_OMAP_STI
 +      if (omap_request_gpio(N800_STI_GPIO) < 0) {
 +              printk(KERN_ERR "Failed to request GPIO %d for STI\n",
 +                     N800_STI_GPIO);
 +              return;
 +      }
 +
 +      omap_set_gpio_direction(N800_STI_GPIO, 0);
 +      omap_set_gpio_dataout(N800_STI_GPIO, 0);
 +#endif
 +}
 +
 +#if defined(CONFIG_MENELAUS) && defined(CONFIG_SENSORS_TMP105)
 +
 +static int n800_tmp105_set_power(int enable)
 +{
 +      return menelaus_set_vaux(enable ? 2800 : 0);
 +}
 +
 +#else
 +
 +#define n800_tmp105_set_power NULL
 +
 +#endif
 +
 +static struct omap_uart_config n800_uart_config __initdata = {
 +      .enabled_uarts = (1 << 0) | (1 << 2),
 +};
 +
 +#include "../../../drivers/cbus/retu.h"
 +
 +static struct omap_fbmem_config n800_fbmem0_config __initdata = {
 +      .size = 752 * 1024,
 +};
 +
 +static struct omap_fbmem_config n800_fbmem1_config __initdata = {
 +      .size = 752 * 1024,
 +};
 +
 +static struct omap_fbmem_config n800_fbmem2_config __initdata = {
 +      .size = 752 * 1024,
 +};
 +
 +static struct omap_tmp105_config n800_tmp105_config __initdata = {
 +      .tmp105_irq_pin = 125,
 +      .set_power = n800_tmp105_set_power,
 +};
 +
 +static void mipid_shutdown(struct mipid_platform_data *pdata)
 +{
 +      if (pdata->nreset_gpio != -1) {
 +              pr_info("shutdown LCD\n");
 +              omap_set_gpio_dataout(pdata->nreset_gpio, 0);
 +              msleep(120);
 +      }
 +}
 +
 +static struct mipid_platform_data n800_mipid_platform_data = {
 +      .shutdown = mipid_shutdown,
 +};
 +
 +static void __init mipid_dev_init(void)
 +{
 +      const struct omap_lcd_config *conf;
 +
 +      conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config);
 +      if (conf != NULL) {
 +              n800_mipid_platform_data.nreset_gpio = conf->nreset_gpio;
 +              n800_mipid_platform_data.data_lines = conf->data_lines;
 +      }
 +}
 +
 +static struct {
 +      struct clk *sys_ck;
 +} blizzard;
 +
 +static int blizzard_get_clocks(void)
 +{
 +      blizzard.sys_ck = clk_get(0, "osc_ck");
 +      if (IS_ERR(blizzard.sys_ck)) {
 +              printk(KERN_ERR "can't get Blizzard clock\n");
 +              return PTR_ERR(blizzard.sys_ck);
 +      }
 +      return 0;
 +}
 +
 +static unsigned long blizzard_get_clock_rate(struct device *dev)
 +{
 +      return clk_get_rate(blizzard.sys_ck);
 +}
 +
 +static void blizzard_enable_clocks(int enable)
 +{
 +      if (enable)
 +              clk_enable(blizzard.sys_ck);
 +      else
 +              clk_disable(blizzard.sys_ck);
 +}
 +
 +static void blizzard_power_up(struct device *dev)
 +{
 +      /* Vcore to 1.475V */
 +      tahvo_set_clear_reg_bits(0x07, 0, 0xf);
 +      msleep(10);
 +
 +      blizzard_enable_clocks(1);
 +      omap_set_gpio_dataout(N800_BLIZZARD_POWERDOWN_GPIO, 1);
 +}
 +
 +static void blizzard_power_down(struct device *dev)
 +{
 +      omap_set_gpio_dataout(N800_BLIZZARD_POWERDOWN_GPIO, 0);
 +      blizzard_enable_clocks(0);
 +
 +      /* Vcore to 1.005V */
 +      tahvo_set_clear_reg_bits(0x07, 0xf, 0);
 +}
 +
 +static struct blizzard_platform_data n800_blizzard_data = {
 +      .power_up       = blizzard_power_up,
 +      .power_down     = blizzard_power_down,
 +      .get_clock_rate = blizzard_get_clock_rate,
 +      .te_connected   = 1,
 +};
 +
 +static void __init blizzard_dev_init(void)
 +{
 +      int r;
 +
 +      r = omap_request_gpio(N800_BLIZZARD_POWERDOWN_GPIO);
 +      if (r < 0)
 +              return;
 +      omap_set_gpio_direction(N800_BLIZZARD_POWERDOWN_GPIO, 0);
 +      omap_set_gpio_dataout(N800_BLIZZARD_POWERDOWN_GPIO, 1);
 +
 +      blizzard_get_clocks();
 +      omapfb_set_ctrl_platform_data(&n800_blizzard_data);
 +}
 +
 +static struct omap_mmc_config n800_mmc_config __initdata = {
 +      .mmc [0] = {
 +              .enabled                = 1,
 +              .wire4                  = 1,
 +      },
 +};
 +
 +extern struct omap_mmc_platform_data n800_mmc_data;
 +
 +static struct omap_board_config_kernel n800_config[] __initdata = {
 +      { OMAP_TAG_UART,                        &n800_uart_config },
 +      { OMAP_TAG_FBMEM,                       &n800_fbmem0_config },
 +      { OMAP_TAG_FBMEM,                       &n800_fbmem1_config },
 +      { OMAP_TAG_FBMEM,                       &n800_fbmem2_config },
 +      { OMAP_TAG_TMP105,                      &n800_tmp105_config },
 +      { OMAP_TAG_MMC,                         &n800_mmc_config },
 +};
 +
 +static struct tsc2301_platform_data tsc2301_config = {
 +      .reset_gpio     = N800_TSC2301_RESET_GPIO,
 +      .keymap = {
 +              -1,             /* Event for bit 0 */
 +              KEY_UP,         /* Event for bit 1 (up) */
 +              KEY_F5,         /* Event for bit 2 (home) */
 +              -1,             /* Event for bit 3 */
 +              KEY_LEFT,       /* Event for bit 4 (left) */
 +              KEY_ENTER,      /* Event for bit 5 (enter) */
 +              KEY_RIGHT,      /* Event for bit 6 (right) */
 +              -1,             /* Event for bit 7 */
 +              KEY_ESC,        /* Event for bit 8 (cycle) */
 +              KEY_DOWN,       /* Event for bit 9 (down) */
 +              KEY_F4,         /* Event for bit 10 (menu) */
 +              -1,             /* Event for bit 11 */
 +              KEY_F8,         /* Event for bit 12 (Zoom-) */
 +              KEY_F6,         /* Event for bit 13 (FS) */
 +              KEY_F7,         /* Event for bit 14 (Zoom+) */
 +              -1,             /* Event for bit 15 */
 +      },
 +      .kp_rep         = 0,
 +      .keyb_name      = "Internal keypad",
 +};
 +
 +static void tsc2301_dev_init(void)
 +{
 +      int r;
 +      int gpio = N800_KEYB_IRQ_GPIO;
 +
 +      r = gpio_request(gpio, "tsc2301 KBD IRQ");
 +      if (r >= 0) {
 +              gpio_direction_input(gpio);
 +              tsc2301_config.keyb_int = OMAP_GPIO_IRQ(gpio);
 +      } else {
 +              printk(KERN_ERR "unable to get KBD GPIO");
 +      }
 +
 +      gpio = N800_DAV_IRQ_GPIO;
 +      r = gpio_request(gpio, "tsc2301 DAV IRQ");
 +      if (r >= 0) {
 +              gpio_direction_input(gpio);
 +              tsc2301_config.dav_int = OMAP_GPIO_IRQ(gpio);
 +      } else {
 +              printk(KERN_ERR "unable to get DAV GPIO");
 +      }
 +}
 +
 +static int __init tea5761_dev_init(void)
 +{
 +      const struct omap_tea5761_config *info;
 +      int enable_gpio = 0;
 +
 +      info = omap_get_config(OMAP_TAG_TEA5761, struct omap_tea5761_config);
 +      if (info)
 +              enable_gpio = info->enable_gpio;
 +
 +      if (enable_gpio) {
 +              pr_debug("Enabling tea5761 at GPIO %d\n",
 +                       enable_gpio);
 +
 +              if (omap_request_gpio(enable_gpio) < 0) {
 +                      printk(KERN_ERR "Can't request GPIO %d\n",
 +                             enable_gpio);
 +                      return -ENODEV;
 +              }
 +
 +              omap_set_gpio_direction(enable_gpio, 0);
 +              udelay(50);
 +              omap_set_gpio_dataout(enable_gpio, 1);
 +      }
 +
 +      return 0;
 +}
 +
 +static struct omap2_mcspi_device_config tsc2301_mcspi_config = {
 +      .turbo_mode     = 0,
 +      .single_channel = 1,
 +};
 +
 +static struct omap2_mcspi_device_config mipid_mcspi_config = {
 +      .turbo_mode     = 0,
 +      .single_channel = 1,
 +};
 +
 +static struct omap2_mcspi_device_config cx3110x_mcspi_config = {
 +      .turbo_mode     = 0,
 +      .single_channel = 1,
 +};
 +
 +#ifdef CONFIG_TOUCHSCREEN_TSC2005
 +static struct tsc2005_platform_data tsc2005_config = {
 +      .reset_gpio = 94,
 +      .dav_gpio = 106
 +};
 +
 +static struct omap2_mcspi_device_config tsc2005_mcspi_config = {
 +      .turbo_mode     = 0,
 +      .single_channel = 1,
 +};
 +#endif
 +
 +static struct spi_board_info n800_spi_board_info[] __initdata = {
 +      {
 +              .modalias       = "lcd_mipid",
 +              .bus_num        = 1,
 +              .chip_select    = 1,
 +              .max_speed_hz   = 4000000,
 +              .controller_data= &mipid_mcspi_config,
 +              .platform_data  = &n800_mipid_platform_data,
 +      }, {
 +              .modalias       = "cx3110x",
 +              .bus_num        = 2,
 +              .chip_select    = 0,
 +              .max_speed_hz   = 48000000,
 +              .controller_data= &cx3110x_mcspi_config,
 +      },
 +      {
 +              .modalias       = "tsc2301",
 +              .bus_num        = 1,
 +              .chip_select    = 0,
 +              .max_speed_hz   = 6000000,
 +              .controller_data= &tsc2301_mcspi_config,
 +              .platform_data  = &tsc2301_config,
 +      },
 +};
 +
 +static struct spi_board_info n810_spi_board_info[] __initdata = {
 +      {
 +              .modalias        = "lcd_mipid",
 +              .bus_num         = 1,
 +              .chip_select     = 1,
 +              .max_speed_hz    = 4000000,
 +              .controller_data = &mipid_mcspi_config,
 +              .platform_data   = &n800_mipid_platform_data,
 +      },
 +      {
 +              .modalias        = "cx3110x",
 +              .bus_num         = 2,
 +              .chip_select     = 0,
 +              .max_speed_hz    = 48000000,
 +              .controller_data = &cx3110x_mcspi_config,
 +      },
 +      {
 +              .modalias        = "tsc2005",
 +              .bus_num         = 1,
 +              .chip_select     = 0,
 +              .max_speed_hz    = 6000000,
 +              .controller_data = &tsc2005_mcspi_config,
 +              .platform_data   = &tsc2005_config,
 +      },
 +};
 +
 +static void __init tsc2005_set_config(void)
 +{
 +      const struct omap_lcd_config *conf;
 +
 +      conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config);
 +      if (conf != NULL) {
 +#ifdef CONFIG_TOUCHSCREEN_TSC2005
 +              if (strcmp(conf->panel_name, "lph8923") == 0) {
 +                      tsc2005_config.ts_x_plate_ohm = 180;
 +                      tsc2005_config.ts_hw_avg = 0;
 +                      tsc2005_config.ts_ignore_last = 0;
 +                      tsc2005_config.ts_touch_pressure = 1500;
 +                      tsc2005_config.ts_stab_time = 100;
 +                      tsc2005_config.ts_pressure_max = 2048;
 +                      tsc2005_config.ts_pressure_fudge = 2;
 +                      tsc2005_config.ts_x_max = 4096;
 +                      tsc2005_config.ts_x_fudge = 4;
 +                      tsc2005_config.ts_y_max = 4096;
 +                      tsc2005_config.ts_y_fudge = 7;
 +              } else if (strcmp(conf->panel_name, "ls041y3") == 0) {
 +                      tsc2005_config.ts_x_plate_ohm = 280;
 +                      tsc2005_config.ts_hw_avg = 0;
 +                      tsc2005_config.ts_ignore_last = 0;
 +                      tsc2005_config.ts_touch_pressure = 1500;
 +                      tsc2005_config.ts_stab_time = 1000;
 +                      tsc2005_config.ts_pressure_max = 2048;
 +                      tsc2005_config.ts_pressure_fudge = 2;
 +                      tsc2005_config.ts_x_max = 4096;
 +                      tsc2005_config.ts_x_fudge = 4;
 +                      tsc2005_config.ts_y_max = 4096;
 +                      tsc2005_config.ts_y_fudge = 7;
 +              } else {
 +                      printk(KERN_ERR "Unknown panel type, set default "
 +                             "touchscreen configuration\n");
 +                      tsc2005_config.ts_x_plate_ohm = 200;
 +                      tsc2005_config.ts_stab_time = 100;
 +              }
 +#endif
 +      }
 +}
 +
 +#if defined(CONFIG_CBUS_RETU) && defined(CONFIG_LEDS_OMAP_PWM)
 +
 +void retu_keypad_led_set_power(struct omap_pwm_led_platform_data *self,
 +                             int on_off)
 +{
 +      if (on_off) {
 +              retu_write_reg(RETU_REG_CTRL_SET, 1 << 6);
 +              msleep(2);
 +              retu_write_reg(RETU_REG_CTRL_SET, 1 << 3);
 +      } else {
 +              retu_write_reg(RETU_REG_CTRL_CLR, (1 << 6) | (1 << 3));
 +      }
 +}
 +
 +static struct omap_pwm_led_platform_data n800_keypad_led_data = {
 +      .name = "keypad",
 +      .intensity_timer = 10,
 +      .blink_timer = 9,
 +      .set_power = retu_keypad_led_set_power,
 +};
 +
 +static struct platform_device n800_keypad_led_device = {
 +      .name           = "omap_pwm_led",
 +      .id             = -1,
 +      .dev            = {
 +              .platform_data = &n800_keypad_led_data,
 +      },
 +};
 +#endif
 +
 +#if defined(CONFIG_TOUCHSCREEN_TSC2301)
 +static void __init n800_ts_set_config(void)
 +{
 +      const struct omap_lcd_config *conf;
 +
 +      conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config);
 +      if (conf != NULL) {
 +              if (strcmp(conf->panel_name, "lph8923") == 0) {
 +                      tsc2301_config.ts_x_plate_ohm   = 180;
 +                      tsc2301_config.ts_hw_avg        = 8;
 +                      tsc2301_config.ts_max_pressure  = 2048;
 +                      tsc2301_config.ts_touch_pressure = 400;
 +                      tsc2301_config.ts_stab_time     = 100;
 +                      tsc2301_config.ts_pressure_fudge = 2;
 +                      tsc2301_config.ts_x_max         = 4096;
 +                      tsc2301_config.ts_x_fudge       = 4;
 +                      tsc2301_config.ts_y_max         = 4096;
 +                      tsc2301_config.ts_y_fudge       = 7;
 +              } else if (strcmp(conf->panel_name, "ls041y3") == 0) {
 +                      tsc2301_config.ts_x_plate_ohm   = 280;
 +                      tsc2301_config.ts_hw_avg        = 8;
 +                      tsc2301_config.ts_touch_pressure = 400;
 +                      tsc2301_config.ts_max_pressure  = 2048;
 +                      tsc2301_config.ts_stab_time     = 1000;
 +                      tsc2301_config.ts_pressure_fudge = 2;
 +                      tsc2301_config.ts_x_max         = 4096;
 +                      tsc2301_config.ts_x_fudge       = 4;
 +                      tsc2301_config.ts_y_max         = 4096;
 +                      tsc2301_config.ts_y_fudge       = 7;
 +              } else {
 +                      printk(KERN_ERR "Unknown panel type, set default "
 +                             "touchscreen configuration\n");
 +                      tsc2301_config.ts_x_plate_ohm   = 200;
 +                      tsc2301_config.ts_stab_time     = 100;
 +              }
 +      }
 +}
 +#else
 +static inline void n800_ts_set_config(void)
 +{
 +}
 +#endif
 +
 +static struct omap_gpio_switch n800_gpio_switches[] __initdata = {
 +      {
 +              .name                   = "bat_cover",
 +              .gpio                   = -1,
 +              .debounce_rising        = 100,
 +              .debounce_falling       = 0,
 +              .notify                 = n800_mmc_slot1_cover_handler,
 +              .notify_data            = NULL,
 +      }, {
 +              .name                   = "headphone",
 +              .gpio                   = -1,
 +              .debounce_rising        = 200,
 +              .debounce_falling       = 200,
 +      }, {
 +              .name                   = "cam_act",
 +              .gpio                   = -1,
 +              .debounce_rising        = 200,
 +              .debounce_falling       = 200,
 +      }, {
 +              .name                   = "cam_turn",
 +              .gpio                   = -1,
 +              .debounce_rising        = 100,
 +              .debounce_falling       = 100,
 +      },
 +};
 +
 +static struct platform_device *n800_devices[] __initdata = {
 +#if defined(CONFIG_CBUS_RETU) && defined(CONFIG_LEDS_OMAP_PWM)
 +      &n800_keypad_led_device,
 +#endif
 +};
 +
 +#ifdef CONFIG_MENELAUS
 +static int n800_auto_sleep_regulators(void)
 +{
 +      u32 val;
 +      int ret;
 +
 +      val = EN_VPLL_SLEEP | EN_VMMC_SLEEP    \
 +              | EN_VAUX_SLEEP | EN_VIO_SLEEP \
 +              | EN_VMEM_SLEEP | EN_DC3_SLEEP \
 +              | EN_VC_SLEEP | EN_DC2_SLEEP;
 +
 +      ret = menelaus_set_regulator_sleep(1, val);
 +      if (ret < 0) {
 +              printk(KERN_ERR "Could not set regulators to sleep on "
 +                      "menelaus: %u\n", ret);
 +              return ret;
 +      }
 +      return 0;
 +}
 +
 +static int n800_auto_voltage_scale(void)
 +{
 +      int ret;
 +
 +      ret = menelaus_set_vcore_hw(1400, 1050);
 +      if (ret < 0) {
 +              printk(KERN_ERR "Could not set VCORE voltage on "
 +                      "menelaus: %u\n", ret);
 +              return ret;
 +      }
 +      return 0;
 +}
 +
 +static int n800_menelaus_init(struct device *dev)
 +{
 +      int ret;
 +
 +      ret = n800_auto_voltage_scale();
 +      if (ret < 0)
 +              return ret;
 +      ret = n800_auto_sleep_regulators();
 +      if (ret < 0)
 +              return ret;
 +      return 0;
 +}
 +
 +static struct menelaus_platform_data n800_menelaus_platform_data = {
 +      .late_init = n800_menelaus_init,
 +};
 +#endif
 +
 +static struct i2c_board_info __initdata n800_i2c_board_info_1[] = {
 +      {
 +              I2C_BOARD_INFO("menelaus", 0x72),
 +              .irq = INT_24XX_SYS_NIRQ,
 +              .platform_data = &n800_menelaus_platform_data,
 +      },
 +};
 +
 +extern struct tcm825x_platform_data n800_tcm825x_platform_data;
 +
 +static struct i2c_board_info __initdata_or_module n8x0_i2c_board_info_2[] = {
 +      {
 +              I2C_BOARD_INFO(TCM825X_NAME, TCM825X_I2C_ADDR),
++#if defined (CONFIG_VIDEO_TCM825X) || defined (CONFIG_VIDEO_TCM825X_MODULE)
 +              .platform_data = &n800_tcm825x_platform_data,
++#endif
 +      },
 +      {
 +              I2C_BOARD_INFO("tsl2563", 0x29),
 +      },
 +      {
 +              I2C_BOARD_INFO("lp5521", 0x32),
 +      },
 +};
 +
 +
 +static struct i2c_board_info __initdata_or_module n800_i2c_board_info_2[] = {
 +      {
 +              I2C_BOARD_INFO("tea5761", 0x10),
 +      },
 +};
 +
 +static struct i2c_board_info __initdata_or_module n810_i2c_board_info_2[] = {
 +      {
 +              I2C_BOARD_INFO("lm8323", 0x45),
 +              .irq            = OMAP_GPIO_IRQ(109),
 +              .platform_data  = &lm8323_pdata,
 +      },
 +};
 +
 +void __init nokia_n800_common_init(void)
 +{
 +      platform_add_devices(n800_devices, ARRAY_SIZE(n800_devices));
 +
 +      n800_flash_init();
 +      n800_mmc_init();
 +      n800_bt_init();
 +      n800_dsp_init();
 +      n800_usb_init();
 +      n800_cam_init();
 +      if (machine_is_nokia_n800())
 +              spi_register_board_info(n800_spi_board_info,
 +                              ARRAY_SIZE(n800_spi_board_info));
 +      if (machine_is_nokia_n810()) {
 +              tsc2005_set_config();
 +              spi_register_board_info(n810_spi_board_info,
 +                              ARRAY_SIZE(n810_spi_board_info));
 +      }
 +      omap_serial_init();
 +      omap_register_i2c_bus(1, 400, n800_i2c_board_info_1,
 +                            ARRAY_SIZE(n800_i2c_board_info_1));
 +      omap_register_i2c_bus(2, 400, n8x0_i2c_board_info_2,
 +                            ARRAY_SIZE(n800_i2c_board_info_2));
 +      if (machine_is_nokia_n800())
 +              i2c_register_board_info(2, n800_i2c_board_info_2,
 +                      ARRAY_SIZE(n800_i2c_board_info_2));
 +      if (machine_is_nokia_n810())
 +              i2c_register_board_info(2, n810_i2c_board_info_2,
 +                      ARRAY_SIZE(n810_i2c_board_info_2));
 +              
 +      mipid_dev_init();
 +      blizzard_dev_init();
 +}
 +
 +static void __init nokia_n800_init(void)
 +{
 +      nokia_n800_common_init();
 +
 +      n800_audio_init(&tsc2301_config);
 +      n800_ts_set_config();
 +      tsc2301_dev_init();
 +      tea5761_dev_init();
 +      omap_register_gpio_switches(n800_gpio_switches,
 +                                  ARRAY_SIZE(n800_gpio_switches));
 +}
 +
 +void __init nokia_n800_map_io(void)
 +{
 +      omap_board_config = n800_config;
 +      omap_board_config_size = ARRAY_SIZE(n800_config);
 +
 +      omap2_set_globals_242x();
 +      omap2_map_common_io();
 +}
 +
 +MACHINE_START(NOKIA_N800, "Nokia N800")
 +      .phys_io        = 0x48000000,
 +      .io_pg_offst    = ((0xd8000000) >> 18) & 0xfffc,
 +      .boot_params    = 0x80000100,
 +      .map_io         = nokia_n800_map_io,
 +      .init_irq       = nokia_n800_init_irq,
 +      .init_machine   = nokia_n800_init,
 +      .timer          = &omap_timer,
 +MACHINE_END
diff --combined arch/arm/mm/Kconfig
index 84c138789e0036df99016b87c0d321ca98bff5c1,ed15f876c7254cd02ea86d53b5346cfa4efc67d0..546d7e7db74e63685c4f659e46f504555382d965
@@@ -180,8 -180,21 +180,21 @@@ config CPU_ARM925
  # 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 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_AT91CAP9 || ARCH_NS9XXX || ARCH_DAVINCI
-       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 || ARCH_AT91SAM9RL || ARCH_AT91CAP9 || ARCH_NS9XXX || ARCH_DAVINCI
+       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 || ARCH_AT91SAM9RL || \
+               ARCH_AT91SAM9G20 || ARCH_AT91CAP9 || \
+               ARCH_NS9XXX || ARCH_DAVINCI || ARCH_MX2
+       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 || ARCH_AT91SAM9RL || \
+               ARCH_AT91SAM9G20 || ARCH_AT91CAP9 || \
+               ARCH_NS9XXX || ARCH_DAVINCI || ARCH_MX2
        select CPU_32v5
        select CPU_ABRT_EV5TJ
        select CPU_PABRT_NOIFAR
@@@ -365,7 -378,7 +378,7 @@@ config CPU_XSC
  # Feroceon
  config CPU_FEROCEON
        bool
-       depends on ARCH_ORION5X
+       depends on ARCH_ORION5X || ARCH_LOKI || ARCH_KIRKWOOD || ARCH_MV78XX0
        default y
        select CPU_32v5
        select CPU_ABRT_EV5T
        select CPU_CACHE_VIVT
        select CPU_CP15_MMU
        select CPU_COPY_FEROCEON if MMU
-       select CPU_TLB_V4WBI if MMU
+       select CPU_TLB_FEROCEON if MMU
  
  config CPU_FEROCEON_OLD_ID
        bool "Accept early Feroceon cores with an ARM926 ID"
@@@ -415,7 -428,7 +428,7 @@@ config CPU_32v6
  # ARMv7
  config CPU_V7
        bool "Support ARM V7 processor"
 -      depends on ARCH_INTEGRATOR || MACH_REALVIEW_EB
 +      depends on ARCH_INTEGRATOR || MACH_REALVIEW_EB || ARCH_OMAP3
        select CPU_32v6K
        select CPU_32v7
        select CPU_ABRT_EV7
@@@ -551,6 -564,11 +564,11 @@@ config CPU_TLB_V4WB
          ARM Architecture Version 4 TLB with writeback cache and invalidate
          instruction cache entry.
  
+ config CPU_TLB_FEROCEON
+       bool
+       help
+         Feroceon TLB (v4wbi with non-outer-cachable page table walks).
  config CPU_TLB_V6
        bool
  
@@@ -709,6 -727,14 +727,14 @@@ config OUTER_CACH
        bool
        default n
  
+ config CACHE_FEROCEON_L2
+       bool "Enable the Feroceon L2 cache controller"
+       depends on ARCH_KIRKWOOD || ARCH_MV78XX0
+       default y
+       select OUTER_CACHE
+       help
+         This option enables the Feroceon L2 cache controller.
  config CACHE_L2X0
        bool "Enable the L2x0 outer cache controller"
        depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176
        select OUTER_CACHE
        help
          This option enables the L2x0 PrimeCell.
+ config CACHE_XSC3L2
+       bool "Enable the L2 cache on XScale3"
+       depends on CPU_XSC3
+       default y
+       select OUTER_CACHE
+       help
+         This option enables the L2 cache on XScale3.
index 7a61d0e185a9e7d5ec22615f1a025e6832630762,0000000000000000000000000000000000000000..7c94fc3c080bd3eb854d30ad9c8e0d1505e85e56
mode 100644,000000..100644
--- /dev/null
@@@ -1,550 -1,0 +1,550 @@@
-                       set_irq_type(OMAP_GPIO_IRQ(sw->gpio), IRQT_FALLING);
 +/*
 + *  linux/arch/arm/plat-omap/gpio-switch.c
 + *
 + *  Copyright (C) 2004-2006 Nokia Corporation
 + *  Written by Juha Yrjölä <juha.yrjola@nokia.com>
 + *         and Paul Mundt <paul.mundt@nokia.com>
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +
 +#include <linux/sched.h>
 +#include <linux/init.h>
 +#include <linux/list.h>
 +#include <linux/irq.h>
 +#include <linux/interrupt.h>
 +#include <linux/module.h>
 +#include <linux/platform_device.h>
 +#include <linux/timer.h>
 +#include <linux/err.h>
 +#include <asm/arch/hardware.h>
 +#include <asm/arch/gpio.h>
 +#include <asm/arch/irqs.h>
 +#include <asm/arch/mux.h>
 +#include <asm/arch/board.h>
 +#include <asm/arch/gpio-switch.h>
 +
 +struct gpio_switch {
 +      char            name[14];
 +      u16             gpio;
 +      unsigned        flags:4;
 +      unsigned        type:4;
 +      unsigned        state:1;
 +      unsigned        both_edges:1;
 +
 +      u16             debounce_rising;
 +      u16             debounce_falling;
 +
 +      void (* notify)(void *data, int state);
 +      void *notify_data;
 +
 +      struct work_struct      work;
 +      struct timer_list       timer;
 +      struct platform_device  pdev;
 +
 +      struct list_head        node;
 +};
 +
 +static LIST_HEAD(gpio_switches);
 +static struct platform_device *gpio_sw_platform_dev;
 +static struct platform_driver gpio_sw_driver;
 +
 +static const struct omap_gpio_switch *board_gpio_sw_table;
 +static int board_gpio_sw_count;
 +
 +static const char *cover_str[2] = { "open", "closed" };
 +static const char *connection_str[2] = { "disconnected", "connected" };
 +static const char *activity_str[2] = { "inactive", "active" };
 +
 +/*
 + * GPIO switch state default debounce delay in ms
 + */
 +#define OMAP_GPIO_SW_DEFAULT_DEBOUNCE         10
 +
 +static const char **get_sw_str(struct gpio_switch *sw)
 +{
 +      switch (sw->type) {
 +      case OMAP_GPIO_SWITCH_TYPE_COVER:
 +              return cover_str;
 +      case OMAP_GPIO_SWITCH_TYPE_CONNECTION:
 +              return connection_str;
 +      case OMAP_GPIO_SWITCH_TYPE_ACTIVITY:
 +              return activity_str;
 +      default:
 +              BUG();
 +              return NULL;
 +      }
 +}
 +
 +static const char *get_sw_type(struct gpio_switch *sw)
 +{
 +      switch (sw->type) {
 +      case OMAP_GPIO_SWITCH_TYPE_COVER:
 +              return "cover";
 +      case OMAP_GPIO_SWITCH_TYPE_CONNECTION:
 +              return "connection";
 +      case OMAP_GPIO_SWITCH_TYPE_ACTIVITY:
 +              return "activity";
 +      default:
 +              BUG();
 +              return NULL;
 +      }
 +}
 +
 +static void print_sw_state(struct gpio_switch *sw, int state)
 +{
 +      const char **str;
 +
 +      str = get_sw_str(sw);
 +      if (str != NULL)
 +              printk(KERN_INFO "%s (GPIO %d) is now %s\n", sw->name, sw->gpio, str[state]);
 +}
 +
 +static int gpio_sw_get_state(struct gpio_switch *sw)
 +{
 +      int state;
 +
 +      state = omap_get_gpio_datain(sw->gpio);
 +      if (sw->flags & OMAP_GPIO_SWITCH_FLAG_INVERTED)
 +              state = !state;
 +
 +      return state;
 +}
 +
 +static ssize_t gpio_sw_state_store(struct device *dev,
 +                                 struct device_attribute *attr,
 +                                 const char *buf,
 +                                 size_t count)
 +{
 +      struct gpio_switch *sw = dev_get_drvdata(dev);
 +      const char **str;
 +      char state[16];
 +      int enable;
 +
 +      if (!(sw->flags & OMAP_GPIO_SWITCH_FLAG_OUTPUT))
 +              return -EPERM;
 +
 +      if (sscanf(buf, "%15s", state) != 1)
 +              return -EINVAL;
 +
 +      str = get_sw_str(sw);
 +      if (strcmp(state, str[0]) == 0)
 +              sw->state = enable = 0;
 +      else if (strcmp(state, str[1]) == 0)
 +              sw->state = enable = 1;
 +      else
 +              return -EINVAL;
 +
 +      if (sw->flags & OMAP_GPIO_SWITCH_FLAG_INVERTED)
 +              enable = !enable;
 +      omap_set_gpio_dataout(sw->gpio, enable);
 +
 +      return count;
 +}
 +
 +static ssize_t gpio_sw_state_show(struct device *dev,
 +                                struct device_attribute *attr,
 +                                char *buf)
 +{
 +      struct gpio_switch *sw = dev_get_drvdata(dev);
 +      const char **str;
 +
 +      str = get_sw_str(sw);
 +      return sprintf(buf, "%s\n", str[sw->state]);
 +}
 +
 +static DEVICE_ATTR(state, S_IRUGO | S_IWUSR, gpio_sw_state_show,
 +                 gpio_sw_state_store);
 +
 +static ssize_t gpio_sw_type_show(struct device *dev,
 +                               struct device_attribute *attr,
 +                               char *buf)
 +{
 +      struct gpio_switch *sw = dev_get_drvdata(dev);
 +
 +      return sprintf(buf, "%s\n", get_sw_type(sw));
 +}
 +
 +static DEVICE_ATTR(type, S_IRUGO, gpio_sw_type_show, NULL);
 +
 +static ssize_t gpio_sw_direction_show(struct device *dev,
 +                                    struct device_attribute *attr,
 +                                    char *buf)
 +{
 +      struct gpio_switch *sw = dev_get_drvdata(dev);
 +      int is_output;
 +
 +      is_output = sw->flags & OMAP_GPIO_SWITCH_FLAG_OUTPUT;
 +      return sprintf(buf, "%s\n", is_output ? "output" : "input");
 +}
 +
 +static DEVICE_ATTR(direction, S_IRUGO, gpio_sw_direction_show, NULL);
 +
 +
 +static irqreturn_t gpio_sw_irq_handler(int irq, void *arg)
 +{
 +      struct gpio_switch *sw = arg;
 +      unsigned long timeout;
 +      int state;
 +
 +      if (!sw->both_edges) {
 +              if (omap_get_gpio_datain(sw->gpio))
-                       set_irq_type(OMAP_GPIO_IRQ(sw->gpio), IRQT_RISING);
++                      set_irq_type(OMAP_GPIO_IRQ(sw->gpio), IRQ_TYPE_EDGE_FALLING);
 +              else
++                      set_irq_type(OMAP_GPIO_IRQ(sw->gpio), IRQ_TYPE_EDGE_RISING);
 +      }
 +
 +      state = gpio_sw_get_state(sw);
 +      if (sw->state == state)
 +              return IRQ_HANDLED;
 +
 +      if (state)
 +              timeout = sw->debounce_rising;
 +      else
 +              timeout = sw->debounce_falling;
 +      if (!timeout)
 +              schedule_work(&sw->work);
 +      else
 +              mod_timer(&sw->timer, jiffies + msecs_to_jiffies(timeout));
 +
 +      return IRQ_HANDLED;
 +}
 +
 +static void gpio_sw_timer(unsigned long arg)
 +{
 +      struct gpio_switch *sw = (struct gpio_switch *) arg;
 +
 +      schedule_work(&sw->work);
 +}
 +
 +static void gpio_sw_handler(struct work_struct *work)
 +{
 +      struct gpio_switch *sw = container_of(work, struct gpio_switch, work);
 +      int state;
 +
 +      state = gpio_sw_get_state(sw);
 +      if (sw->state == state)
 +              return;
 +
 +      sw->state = state;
 +      if (sw->notify != NULL)
 +              sw->notify(sw->notify_data, state);
 +      sysfs_notify(&sw->pdev.dev.kobj, NULL, "state");
 +      print_sw_state(sw, state);
 +}
 +
 +static int __init can_do_both_edges(struct gpio_switch *sw)
 +{
 +      if (!cpu_class_is_omap1())
 +              return 1;
 +      if (OMAP_GPIO_IS_MPUIO(sw->gpio))
 +              return 0;
 +      else
 +              return 1;
 +}
 +
 +static void gpio_sw_release(struct device *dev)
 +{
 +}
 +
 +static int __init new_switch(struct gpio_switch *sw)
 +{
 +      int r, direction, trigger;
 +
 +      switch (sw->type) {
 +      case OMAP_GPIO_SWITCH_TYPE_COVER:
 +      case OMAP_GPIO_SWITCH_TYPE_CONNECTION:
 +      case OMAP_GPIO_SWITCH_TYPE_ACTIVITY:
 +              break;
 +      default:
 +              printk(KERN_ERR "invalid GPIO switch type: %d\n", sw->type);
 +              return -EINVAL;
 +      }
 +
 +      sw->pdev.name   = sw->name;
 +      sw->pdev.id     = -1;
 +
 +      sw->pdev.dev.parent = &gpio_sw_platform_dev->dev;
 +      sw->pdev.dev.driver = &gpio_sw_driver.driver;
 +      sw->pdev.dev.release = gpio_sw_release;
 +
 +      r = platform_device_register(&sw->pdev);
 +      if (r) {
 +              printk(KERN_ERR "gpio-switch: platform device registration "
 +                     "failed for %s", sw->name);
 +              return r;
 +      }
 +      dev_set_drvdata(&sw->pdev.dev, sw);
 +
 +      r = omap_request_gpio(sw->gpio);
 +      if (r < 0) {
 +              platform_device_unregister(&sw->pdev);
 +              return r;
 +      }
 +
 +      /* input: 1, output: 0 */
 +      direction = !(sw->flags & OMAP_GPIO_SWITCH_FLAG_OUTPUT);
 +      omap_set_gpio_direction(sw->gpio, direction);
 +
 +      sw->state = gpio_sw_get_state(sw);
 +
 +      r = 0;
 +      r |= device_create_file(&sw->pdev.dev, &dev_attr_state);
 +      r |= device_create_file(&sw->pdev.dev, &dev_attr_type);
 +      r |= device_create_file(&sw->pdev.dev, &dev_attr_direction);
 +      if (r)
 +              printk(KERN_ERR "gpio-switch: attribute file creation "
 +                     "failed for %s\n", sw->name);
 +
 +      if (!direction)
 +              return 0;
 +
 +      if (can_do_both_edges(sw)) {
 +              trigger = IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING;
 +              sw->both_edges = 1;
 +      } else {
 +              if (omap_get_gpio_datain(sw->gpio))
 +                      trigger = IRQF_TRIGGER_FALLING;
 +              else
 +                      trigger = IRQF_TRIGGER_RISING;
 +      }
 +      r = request_irq(OMAP_GPIO_IRQ(sw->gpio), gpio_sw_irq_handler,
 +                      IRQF_SHARED | trigger, sw->name, sw);
 +      if (r < 0) {
 +              printk(KERN_ERR "gpio-switch: request_irq() failed "
 +                     "for GPIO %d\n", sw->gpio);
 +              platform_device_unregister(&sw->pdev);
 +              omap_free_gpio(sw->gpio);
 +              return r;
 +      }
 +
 +      INIT_WORK(&sw->work, gpio_sw_handler);
 +      init_timer(&sw->timer);
 +
 +      sw->timer.function = gpio_sw_timer;
 +      sw->timer.data = (unsigned long)sw;
 +
 +      list_add(&sw->node, &gpio_switches);
 +
 +      return 0;
 +}
 +
 +static int __init add_atag_switches(void)
 +{
 +      const struct omap_gpio_switch_config *cfg;
 +      struct gpio_switch *sw;
 +      int i, r;
 +
 +      for (i = 0; ; i++) {
 +              cfg = omap_get_nr_config(OMAP_TAG_GPIO_SWITCH,
 +                                       struct omap_gpio_switch_config, i);
 +              if (cfg == NULL)
 +                      break;
 +              sw = kzalloc(sizeof(*sw), GFP_KERNEL);
 +              if (sw == NULL) {
 +                      printk(KERN_ERR "gpio-switch: kmalloc failed\n");
 +                      return -ENOMEM;
 +              }
 +              strncpy(sw->name, cfg->name, sizeof(cfg->name));
 +              sw->gpio = cfg->gpio;
 +              sw->flags = cfg->flags;
 +              sw->type = cfg->type;
 +              sw->debounce_rising = OMAP_GPIO_SW_DEFAULT_DEBOUNCE;
 +              sw->debounce_falling = OMAP_GPIO_SW_DEFAULT_DEBOUNCE;
 +              if ((r = new_switch(sw)) < 0) {
 +                      kfree(sw);
 +                      return r;
 +              }
 +      }
 +      return 0;
 +}
 +
 +static struct gpio_switch * __init find_switch(int gpio, const char *name)
 +{
 +      struct gpio_switch *sw;
 +
 +      list_for_each_entry(sw, &gpio_switches, node) {
 +              if ((gpio < 0 || sw->gpio != gpio) &&
 +                  (name == NULL || strcmp(sw->name, name) != 0))
 +                      continue;
 +
 +              if (gpio < 0 || name == NULL)
 +                      goto no_check;
 +
 +              if (strcmp(sw->name, name) != 0)
 +                      printk("gpio-switch: name mismatch for %d (%s, %s)\n",
 +                             gpio, name, sw->name);
 +              else if (sw->gpio != gpio)
 +                      printk("gpio-switch: GPIO mismatch for %s (%d, %d)\n",
 +                             name, gpio, sw->gpio);
 +no_check:
 +              return sw;
 +      }
 +      return NULL;
 +}
 +
 +static int __init add_board_switches(void)
 +{
 +      int i;
 +
 +      for (i = 0; i < board_gpio_sw_count; i++) {
 +              const struct omap_gpio_switch *cfg;
 +              struct gpio_switch *sw;
 +              int r;
 +
 +              cfg = board_gpio_sw_table + i;
 +              if (strlen(cfg->name) > sizeof(sw->name) - 1)
 +                      return -EINVAL;
 +              /* Check whether we only update an existing switch
 +               * or add a new switch. */
 +              sw = find_switch(cfg->gpio, cfg->name);
 +              if (sw != NULL) {
 +                      sw->debounce_rising = cfg->debounce_rising;
 +                      sw->debounce_falling = cfg->debounce_falling;
 +                      sw->notify = cfg->notify;
 +                      sw->notify_data = cfg->notify_data;
 +                      continue;
 +              } else {
 +                      if (cfg->gpio < 0 || cfg->name == NULL) {
 +                              printk("gpio-switch: required switch not "
 +                                     "found (%d, %s)\n", cfg->gpio,
 +                                     cfg->name);
 +                              continue;
 +                      }
 +              }
 +              sw = kzalloc(sizeof(*sw), GFP_KERNEL);
 +              if (sw == NULL) {
 +                      printk(KERN_ERR "gpio-switch: kmalloc failed\n");
 +                      return -ENOMEM;
 +              }
 +              strlcpy(sw->name, cfg->name, sizeof(sw->name));
 +              sw->gpio = cfg->gpio;
 +              sw->flags = cfg->flags;
 +              sw->type = cfg->type;
 +              sw->debounce_rising = cfg->debounce_rising;
 +              sw->debounce_falling = cfg->debounce_falling;
 +              sw->notify = cfg->notify;
 +              sw->notify_data = cfg->notify_data;
 +              if ((r = new_switch(sw)) < 0) {
 +                      kfree(sw);
 +                      return r;
 +              }
 +      }
 +      return 0;
 +}
 +
 +static void gpio_sw_cleanup(void)
 +{
 +      struct gpio_switch *sw = NULL, *old = NULL;
 +
 +      list_for_each_entry(sw, &gpio_switches, node) {
 +              if (old != NULL)
 +                      kfree(old);
 +              flush_scheduled_work();
 +              del_timer_sync(&sw->timer);
 +
 +              free_irq(OMAP_GPIO_IRQ(sw->gpio), sw);
 +
 +              device_remove_file(&sw->pdev.dev, &dev_attr_state);
 +              device_remove_file(&sw->pdev.dev, &dev_attr_type);
 +              device_remove_file(&sw->pdev.dev, &dev_attr_direction);
 +
 +              platform_device_unregister(&sw->pdev);
 +              omap_free_gpio(sw->gpio);
 +              old = sw;
 +      }
 +      kfree(old);
 +}
 +
 +static void __init report_initial_state(void)
 +{
 +      struct gpio_switch *sw;
 +
 +      list_for_each_entry(sw, &gpio_switches, node) {
 +              int state;
 +
 +              state = omap_get_gpio_datain(sw->gpio);
 +              if (sw->flags & OMAP_GPIO_SWITCH_FLAG_INVERTED)
 +                      state = !state;
 +              if (sw->notify != NULL)
 +                      sw->notify(sw->notify_data, state);
 +              print_sw_state(sw, state);
 +      }
 +}
 +
 +static int gpio_sw_remove(struct platform_device *dev)
 +{
 +      return 0;
 +}
 +
 +static struct platform_driver gpio_sw_driver = {
 +      .remove         = gpio_sw_remove,
 +      .driver         = {
 +              .name   = "gpio-switch",
 +      },
 +};
 +
 +void __init omap_register_gpio_switches(const struct omap_gpio_switch *tbl,
 +                                      int count)
 +{
 +      BUG_ON(board_gpio_sw_table != NULL);
 +
 +      board_gpio_sw_table = tbl;
 +      board_gpio_sw_count = count;
 +}
 +
 +static int __init gpio_sw_init(void)
 +{
 +      int r;
 +
 +      printk(KERN_INFO "OMAP GPIO switch handler initializing\n");
 +
 +      r = platform_driver_register(&gpio_sw_driver);
 +      if (r)
 +              return r;
 +
 +      gpio_sw_platform_dev = platform_device_register_simple("gpio-switch",
 +                                                             -1, NULL, 0);
 +      if (IS_ERR(gpio_sw_platform_dev)) {
 +              r = PTR_ERR(gpio_sw_platform_dev);
 +              goto err1;
 +      }
 +
 +      r = add_atag_switches();
 +      if (r < 0)
 +              goto err2;
 +
 +      r = add_board_switches();
 +      if (r < 0)
 +              goto err2;
 +
 +      report_initial_state();
 +
 +      return 0;
 +err2:
 +      gpio_sw_cleanup();
 +      platform_device_unregister(gpio_sw_platform_dev);
 +err1:
 +      platform_driver_unregister(&gpio_sw_driver);
 +      return r;
 +}
 +
 +static void __exit gpio_sw_exit(void)
 +{
 +      gpio_sw_cleanup();
 +      platform_device_unregister(gpio_sw_platform_dev);
 +      platform_driver_unregister(&gpio_sw_driver);
 +}
 +
 +#ifndef MODULE
 +late_initcall(gpio_sw_init);
 +#else
 +module_init(gpio_sw_init);
 +#endif
 +module_exit(gpio_sw_exit);
 +
 +MODULE_AUTHOR("Juha Yrjölä <juha.yrjola@nokia.com>, Paul Mundt <paul.mundt@nokia.com");
 +MODULE_DESCRIPTION("GPIO switch driver");
 +MODULE_LICENSE("GPL");
diff --combined drivers/Makefile
index efd304112d18c26c99ebe250bf599f5250d52b9f,a280ab3d0833fa29e8ae031bbb53bfdba37c4191..39cfe4034d1aeab2c795de77af08bb4bc599a4a3
@@@ -5,7 -5,7 +5,7 @@@
  # Rewritten to use lists instead of if-statements.
  #
  
- obj-$(CONFIG_HAVE_GPIO_LIB)   += gpio/
+ obj-y                         += gpio/
  obj-$(CONFIG_PCI)             += pci/
  obj-$(CONFIG_PARISC)          += parisc/
  obj-$(CONFIG_RAPIDIO)         += rapidio/
@@@ -22,21 -22,18 +22,24 @@@ obj-$(CONFIG_XEN)          += xen
  # default.
  obj-y                         += char/
  
+ # gpu/ comes after char for AGP vs DRM startup
+ obj-y                         += gpu/
  obj-$(CONFIG_CONNECTOR)               += connector/
  
  # i810fb and intelfb depend on char/agp/
  obj-$(CONFIG_FB_I810)           += video/i810/
  obj-$(CONFIG_FB_INTEL)          += video/intelfb/
  
 +# we also need input/serio early so serio bus is initialized by the time
 +# serial drivers start registering their serio ports
 +obj-$(CONFIG_SERIO)           += input/serio/
  obj-y                         += serial/
  obj-$(CONFIG_PARPORT)         += parport/
 -obj-y                         += base/ block/ misc/ mfd/ net/ media/
 +obj-y                         += base/ block/ misc/ mfd/ net/ media/ cbus/
 +obj-y                         += i2c/
 +obj-y                         += cbus/
 +obj-$(CONFIG_ARCH_OMAP)               += dsp/dspgateway/
  obj-$(CONFIG_NUBUS)           += nubus/
  obj-$(CONFIG_ATM)             += atm/
  obj-y                         += macintosh/
@@@ -60,13 -57,14 +63,13 @@@ obj-$(CONFIG_ATA_OVER_ETH) += block/aoe
  obj-$(CONFIG_PARIDE)          += block/paride/
  obj-$(CONFIG_TC)              += tc/
  obj-$(CONFIG_USB)             += usb/
 +obj-$(CONFIG_USB_MUSB_HDRC)   += usb/musb/
  obj-$(CONFIG_PCI)             += usb/
  obj-$(CONFIG_USB_GADGET)      += usb/gadget/
 -obj-$(CONFIG_SERIO)           += input/serio/
  obj-$(CONFIG_GAMEPORT)                += input/gameport/
  obj-$(CONFIG_INPUT)           += input/
  obj-$(CONFIG_I2O)             += message/
  obj-$(CONFIG_RTC_LIB)         += rtc/
 -obj-y                         += i2c/
  obj-$(CONFIG_W1)              += w1/
  obj-$(CONFIG_POWER_SUPPLY)    += power/
  obj-$(CONFIG_HWMON)           += hwmon/
@@@ -99,3 -97,4 +102,4 @@@ obj-$(CONFIG_PPC_PS3)                += ps3
  obj-$(CONFIG_OF)              += of/
  obj-$(CONFIG_SSB)             += ssb/
  obj-$(CONFIG_VIRTIO)          += virtio/
+ obj-$(CONFIG_REGULATOR)               += regulator/
index 455f18ccbf278e31f3a5850439490ae507786bcd,a235ca787465f5bb0d310fd4211635492f43dc26..9b423c1491fe8b13750e31bfd9277d350450edda
@@@ -71,6 -71,7 +71,7 @@@ config BT_HCIUART_H
  config BT_HCIUART_BCSP
        bool "BCSP protocol support"
        depends on BT_HCIUART
+       select BITREVERSE
        help
          BCSP (BlueCore Serial Protocol) is serial protocol for communication 
          between Bluetooth device and host. This protocol is required for non
@@@ -182,27 -183,6 +183,27 @@@ config BT_HCIBTUAR
          Say Y here to compile support for HCI UART devices into the
          kernel or say M to compile it as module (btuart_cs).
  
 +config BT_HCIBRF6150
 +      tristate "HCI TI BRF6150 driver with H4 extensions"
 +      depends on BT && ARCH_OMAP
 +      help
 +        Bluetooth HCI driver for TI BRF6150 with H4 extensions.
 +        This driver provides support for BRF6150 Bluetooth chip 
 +        with vendor-specific H4 extensions.
 +
 +        Say Y here to compile support for TI BRF6150 devices into the
 +        kernel or say M to compile it as module (brf6150).
 +
 +config BT_HCIH4P
 +      tristate "HCI driver with H4 Nokia extensions"
 +      depends on BT && ARCH_OMAP 
 +      help 
 +        Bluetooth HCI driver with H4 extensions.  This driver provides
 +        support for H4+ Bluetooth chip with vendor-specific H4 extensions.
 +
 +        Say Y here to compile support for h4 extended devices into the kernel
 +        or say M to compile it as module (hci_h4p).
 +
  config BT_HCIVHCI
        tristate "HCI VHCI (Virtual HCI device) driver"
        help
index 4bb38d990917f0584bdfe0c8e83d4ada9729a0d2,0000000000000000000000000000000000000000..ccb7f089d1b63e44ccb60e8b1990ec976069f89a
mode 100644,000000..100644
--- /dev/null
@@@ -1,1041 -1,0 +1,1041 @@@
-       set_irq_type(OMAP_GPIO_IRQ(info->btinfo->host_wakeup_gpio), IRQT_NOEDGE);
 +/*
 + *  linux/drivers/bluetooth/brf6150/brf6150.c
 + *
 + *  Copyright (C) 2005 Nokia Corporation
 + *  Written by Ville Tervo <ville.tervo@nokia.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. 
 + *
 + *  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/module.h>
 +
 +#include <linux/kernel.h>
 +#include <linux/init.h>
 +#include <linux/errno.h>
 +#include <linux/delay.h>
 +#include <linux/spinlock.h>
 +#include <linux/serial_reg.h>
 +#include <linux/skbuff.h>
 +#include <linux/firmware.h>
 +#include <linux/irq.h>
 +#include <linux/timer.h>
 +#include <linux/clk.h>
 +#include <linux/platform_device.h>
 +
 +#include <asm/arch/hardware.h>
 +#include <asm/arch/gpio.h>
 +#include <asm/arch/board.h>
 +#include <asm/arch/irqs.h>
 +
 +#include <net/bluetooth/bluetooth.h>
 +#include <net/bluetooth/hci_core.h>
 +#include <net/bluetooth/hci.h>
 +
 +#include "brf6150.h"
 +
 +#if 0
 +#define NBT_DBG(fmt, arg...)  printk("%s: " fmt "" , __FUNCTION__ , ## arg)
 +#else
 +#define NBT_DBG(...)
 +#endif
 +
 +#if 0
 +#define NBT_DBG_FW(fmt, arg...)  printk("%s: " fmt "" , __FUNCTION__ , ## arg)
 +#else
 +#define NBT_DBG_FW(...)
 +#endif
 +
 +#if 0
 +#define NBT_DBG_POWER(fmt, arg...)  printk("%s: " fmt "" , __FUNCTION__ , ## arg)
 +#else
 +#define NBT_DBG_POWER(...)
 +#endif
 +
 +#if 0
 +#define NBT_DBG_TRANSFER(fmt, arg...)  printk("%s: " fmt "" , __FUNCTION__ , ## arg)
 +#else
 +#define NBT_DBG_TRANSFER(...)
 +#endif
 +
 +#if 0
 +#define NBT_DBG_TRANSFER_NF(fmt, arg...)  printk(fmt "" , ## arg)
 +#else
 +#define NBT_DBG_TRANSFER_NF(...)
 +#endif
 +
 +#define PM_TIMEOUT (2000)
 +
 +static void brf6150_device_release(struct device *dev);
 +static struct brf6150_info *exit_info;
 +
 +static struct platform_device brf6150_device = {
 +      .name           = BT_DEVICE,
 +      .id             = -1,
 +      .num_resources  = 0,
 +      .dev = {
 +              .release = brf6150_device_release,
 +      }
 +};
 +
 +static struct device_driver brf6150_driver = {
 +      .name           = BT_DRIVER,
 +      .bus            = &platform_bus_type,
 +};
 +
 +static inline void brf6150_outb(struct brf6150_info *info, unsigned int offset, u8 val)
 +{
 +      outb(val, info->uart_base + (offset << 2));
 +}
 +
 +static inline u8 brf6150_inb(struct brf6150_info *info, unsigned int offset)
 +{
 +      return inb(info->uart_base + (offset << 2));
 +}
 +
 +static void brf6150_set_rts(struct brf6150_info *info, int active)
 +{
 +      u8 b;
 +
 +      b = brf6150_inb(info, UART_MCR);
 +      if (active)
 +              b |= UART_MCR_RTS;
 +      else
 +              b &= ~UART_MCR_RTS;
 +      brf6150_outb(info, UART_MCR, b);
 +}
 +
 +static void brf6150_wait_for_cts(struct brf6150_info *info, int active,
 +                               int timeout_ms)
 +{
 +      int okay;
 +      unsigned long timeout;
 +
 +      okay = 0;
 +      timeout = jiffies + msecs_to_jiffies(timeout_ms);
 +      for (;;) {
 +              int state;
 +
 +              state = brf6150_inb(info, UART_MSR) & UART_MSR_CTS;
 +              if (active) {
 +                      if (state)
 +                              break;
 +              } else {
 +                      if (!state)
 +                              break;
 +              }
 +              if (jiffies > timeout)
 +                      break;
 +      }
 +}
 +
 +static inline void brf6150_set_auto_ctsrts(struct brf6150_info *info, int on)
 +{
 +      u8 lcr, b;
 +
 +      lcr = brf6150_inb(info, UART_LCR);
 +      brf6150_outb(info, UART_LCR, 0xbf);
 +      b = brf6150_inb(info, UART_EFR);
 +      if (on)
 +              b |= UART_EFR_CTS | UART_EFR_RTS;
 +      else
 +              b &= ~(UART_EFR_CTS | UART_EFR_RTS);
 +      brf6150_outb(info, UART_EFR, b);
 +      brf6150_outb(info, UART_LCR, lcr);
 +}
 +
 +static inline void brf6150_enable_pm_rx(struct brf6150_info *info)
 +{
 +      if (info->pm_enabled) {
 +              info->rx_pm_enabled = 1;
 +      }
 +}
 +
 +static inline void brf6150_disable_pm_rx(struct brf6150_info *info)
 +{
 +      if (info->pm_enabled) {
 +              info->rx_pm_enabled = 0;
 +      }
 +}
 +
 +static void brf6150_enable_pm_tx(struct brf6150_info *info)
 +{
 +      if (info->pm_enabled) {
 +              mod_timer(&info->pm_timer, jiffies + msecs_to_jiffies(PM_TIMEOUT));
 +              info->tx_pm_enabled = 1;
 +      }
 +}
 +
 +static void brf6150_disable_pm_tx(struct brf6150_info *info)
 +{
 +      if (info->pm_enabled) {
 +              info->tx_pm_enabled = 0;
 +              omap_set_gpio_dataout(info->btinfo->bt_wakeup_gpio, 1);
 +      }
 +      if (omap_get_gpio_datain(info->btinfo->host_wakeup_gpio))
 +              tasklet_schedule(&info->tx_task);
 +}
 +
 +static void brf6150_pm_timer(unsigned long data)
 +{
 +      struct brf6150_info *info;
 +
 +      info = (struct brf6150_info *)data;
 +      if (info->tx_pm_enabled && info->rx_pm_enabled && !test_bit(HCI_INQUIRY, &info->hdev->flags))
 +              omap_set_gpio_dataout(info->btinfo->bt_wakeup_gpio, 0);
 +      else
 +              mod_timer(&info->pm_timer, jiffies + msecs_to_jiffies(PM_TIMEOUT));
 +}
 +
 +static int brf6150_change_speed(struct brf6150_info *info, unsigned long speed)
 +{
 +      unsigned int divisor;
 +      u8 lcr, mdr1;
 +
 +      NBT_DBG("Setting speed %lu\n", speed);
 +
 +      if (speed >= 460800) {
 +              divisor = UART_CLOCK / 13 / speed;
 +              mdr1 = 3;
 +      } else {
 +              divisor = UART_CLOCK / 16 / speed;
 +              mdr1 = 0;
 +      }
 +
 +      brf6150_outb(info, UART_OMAP_MDR1, 7); /* Make sure UART mode is disabled */
 +      lcr = brf6150_inb(info, UART_LCR);
 +      brf6150_outb(info, UART_LCR, UART_LCR_DLAB);     /* Set DLAB */
 +      brf6150_outb(info, UART_DLL, divisor & 0xff);    /* Set speed */
 +      brf6150_outb(info, UART_DLM, divisor >> 8);
 +      brf6150_outb(info, UART_LCR, lcr);
 +      brf6150_outb(info, UART_OMAP_MDR1, mdr1); /* Make sure UART mode is enabled */
 +
 +      return 0;
 +}
 +
 +/* Firmware handling */
 +static int brf6150_open_firmware(struct brf6150_info *info)
 +{
 +      int err;
 +
 +      info->fw_pos = 0;
 +      err = request_firmware(&info->fw_entry, "brf6150fw.bin", &brf6150_device.dev);
 +
 +      return err;
 +}
 +
 +static struct sk_buff *brf6150_read_fw_cmd(struct brf6150_info *info, int how)
 +{
 +      struct sk_buff *skb;
 +      unsigned int cmd_len;
 +
 +      if (info->fw_pos >= info->fw_entry->size) {
 +              return NULL;
 +      }
 +
 +      cmd_len = info->fw_entry->data[info->fw_pos++];
 +      if (!cmd_len)
 +              return NULL;
 +
 +      if (info->fw_pos + cmd_len > info->fw_entry->size) {
 +              printk(KERN_WARNING "Corrupted firmware image\n");
 +              return NULL;
 +      }
 +
 +      skb = bt_skb_alloc(cmd_len, how);
 +      if (!skb) {
 +              printk(KERN_WARNING "Cannot reserve memory for buffer\n");
 +              return NULL;
 +      }
 +      memcpy(skb_put(skb, cmd_len), &info->fw_entry->data[info->fw_pos], cmd_len);
 +
 +      info->fw_pos += cmd_len;
 +
 +      return skb;
 +}
 +
 +static int brf6150_close_firmware(struct brf6150_info *info)
 +{
 +      release_firmware(info->fw_entry);
 +      return 0;
 +}
 +
 +static int brf6150_send_alive_packet(struct brf6150_info *info)
 +{
 +      struct sk_buff *skb;
 +
 +      NBT_DBG("Sending alive packet\n");
 +      skb = brf6150_read_fw_cmd(info, GFP_ATOMIC);
 +      if (!skb) {
 +              printk(KERN_WARNING "Cannot read alive command");
 +              return -1;
 +      }
 +
 +      clk_enable(info->uart_ck);
 +      skb_queue_tail(&info->txq, skb);
 +      tasklet_schedule(&info->tx_task);
 +
 +      NBT_DBG("Alive packet sent\n");
 +      return 0;
 +}
 +
 +static void brf6150_alive_packet(struct brf6150_info *info, struct sk_buff *skb)
 +{
 +      NBT_DBG("Received alive packet\n");
 +      if (skb->data[1] == 0xCC) {
 +              complete(&info->init_completion);
 +      }
 +
 +      kfree_skb(skb);
 +}
 +
 +static int brf6150_send_negotiation(struct brf6150_info *info)
 +{
 +      struct sk_buff *skb;
 +      NBT_DBG("Sending negotiation..\n");
 +
 +      brf6150_change_speed(info, INIT_SPEED);
 +
 +      skb = brf6150_read_fw_cmd(info, GFP_KERNEL);
 +
 +      if (!skb) {
 +              printk(KERN_WARNING "Cannot read negoatiation message");
 +              return -1;
 +      }
 +
 +      clk_enable(info->uart_ck);
 +      skb_queue_tail(&info->txq, skb);
 +      tasklet_schedule(&info->tx_task);
 +
 +
 +      NBT_DBG("Negotiation sent\n");
 +      return 0;
 +}
 +
 +static void brf6150_negotiation_packet(struct brf6150_info *info,
 +                                     struct sk_buff *skb)
 +{
 +      if (skb->data[1] == 0x20) {
 +              /* Change to operational settings */
 +              brf6150_set_rts(info, 0);
 +              brf6150_wait_for_cts(info, 0, 100);
 +              brf6150_change_speed(info, MAX_BAUD_RATE);
 +              brf6150_set_rts(info, 1);
 +              brf6150_wait_for_cts(info, 1, 100);
 +              brf6150_set_auto_ctsrts(info, 1);
 +              brf6150_send_alive_packet(info);
 +      } else {
 +              printk(KERN_WARNING "Could not negotiate brf6150 settings\n");
 +      }
 +      kfree_skb(skb);
 +}
 +
 +static int brf6150_get_hdr_len(u8 pkt_type)
 +{
 +      long retval;
 +
 +      switch (pkt_type) {
 +      case H4_EVT_PKT:
 +              retval = HCI_EVENT_HDR_SIZE;
 +              break;
 +      case H4_ACL_PKT:
 +              retval = HCI_ACL_HDR_SIZE;
 +              break;
 +      case H4_SCO_PKT:
 +              retval = HCI_SCO_HDR_SIZE;
 +              break;
 +      case H4_NEG_PKT:
 +              retval = 9;
 +              break;
 +      case H4_ALIVE_PKT:
 +              retval = 3;
 +              break;
 +      default:
 +              printk(KERN_ERR "brf6150: Unknown H4 packet");
 +              retval = -1;
 +              break;
 +      }
 +
 +      return retval;
 +}
 +
 +static unsigned int brf6150_get_data_len(struct brf6150_info *info,
 +                                       struct sk_buff *skb)
 +{
 +      long retval = -1;
 +      struct hci_event_hdr *evt_hdr;
 +      struct hci_acl_hdr *acl_hdr;
 +      struct hci_sco_hdr *sco_hdr;
 +
 +      switch (bt_cb(skb)->pkt_type) {
 +      case H4_EVT_PKT:
 +              evt_hdr = (struct hci_event_hdr *)skb->data;
 +              retval = evt_hdr->plen;
 +              break;
 +      case H4_ACL_PKT:
 +              acl_hdr = (struct hci_acl_hdr *)skb->data;
 +              retval = le16_to_cpu(acl_hdr->dlen);
 +              break;
 +      case H4_SCO_PKT:
 +              sco_hdr = (struct hci_sco_hdr *)skb->data;
 +              retval = sco_hdr->dlen;
 +              break;
 +      case H4_NEG_PKT:
 +              retval = 0;
 +              break;
 +      case H4_ALIVE_PKT:
 +              retval = 0;
 +              break;
 +      }
 +
 +      return retval;
 +}
 +
 +static void brf6150_parse_fw_event(struct brf6150_info *info)
 +{
 +      struct hci_fw_event *ev;
 +
 +      if (bt_cb(info->rx_skb)->pkt_type != H4_EVT_PKT) {
 +              printk(KERN_WARNING "Got non event fw packet.\n");
 +              info->fw_error = 1;
 +              return;
 +      }
 +
 +      ev = (struct hci_fw_event *)info->rx_skb->data;
 +      if (ev->hev.evt != HCI_EV_CMD_COMPLETE) {
 +              printk(KERN_WARNING "Got non cmd complete fw event\n");
 +              info->fw_error = 1;
 +              return;
 +      }
 +
 +      if (ev->status != 0) {
 +              printk(KERN_WARNING "Got error status from fw command\n");
 +              info->fw_error = 1;
 +              return;
 +      }
 +
 +      complete(&info->fw_completion);
 +}
 +
 +static inline void brf6150_recv_frame(struct brf6150_info *info,
 +                                    struct sk_buff *skb)
 +{
 +      if (unlikely(!test_bit(HCI_RUNNING, &info->hdev->flags))) {
 +              NBT_DBG("fw_event\n");
 +              brf6150_parse_fw_event(info);
 +              kfree_skb(skb);
 +      } else {
 +              hci_recv_frame(skb);
 +              if (!(brf6150_inb(info, UART_LSR) & UART_LSR_DR))
 +                      brf6150_enable_pm_rx(info);
 +              NBT_DBG("Frame sent to upper layer\n");
 +      }
 +
 +}
 +
 +static inline void brf6150_rx(struct brf6150_info *info)
 +{
 +      u8 byte;
 +
 +      NBT_DBG_TRANSFER("rx_tasklet woke up\ndata ");
 +
 +      while (brf6150_inb(info, UART_LSR) & UART_LSR_DR) {
 +              if (info->rx_skb == NULL) {
 +                      info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
 +                      if (!info->rx_skb) {
 +                              printk(KERN_WARNING "brf6150: Can't allocate memory for new packet\n");
 +                              return;
 +                      }
 +                      info->rx_state = WAIT_FOR_PKT_TYPE;
 +                      info->rx_skb->dev = (void *)info->hdev;
 +                      brf6150_disable_pm_rx(info);
 +                      clk_enable(info->uart_ck);
 +              }
 +
 +              byte = brf6150_inb(info, UART_RX);
 +              if (info->garbage_bytes) {
 +                      info->garbage_bytes--;
 +                      info->hdev->stat.err_rx++;
 +                      continue;
 +              }
 +              info->hdev->stat.byte_rx++;
 +              NBT_DBG_TRANSFER_NF("0x%.2x  ", byte);
 +              switch (info->rx_state) {
 +              case WAIT_FOR_PKT_TYPE:
 +                      bt_cb(info->rx_skb)->pkt_type = byte;
 +                      info->rx_count = brf6150_get_hdr_len(byte);
 +                      if (info->rx_count >= 0) {
 +                              info->rx_state = WAIT_FOR_HEADER;
 +                      } else {
 +                              info->hdev->stat.err_rx++;
 +                              kfree_skb(info->rx_skb);
 +                              info->rx_skb = NULL;
 +                              clk_disable(info->uart_ck);
 +                      }
 +                      break;
 +              case WAIT_FOR_HEADER:
 +                      info->rx_count--;
 +                      *skb_put(info->rx_skb, 1) = byte;
 +                      if (info->rx_count == 0) {
 +                              info->rx_count = brf6150_get_data_len(info, info->rx_skb);
 +                              if (info->rx_count > skb_tailroom(info->rx_skb)) {
 +                                      printk(KERN_WARNING "brf6150: Frame is %ld bytes too long.\n",
 +                                             info->rx_count - skb_tailroom(info->rx_skb));
 +                                      info->rx_skb = NULL;
 +                                      info->garbage_bytes = info->rx_count - skb_tailroom(info->rx_skb);
 +                                      clk_disable(info->uart_ck);
 +                                      break;
 +                              }
 +                              info->rx_state = WAIT_FOR_DATA;
 +                              if (bt_cb(info->rx_skb)->pkt_type == H4_NEG_PKT) {
 +                                      brf6150_negotiation_packet(info, info->rx_skb);
 +                                      info->rx_skb = NULL;
 +                                      clk_disable(info->uart_ck);
 +                                      return;
 +                              }
 +                              if (bt_cb(info->rx_skb)->pkt_type == H4_ALIVE_PKT) {
 +                                      brf6150_alive_packet(info, info->rx_skb);
 +                                      info->rx_skb = NULL;
 +                                      clk_disable(info->uart_ck);
 +                                      return;
 +                              }
 +                      }
 +                      break;
 +              case WAIT_FOR_DATA:
 +                      info->rx_count--;
 +                      *skb_put(info->rx_skb, 1) = byte;
 +                      if (info->rx_count == 0) {
 +                              brf6150_recv_frame(info, info->rx_skb);
 +                              info->rx_skb = NULL;
 +                              clk_disable(info->uart_ck);
 +                      }
 +                      break;
 +              default:
 +                      WARN_ON(1);
 +                      break;
 +              }
 +      }
 +
 +      NBT_DBG_TRANSFER_NF("\n");
 +}
 +
 +static void brf6150_tx_tasklet(unsigned long data)
 +{
 +      unsigned int sent = 0;
 +      unsigned long flags;
 +      struct sk_buff *skb;
 +      struct brf6150_info *info = (struct brf6150_info *)data;
 +
 +      NBT_DBG_TRANSFER("tx_tasklet woke up\n data ");
 +
 +      skb = skb_dequeue(&info->txq);
 +      if (!skb) {
 +              /* No data in buffer */
 +              brf6150_enable_pm_tx(info);
 +              return;
 +      }
 +
 +      /* Copy data to tx fifo */
 +      while (!(brf6150_inb(info, UART_OMAP_SSR) & UART_OMAP_SSR_TXFULL) &&
 +             (sent < skb->len)) {
 +              NBT_DBG_TRANSFER_NF("0x%.2x ", skb->data[sent]);
 +              brf6150_outb(info, UART_TX, skb->data[sent]);
 +              sent++;
 +      }
 +
 +      info->hdev->stat.byte_tx += sent;
 +      NBT_DBG_TRANSFER_NF("\n");
 +      if (skb->len == sent) {
 +              kfree_skb(skb);
 +              clk_disable(info->uart_ck);
 +      } else {
 +              skb_pull(skb, sent);
 +              skb_queue_head(&info->txq, skb);
 +      }
 +
 +      spin_lock_irqsave(&info->lock, flags);
 +      brf6150_outb(info, UART_IER, brf6150_inb(info, UART_IER) | UART_IER_THRI);
 +      spin_unlock_irqrestore(&info->lock, flags);
 +}
 +
 +static irqreturn_t brf6150_interrupt(int irq, void *data)
 +{
 +      struct brf6150_info *info = (struct brf6150_info *)data;
 +      u8 iir, msr;
 +      int ret;
 +      unsigned long flags;
 +
 +      ret = IRQ_NONE;
 +
 +      clk_enable(info->uart_ck);
 +      iir = brf6150_inb(info, UART_IIR);
 +      if (iir & UART_IIR_NO_INT) {
 +              printk("Interrupt but no reason irq 0x%.2x\n", iir);
 +              clk_disable(info->uart_ck);
 +              return IRQ_HANDLED;
 +      }
 +
 +      NBT_DBG("In interrupt handler iir 0x%.2x\n", iir);
 +
 +      iir &= UART_IIR_ID;
 +
 +      if (iir == UART_IIR_MSI) {
 +              msr = brf6150_inb(info, UART_MSR);
 +              ret = IRQ_HANDLED;
 +      }
 +      if (iir == UART_IIR_RLSI) {
 +              brf6150_inb(info, UART_RX);
 +              brf6150_inb(info, UART_LSR);
 +              ret = IRQ_HANDLED;
 +      }
 +
 +      if (iir == UART_IIR_RDI) {
 +              brf6150_rx(info);
 +              ret = IRQ_HANDLED;
 +      }
 +
 +      if (iir == UART_IIR_THRI) {
 +              spin_lock_irqsave(&info->lock, flags);
 +              brf6150_outb(info, UART_IER, brf6150_inb(info, UART_IER) & ~UART_IER_THRI);
 +              spin_unlock_irqrestore(&info->lock, flags);
 +              tasklet_schedule(&info->tx_task);
 +              ret = IRQ_HANDLED;
 +      }
 +
 +      clk_disable(info->uart_ck);
 +      return ret;
 +}
 +
 +static irqreturn_t brf6150_wakeup_interrupt(int irq, void *dev_inst)
 +{
 +      struct brf6150_info *info = dev_inst;
 +      int should_wakeup;
 +      unsigned long flags;
 +
 +      spin_lock_irqsave(&info->lock, flags);
 +      should_wakeup = omap_get_gpio_datain(info->btinfo->host_wakeup_gpio);
 +      NBT_DBG_POWER("gpio interrupt %d\n", should_wakeup);
 +      if (should_wakeup) {
 +              clk_enable(info->uart_ck);
 +              brf6150_set_auto_ctsrts(info, 1);
 +              brf6150_rx(info);
 +              tasklet_schedule(&info->tx_task);
 +      } else {
 +              brf6150_set_auto_ctsrts(info, 0);
 +              brf6150_set_rts(info, 0);
 +              clk_disable(info->uart_ck);
 +      }
 +
 +      spin_unlock_irqrestore(&info->lock, flags);
 +      return IRQ_HANDLED;
 +}
 +
 +static int brf6150_init_uart(struct brf6150_info *info)
 +{
 +      int count = 0;
 +
 +      /* Reset the  UART */
 +      brf6150_outb(info, UART_OMAP_SYSC, UART_SYSC_OMAP_RESET);
 +      while (!(brf6150_inb(info, UART_OMAP_SYSS) & UART_SYSS_RESETDONE)) {
 +              if (count++ > 100) {
 +                      printk(KERN_ERR "brf6150: UART reset timeout\n");
 +                      return -1;
 +              }
 +              udelay(1);
 +      }
 +
 +      /* Enable and setup FIFO */
 +      brf6150_outb(info, UART_LCR, UART_LCR_WLEN8);
 +      brf6150_outb(info, UART_OMAP_MDR1, 0x00); /* Make sure UART mode is enabled */
 +      brf6150_outb(info, UART_OMAP_SCR, 0x00);
 +      brf6150_outb(info, UART_EFR, brf6150_inb(info, UART_EFR) | UART_EFR_ECB);
 +      brf6150_outb(info, UART_MCR, brf6150_inb(info, UART_MCR) | UART_MCR_TCRTLR);
 +      brf6150_outb(info, UART_TI752_TLR, 0xff);
 +      brf6150_outb(info, UART_TI752_TCR, 0x1f);
 +      brf6150_outb(info, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
 +      brf6150_outb(info, UART_IER, UART_IER_RDI);
 +
 +      return 0;
 +}
 +
 +static int brf6150_reset(struct brf6150_info *info)
 +{
 +      omap_set_gpio_dataout(info->btinfo->bt_wakeup_gpio, 0);
 +      omap_set_gpio_dataout(info->btinfo->reset_gpio, 0);
 +      current->state = TASK_UNINTERRUPTIBLE;
 +      schedule_timeout(msecs_to_jiffies(10));
 +      omap_set_gpio_dataout(info->btinfo->bt_wakeup_gpio, 1);
 +      current->state = TASK_UNINTERRUPTIBLE;
 +      schedule_timeout(msecs_to_jiffies(100));
 +      omap_set_gpio_dataout(info->btinfo->reset_gpio, 1);
 +      current->state = TASK_UNINTERRUPTIBLE;
 +      schedule_timeout(msecs_to_jiffies(100));
 +
 +      return 0;
 +}
 +
 +static int brf6150_send_firmware(struct brf6150_info *info)
 +{
 +      struct sk_buff *skb;
 +
 +      init_completion(&info->fw_completion);
 +      info->fw_error = 0;
 +
 +      while ((skb = brf6150_read_fw_cmd(info, GFP_KERNEL)) != NULL) {
 +              clk_enable(info->uart_ck);
 +              skb_queue_tail(&info->txq, skb);
 +              tasklet_schedule(&info->tx_task);
 +
 +              if (!wait_for_completion_timeout(&info->fw_completion, HZ)) {
 +                      return -1;
 +              }
 +
 +              if (info->fw_error) {
 +                      return -1;
 +              }
 +      }
 +      NBT_DBG_FW("Firmware sent\n");
 +
 +      return 0;
 +
 +}
 +
 +/* hci callback functions */
 +static int brf6150_hci_flush(struct hci_dev *hdev)
 +{
 +      struct brf6150_info *info;
 +      info = hdev->driver_data;
 +
 +      skb_queue_purge(&info->txq);
 +
 +      return 0;
 +}
 +
 +static int brf6150_hci_open(struct hci_dev *hdev)
 +{
 +      struct brf6150_info *info;
 +      int err;
 +
 +      info = hdev->driver_data;
 +
 +      if (test_bit(HCI_RUNNING, &hdev->flags))
 +              return 0;
 +
 +      if (brf6150_open_firmware(info) < 0) {
 +              printk("Cannot open firmware\n");
 +              return -1;
 +      }
 +
 +      info->rx_state = WAIT_FOR_PKT_TYPE;
 +      info->rx_count = 0;
 +      info->garbage_bytes = 0;
 +      info->rx_skb = NULL;
 +      info->pm_enabled = 0;
-       set_irq_type(OMAP_GPIO_IRQ(info->btinfo->host_wakeup_gpio), IRQT_BOTHEDGE);
++      set_irq_type(OMAP_GPIO_IRQ(info->btinfo->host_wakeup_gpio), IRQ_TYPE_NONE);
 +      init_completion(&info->fw_completion);
 +
 +      clk_enable(info->uart_ck);
 +
 +      brf6150_init_uart(info);
 +      brf6150_set_auto_ctsrts(info, 0);
 +      brf6150_set_rts(info, 0);
 +      brf6150_reset(info);
 +      brf6150_wait_for_cts(info, 1, 10);
 +      brf6150_set_rts(info, 1);
 +      if (brf6150_send_negotiation(info)) {
 +              brf6150_close_firmware(info);
 +              return -1;
 +      }
 +
 +      if (!wait_for_completion_interruptible_timeout(&info->init_completion, HZ)) {
 +              brf6150_close_firmware(info);
 +              clk_disable(info->uart_ck);
 +              clear_bit(HCI_RUNNING, &hdev->flags);
 +              return -1;
 +      }
 +      brf6150_set_auto_ctsrts(info, 1);
 +
 +      err = brf6150_send_firmware(info);
 +      brf6150_close_firmware(info);
 +      if (err < 0)
 +              printk(KERN_ERR "brf6150: Sending firmware failed. Bluetooth won't work properly\n");
 +
-       set_irq_type(OMAP_GPIO_IRQ(info->btinfo->host_wakeup_gpio), IRQT_NOEDGE);
++      set_irq_type(OMAP_GPIO_IRQ(info->btinfo->host_wakeup_gpio), IRQ_TYPE_EDGE_BOTH);
 +      info->pm_enabled = 1;
 +      set_bit(HCI_RUNNING, &hdev->flags);
 +      return 0;
 +}
 +
 +static int brf6150_hci_close(struct hci_dev *hdev)
 +{
 +      struct brf6150_info *info = hdev->driver_data;
 +      if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
 +              return 0;
 +
 +      brf6150_hci_flush(hdev);
 +      clk_disable(info->uart_ck);
 +      del_timer_sync(&info->pm_timer);
 +      omap_set_gpio_dataout(info->btinfo->bt_wakeup_gpio, 0);
-       set_irq_type(OMAP_GPIO_IRQ(info->btinfo->host_wakeup_gpio), IRQT_NOEDGE);
++      set_irq_type(OMAP_GPIO_IRQ(info->btinfo->host_wakeup_gpio), IRQ_TYPE_NONE);
 +
 +      return 0;
 +}
 +
 +static void brf6150_hci_destruct(struct hci_dev *hdev)
 +{
 +}
 +
 +static int brf6150_hci_send_frame(struct sk_buff *skb)
 +{
 +      struct brf6150_info *info;
 +      struct hci_dev *hdev = (struct hci_dev *)skb->dev;
 +
 +      if (!hdev) {
 +              printk(KERN_WARNING "brf6150: Frame for unknown device\n");
 +              return -ENODEV;
 +      }
 +
 +      if (!test_bit(HCI_RUNNING, &hdev->flags)) {
 +              printk(KERN_WARNING "brf6150: Frame for non-running device\n");
 +              return -EIO;
 +      }
 +
 +      info = hdev->driver_data;
 +
 +      switch (bt_cb(skb)->pkt_type) {
 +              case HCI_COMMAND_PKT:
 +                      hdev->stat.cmd_tx++;
 +                      break;
 +              case HCI_ACLDATA_PKT:
 +                      hdev->stat.acl_tx++;
 +                      break;
 +              case HCI_SCODATA_PKT:
 +                      hdev->stat.sco_tx++;
 +                      break;
 +      };
 +
 +      /* Push frame type to skb */
 +      clk_enable(info->uart_ck);
 +      *skb_push(skb, 1) = bt_cb(skb)->pkt_type;
 +      skb_queue_tail(&info->txq, skb);
 +
 +      brf6150_disable_pm_tx(info);
 +
 +      return 0;
 +}
 +
 +static int brf6150_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg)
 +{
 +      return -ENOIOCTLCMD;
 +}
 +
 +static void brf6150_device_release(struct device *dev)
 +{
 +}
 +
 +static int brf6150_register_hdev(struct brf6150_info *info)
 +{
 +      struct hci_dev *hdev;
 +
 +      /* Initialize and register HCI device */
 +
 +      hdev = hci_alloc_dev();
 +      if (!hdev) {
 +              printk(KERN_WARNING "brf6150: Can't allocate memory for device\n");
 +              return -ENOMEM;
 +      }
 +      info->hdev = hdev;
 +
 +      hdev->type = HCI_UART;
 +      hdev->driver_data = info;
 +
 +      hdev->open = brf6150_hci_open;
 +      hdev->close = brf6150_hci_close;
 +      hdev->destruct = brf6150_hci_destruct;
 +      hdev->flush = brf6150_hci_flush;
 +      hdev->send = brf6150_hci_send_frame;
 +      hdev->destruct = brf6150_hci_destruct;
 +      hdev->ioctl = brf6150_hci_ioctl;
 +
 +      hdev->owner = THIS_MODULE;
 +
 +      if (hci_register_dev(hdev) < 0) {
 +              printk(KERN_WARNING "brf6150: Can't register HCI device %s.\n", hdev->name);
 +              return -ENODEV;
 +      }
 +
 +      return 0;
 +}
 +
 +static int __init brf6150_init(void)
 +{
 +      struct brf6150_info *info;
 +      int irq, err;
 +
 +      info = kmalloc(sizeof(struct brf6150_info), GFP_KERNEL);
 +      if (!info)
 +              return -ENOMEM;
 +      memset(info, 0, sizeof(struct brf6150_info));
 +
 +      brf6150_device.dev.driver_data = info;
 +      init_completion(&info->init_completion);
 +      init_completion(&info->fw_completion);
 +      info->pm_enabled = 0;
 +      info->rx_pm_enabled = 0;
 +      info->tx_pm_enabled = 0;
 +      info->garbage_bytes = 0;
 +      tasklet_init(&info->tx_task, brf6150_tx_tasklet, (unsigned long)info);
 +      spin_lock_init(&info->lock);
 +      skb_queue_head_init(&info->txq);
 +      init_timer(&info->pm_timer);
 +      info->pm_timer.function = brf6150_pm_timer;
 +      info->pm_timer.data = (unsigned long)info;
 +      exit_info = NULL;
 +
 +      info->btinfo = omap_get_config(OMAP_TAG_NOKIA_BT, struct omap_bluetooth_config);
 +      if (info->btinfo == NULL)
 +              return -1;
 +
 +      NBT_DBG("RESET gpio: %d\n", info->btinfo->reset_gpio);
 +      NBT_DBG("BTWU gpio: %d\n", info->btinfo->bt_wakeup_gpio);
 +      NBT_DBG("HOSTWU gpio: %d\n", info->btinfo->host_wakeup_gpio);
 +      NBT_DBG("Uart: %d\n", info->btinfo->bt_uart);
 +      NBT_DBG("sysclk: %d\n", info->btinfo->bt_sysclk);
 +
 +      err = omap_request_gpio(info->btinfo->reset_gpio);
 +      if (err < 0)
 +      {
 +              printk(KERN_WARNING "Cannot get GPIO line %d", 
 +                     info->btinfo->reset_gpio);
 +              kfree(info);
 +              return err;
 +      }
 +
 +      err = omap_request_gpio(info->btinfo->bt_wakeup_gpio);
 +      if (err < 0)
 +      {
 +              printk(KERN_WARNING "Cannot get GPIO line 0x%d",
 +                     info->btinfo->bt_wakeup_gpio);
 +              omap_free_gpio(info->btinfo->reset_gpio);
 +              kfree(info);
 +              return err;
 +      }
 +
 +      err = omap_request_gpio(info->btinfo->host_wakeup_gpio);
 +      if (err < 0)
 +      {
 +              printk(KERN_WARNING "Cannot get GPIO line %d",
 +                     info->btinfo->host_wakeup_gpio);
 +              omap_free_gpio(info->btinfo->reset_gpio);
 +              omap_free_gpio(info->btinfo->bt_wakeup_gpio);
 +              kfree(info);
 +              return err;
 +      }
 +
 +      omap_set_gpio_direction(info->btinfo->reset_gpio, 0);
 +      omap_set_gpio_direction(info->btinfo->bt_wakeup_gpio, 0);
 +      omap_set_gpio_direction(info->btinfo->host_wakeup_gpio, 1);
++      set_irq_type(OMAP_GPIO_IRQ(info->btinfo->host_wakeup_gpio), IRQ_TYPE_NONE);
 +
 +      switch (info->btinfo->bt_uart) {
 +      case 1:
 +              irq = INT_UART1;
 +              info->uart_ck = clk_get(NULL, "uart1_ck");
 +              info->uart_base = io_p2v((unsigned long)OMAP_UART1_BASE);
 +              break;
 +      case 2:
 +              irq = INT_UART2;
 +              info->uart_ck = clk_get(NULL, "uart2_ck");
 +              info->uart_base = io_p2v((unsigned long)OMAP_UART2_BASE);
 +              break;
 +      case 3:
 +              irq = INT_UART3;
 +              info->uart_ck = clk_get(NULL, "uart3_ck");
 +              info->uart_base = io_p2v((unsigned long)OMAP_UART3_BASE);
 +              break;
 +      default:
 +              printk(KERN_ERR "No uart defined\n");
 +              goto cleanup;
 +      }
 +
 +      info->irq = irq;
 +      err = request_irq(irq, brf6150_interrupt, 0, "brf6150", (void *)info);
 +      if (err < 0) {
 +              printk(KERN_ERR "brf6150: unable to get IRQ %d\n", irq);
 +              goto cleanup;
 +      }
 +
 +      err = request_irq(OMAP_GPIO_IRQ(info->btinfo->host_wakeup_gpio),
 +                      brf6150_wakeup_interrupt, 0, "brf6150_wkup", (void *)info);
 +      if (err < 0) {
 +              printk(KERN_ERR "brf6150: unable to get wakeup IRQ %d\n",
 +                              OMAP_GPIO_IRQ(info->btinfo->host_wakeup_gpio));
 +              free_irq(irq, (void *)info);
 +              goto cleanup;
 +      }
 +
 +      /* Register with LDM */
 +      if (platform_device_register(&brf6150_device)) {
 +              printk(KERN_ERR "failed to register brf6150 device\n");
 +              err = -ENODEV;
 +              goto cleanup_irq;
 +      }
 +      /* Register the driver with LDM */
 +      if (driver_register(&brf6150_driver)) {
 +              printk(KERN_WARNING "failed to register brf6150 driver\n");
 +              platform_device_unregister(&brf6150_device);
 +              err = -ENODEV;
 +              goto cleanup_irq;
 +      }
 +
 +      if (brf6150_register_hdev(info) < 0) {
 +              printk(KERN_WARNING "failed to register brf6150 hci device\n");
 +              platform_device_unregister(&brf6150_device);
 +              driver_unregister(&brf6150_driver);
 +              goto cleanup_irq;
 +      }
 +
 +      exit_info = info;
 +      return 0;
 +
 +cleanup_irq:
 +      free_irq(irq, (void *)info);
 +      free_irq(OMAP_GPIO_IRQ(info->btinfo->host_wakeup_gpio), (void *)info);
 +cleanup:
 +      omap_free_gpio(info->btinfo->reset_gpio);
 +      omap_free_gpio(info->btinfo->bt_wakeup_gpio);
 +      omap_free_gpio(info->btinfo->host_wakeup_gpio);
 +      kfree(info);
 +
 +      return err;
 +}
 +
 +static void __exit brf6150_exit(void)
 +{
 +      brf6150_hci_close(exit_info->hdev);
 +      hci_free_dev(exit_info->hdev);
 +      omap_free_gpio(exit_info->btinfo->reset_gpio);
 +      omap_free_gpio(exit_info->btinfo->bt_wakeup_gpio);
 +      omap_free_gpio(exit_info->btinfo->host_wakeup_gpio);
 +      free_irq(exit_info->irq, (void *)exit_info);
 +      free_irq(OMAP_GPIO_IRQ(exit_info->btinfo->host_wakeup_gpio), (void *)exit_info);
 +      kfree(exit_info);
 +}
 +
 +module_init(brf6150_init);
 +module_exit(brf6150_exit);
 +
 +MODULE_DESCRIPTION("brf6150 hci driver");
 +MODULE_LICENSE("GPL");
 +MODULE_AUTHOR("Ville Tervo <ville.tervo@nokia.com>");
diff --combined drivers/cbus/retu.c
index ebb86b363de1dce2a2ef9654401049fe27373cc3,0000000000000000000000000000000000000000..ceb93d03e2d682f12b0d686255c9f8588f7c3585
mode 100644,000000..100644
--- /dev/null
@@@ -1,466 -1,0 +1,466 @@@
-       set_irq_type(OMAP_GPIO_IRQ(retu_irq_pin), IRQT_RISING);
 +/**
 + * drivers/cbus/retu.c
 + *
 + * Support functions for Retu ASIC
 + *
 + * Copyright (C) 2004, 2005 Nokia Corporation
 + *
 + * Written by Juha Yrjölä <juha.yrjola@nokia.com>,
 + *          David Weinehall <david.weinehall@nokia.com>, and
 + *          Mikko Ylinen <mikko.k.ylinen@nokia.com>
 + *
 + * This file is subject to the terms and conditions of the GNU General
 + * Public License. See the file "COPYING" in the main directory of this
 + * archive for more details.
 + *
 + * This 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/module.h>
 +#include <linux/init.h>
 +
 +#include <linux/kernel.h>
 +#include <linux/errno.h>
 +#include <linux/device.h>
 +#include <linux/miscdevice.h>
 +#include <linux/poll.h>
 +#include <linux/fs.h>
 +#include <linux/irq.h>
 +#include <linux/interrupt.h>
 +#include <linux/platform_device.h>
 +
 +#include <asm/uaccess.h>
 +
 +#include <asm/arch/mux.h>
 +#include <asm/arch/gpio.h>
 +#include <asm/arch/board.h>
 +
 +#include "cbus.h"
 +#include "retu.h"
 +
 +#define RETU_ID                       0x01
 +#define PFX                   "retu: "
 +
 +static int retu_initialized;
 +static int retu_irq_pin;
 +static int retu_is_vilma;
 +
 +static struct tasklet_struct retu_tasklet;
 +spinlock_t retu_lock = SPIN_LOCK_UNLOCKED;
 +
 +static struct completion device_release;
 +
 +struct retu_irq_handler_desc {
 +      int (*func)(unsigned long);
 +      unsigned long arg;
 +      char name[8];
 +};
 +
 +static struct retu_irq_handler_desc retu_irq_handlers[MAX_RETU_IRQ_HANDLERS];
 +
 +/**
 + * retu_read_reg - Read a value from a register in Retu
 + * @reg: the register to read from
 + *
 + * This function returns the contents of the specified register
 + */
 +int retu_read_reg(int reg)
 +{
 +      BUG_ON(!retu_initialized);
 +      return cbus_read_reg(cbus_host, RETU_ID, reg);
 +}
 +
 +/**
 + * retu_write_reg - Write a value to a register in Retu
 + * @reg: the register to write to
 + * @reg: the value to write to the register
 + *
 + * This function writes a value to the specified register
 + */
 +void retu_write_reg(int reg, u16 val)
 +{
 +      BUG_ON(!retu_initialized);
 +      cbus_write_reg(cbus_host, RETU_ID, reg, val);
 +}
 +
 +void retu_set_clear_reg_bits(int reg, u16 set, u16 clear)
 +{
 +      unsigned long flags;
 +      u16 w;
 +
 +      spin_lock_irqsave(&retu_lock, flags);
 +      w = retu_read_reg(reg);
 +      w &= ~clear;
 +      w |= set;
 +      retu_write_reg(reg, w);
 +      spin_unlock_irqrestore(&retu_lock, flags);
 +}
 +
 +#define ADC_MAX_CHAN_NUMBER   13
 +
 +int retu_read_adc(int channel)
 +{
 +      unsigned long flags;
 +      int res;
 +
 +      if (channel < 0 || channel > ADC_MAX_CHAN_NUMBER)
 +              return -EINVAL;
 +
 +      spin_lock_irqsave(&retu_lock, flags);
 +
 +      if ((channel == 8) && retu_is_vilma) {
 +              int scr = retu_read_reg(RETU_REG_ADCSCR);
 +              int ch = (retu_read_reg(RETU_REG_ADCR) >> 10) & 0xf;
 +              if (((scr & 0xff) != 0) && (ch != 8))
 +                      retu_write_reg (RETU_REG_ADCSCR, (scr & ~0xff));
 +      }
 +
 +      /* Select the channel and read result */
 +      retu_write_reg(RETU_REG_ADCR, channel << 10);
 +      res = retu_read_reg(RETU_REG_ADCR) & 0x3ff;
 +
 +      if (retu_is_vilma)
 +              retu_write_reg(RETU_REG_ADCR, (1 << 13));
 +
 +      /* Unlock retu */
 +      spin_unlock_irqrestore(&retu_lock, flags);
 +
 +      return res;
 +}
 +
 +
 +static u16 retu_disable_bogus_irqs(u16 mask)
 +{
 +       int i;
 +
 +       for (i = 0; i < MAX_RETU_IRQ_HANDLERS; i++) {
 +               if (mask & (1 << i))
 +                       continue;
 +               if (retu_irq_handlers[i].func != NULL)
 +                       continue;
 +               /* an IRQ was enabled but we don't have a handler for it */
 +               printk(KERN_INFO PFX "disabling bogus IRQ %d\n", i);
 +               mask |= (1 << i);
 +       }
 +       return mask;
 +}
 +
 +/*
 + * Disable given RETU interrupt
 + */
 +void retu_disable_irq(int id)
 +{
 +      unsigned long flags;
 +      u16 mask;
 +
 +      spin_lock_irqsave(&retu_lock, flags);
 +      mask = retu_read_reg(RETU_REG_IMR);
 +      mask |= 1 << id;
 +      mask = retu_disable_bogus_irqs(mask);
 +      retu_write_reg(RETU_REG_IMR, mask);
 +      spin_unlock_irqrestore(&retu_lock, flags);
 +}
 +
 +/*
 + * Enable given RETU interrupt
 + */
 +void retu_enable_irq(int id)
 +{
 +      unsigned long flags;
 +      u16 mask;
 +
 +      if (id == 3) {
 +              printk("Enabling Retu IRQ %d\n", id);
 +              dump_stack();
 +      }
 +      spin_lock_irqsave(&retu_lock, flags);
 +      mask = retu_read_reg(RETU_REG_IMR);
 +      mask &= ~(1 << id);
 +      mask = retu_disable_bogus_irqs(mask);
 +      retu_write_reg(RETU_REG_IMR, mask);
 +      spin_unlock_irqrestore(&retu_lock, flags);
 +}
 +
 +/*
 + * Acknowledge given RETU interrupt
 + */
 +void retu_ack_irq(int id)
 +{
 +      retu_write_reg(RETU_REG_IDR, 1 << id);
 +}
 +
 +/*
 + * RETU interrupt handler. Only schedules the tasklet.
 + */
 +static irqreturn_t retu_irq_handler(int irq, void *dev_id)
 +{
 +      tasklet_schedule(&retu_tasklet);
 +      return IRQ_HANDLED;
 +}
 +
 +/*
 + * Tasklet handler
 + */
 +static void retu_tasklet_handler(unsigned long data)
 +{
 +      struct retu_irq_handler_desc *hnd;
 +      u16 id;
 +      u16 im;
 +      int i;
 +
 +      for (;;) {
 +              id = retu_read_reg(RETU_REG_IDR);
 +              im = ~retu_read_reg(RETU_REG_IMR);
 +              id &= im;
 +
 +              if (!id)
 +                      break;
 +
 +              for (i = 0; id != 0; i++, id >>= 1) {
 +                      if (!(id & 1))
 +                              continue;
 +                      hnd = &retu_irq_handlers[i];
 +                      if (hnd->func == NULL) {
 +                               /* Spurious retu interrupt - disable and ack it */
 +                              printk(KERN_INFO "Spurious Retu interrupt "
 +                                               "(id %d)\n", i);
 +                              retu_disable_irq(i);
 +                              retu_ack_irq(i);
 +                              continue;
 +                      }
 +                      hnd->func(hnd->arg);
 +                      /*
 +                       * Don't acknowledge the interrupt here
 +                       * It must be done explicitly
 +                       */
 +              }
 +      }
 +}
 +
 +/*
 + * Register the handler for a given RETU interrupt source.
 + */
 +int retu_request_irq(int id, void *irq_handler, unsigned long arg, char *name)
 +{
 +      struct retu_irq_handler_desc *hnd;
 +
 +      if (irq_handler == NULL || id >= MAX_RETU_IRQ_HANDLERS ||
 +          name == NULL) {
 +              printk(KERN_ERR PFX "Invalid arguments to %s\n",
 +                     __FUNCTION__);
 +              return -EINVAL;
 +      }
 +      hnd = &retu_irq_handlers[id];
 +      if (hnd->func != NULL) {
 +              printk(KERN_ERR PFX "IRQ %d already reserved\n", id);
 +              return -EBUSY;
 +      }
 +      printk(KERN_INFO PFX "Registering interrupt %d for device %s\n",
 +             id, name);
 +      hnd->func = irq_handler;
 +      hnd->arg = arg;
 +      strlcpy(hnd->name, name, sizeof(hnd->name));
 +
 +      retu_ack_irq(id);
 +      retu_enable_irq(id);
 +
 +      return 0;
 +}
 +
 +/*
 + * Unregister the handler for a given RETU interrupt source.
 + */
 +void retu_free_irq(int id)
 +{
 +      struct retu_irq_handler_desc *hnd;
 +
 +      if (id >= MAX_RETU_IRQ_HANDLERS) {
 +              printk(KERN_ERR PFX "Invalid argument to %s\n",
 +                     __FUNCTION__);
 +              return;
 +      }
 +      hnd = &retu_irq_handlers[id];
 +      if (hnd->func == NULL) {
 +              printk(KERN_ERR PFX "IRQ %d already freed\n", id);
 +              return;
 +      }
 +
 +      retu_disable_irq(id);
 +      hnd->func = NULL;
 +}
 +
 +/**
 + * retu_power_off - Shut down power to system
 + *
 + * This function puts the system in power off state
 + */
 +static void retu_power_off(void)
 +{
 +      /* Ignore power button state */
 +      retu_write_reg(RETU_REG_CC1, retu_read_reg(RETU_REG_CC1) | 2);
 +      /* Expire watchdog immediately */
 +      retu_write_reg(RETU_REG_WATCHDOG, 0);
 +      /* Wait for poweroff*/
 +      for (;;);
 +}
 +
 +/**
 + * retu_probe - Probe for Retu ASIC
 + * @dev: the Retu device
 + *
 + * Probe for the Retu ASIC and allocate memory
 + * for its device-struct if found
 + */
 +static int __devinit retu_probe(struct device *dev)
 +{
 +      const struct omap_em_asic_bb5_config * em_asic_config;
 +      int rev, ret;
 +
 +      /* Prepare tasklet */
 +      tasklet_init(&retu_tasklet, retu_tasklet_handler, 0);
 +
 +      em_asic_config = omap_get_config(OMAP_TAG_EM_ASIC_BB5,
 +                                       struct omap_em_asic_bb5_config);
 +      if (em_asic_config == NULL) {
 +              printk(KERN_ERR PFX "Unable to retrieve config data\n");
 +              return -ENODATA;
 +      }
 +
 +      retu_irq_pin = em_asic_config->retu_irq_gpio;
 +
 +      if ((ret = omap_request_gpio(retu_irq_pin)) < 0) {
 +              printk(KERN_ERR PFX "Unable to reserve IRQ GPIO\n");
 +              return ret;
 +      }
 +
 +      /* Set the pin as input */
 +      omap_set_gpio_direction(retu_irq_pin, 1);
 +
 +      /* Rising edge triggers the IRQ */
++      set_irq_type(OMAP_GPIO_IRQ(retu_irq_pin), IRQ_TYPE_EDGE_RISING);
 +
 +      retu_initialized = 1;
 +
 +      rev = retu_read_reg(RETU_REG_ASICR) & 0xff;
 +      if (rev & (1 << 7))
 +              retu_is_vilma = 1;
 +
 +      printk(KERN_INFO "%s v%d.%d found\n", retu_is_vilma ? "Vilma" : "Retu",
 +             (rev >> 4) & 0x07, rev & 0x0f);
 +
 +      /* Mask all RETU interrupts */
 +      retu_write_reg(RETU_REG_IMR, 0xffff);
 +
 +      ret = request_irq(OMAP_GPIO_IRQ(retu_irq_pin), retu_irq_handler, 0,
 +                        "retu", 0);
 +      if (ret < 0) {
 +              printk(KERN_ERR PFX "Unable to register IRQ handler\n");
 +              omap_free_gpio(retu_irq_pin);
 +              return ret;
 +      }
 +      set_irq_wake(OMAP_GPIO_IRQ(retu_irq_pin), 1);
 +
 +      /* Register power off function */
 +      pm_power_off = retu_power_off;
 +
 +#ifdef CONFIG_CBUS_RETU_USER
 +      /* Initialize user-space interface */
 +      if (retu_user_init() < 0) {
 +              printk(KERN_ERR "Unable to initialize driver\n");
 +              free_irq(OMAP_GPIO_IRQ(retu_irq_pin), 0);
 +              omap_free_gpio(retu_irq_pin);
 +              return ret;
 +      }
 +#endif
 +
 +      return 0;
 +}
 +
 +static int retu_remove(struct device *dev)
 +{
 +#ifdef CONFIG_CBUS_RETU_USER
 +      retu_user_cleanup();
 +#endif
 +      /* Mask all RETU interrupts */
 +      retu_write_reg(RETU_REG_IMR, 0xffff);
 +      free_irq(OMAP_GPIO_IRQ(retu_irq_pin), 0);
 +      omap_free_gpio(retu_irq_pin);
 +      tasklet_kill(&retu_tasklet);
 +
 +      return 0;
 +}
 +
 +static void retu_device_release(struct device *dev)
 +{
 +      complete(&device_release);
 +}
 +
 +static struct device_driver retu_driver = {
 +      .name           = "retu",
 +      .bus            = &platform_bus_type,
 +      .probe          = retu_probe,
 +      .remove         = retu_remove,
 +};
 +
 +static struct platform_device retu_device = {
 +      .name           = "retu",
 +      .id             = -1,
 +      .dev = {
 +              .release = retu_device_release,
 +      }
 +};
 +
 +/**
 + * retu_init - initialise Retu driver
 + *
 + * Initialise the Retu driver and return 0 if everything worked ok
 + */
 +static int __init retu_init(void)
 +{
 +      int ret = 0;
 +
 +      printk(KERN_INFO "Retu/Vilma driver initialising\n");
 +
 +      init_completion(&device_release);
 +
 +      if ((ret = driver_register(&retu_driver)) < 0)
 +              return ret;
 +
 +      if ((ret = platform_device_register(&retu_device)) < 0) {
 +              driver_unregister(&retu_driver);
 +              return ret;
 +      }
 +      return 0;
 +}
 +
 +/*
 + * Cleanup
 + */
 +static void __exit retu_exit(void)
 +{
 +      platform_device_unregister(&retu_device);
 +      driver_unregister(&retu_driver);
 +      wait_for_completion(&device_release);
 +}
 +
 +EXPORT_SYMBOL(retu_request_irq);
 +EXPORT_SYMBOL(retu_free_irq);
 +EXPORT_SYMBOL(retu_enable_irq);
 +EXPORT_SYMBOL(retu_disable_irq);
 +EXPORT_SYMBOL(retu_ack_irq);
 +EXPORT_SYMBOL(retu_read_reg);
 +EXPORT_SYMBOL(retu_write_reg);
 +
 +subsys_initcall(retu_init);
 +module_exit(retu_exit);
 +
 +MODULE_DESCRIPTION("Retu ASIC control");
 +MODULE_LICENSE("GPL");
 +MODULE_AUTHOR("Juha Yrjölä, David Weinehall, and Mikko Ylinen");
diff --combined drivers/cbus/tahvo.c
index edf7082c60a860df4238af0afb618fb3b7ebd92d,0000000000000000000000000000000000000000..bc7a4b6c69ad253e463ed8a658efc0cb702a88e0
mode 100644,000000..100644
--- /dev/null
@@@ -1,441 -1,0 +1,441 @@@
-       set_irq_type(OMAP_GPIO_IRQ(tahvo_irq_pin), IRQT_RISING);
 +/**
 + * drivers/cbus/tahvo.c
 + *
 + * Support functions for Tahvo ASIC
 + *
 + * Copyright (C) 2004, 2005 Nokia Corporation
 + *
 + * Written by Juha Yrjölä <juha.yrjola@nokia.com>,
 + *          David Weinehall <david.weinehall@nokia.com>, and
 + *          Mikko Ylinen <mikko.k.ylinen@nokia.com>
 + *
 + * This file is subject to the terms and conditions of the GNU General
 + * Public License. See the file "COPYING" in the main directory of this
 + * archive for more details.
 + *
 + * This 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/module.h>
 +#include <linux/init.h>
 +
 +#include <linux/kernel.h>
 +#include <linux/errno.h>
 +#include <linux/device.h>
 +#include <linux/miscdevice.h>
 +#include <linux/poll.h>
 +#include <linux/fs.h>
 +#include <linux/irq.h>
 +#include <linux/interrupt.h>
 +#include <linux/platform_device.h>
 +
 +#include <asm/uaccess.h>
 +
 +#include <asm/arch/mux.h>
 +#include <asm/arch/gpio.h>
 +#include <asm/arch/board.h>
 +
 +#include "cbus.h"
 +#include "tahvo.h"
 +
 +#define TAHVO_ID              0x02
 +#define PFX                   "tahvo: "
 +
 +static int tahvo_initialized;
 +static int tahvo_irq_pin;
 +static int tahvo_is_betty;
 +
 +static struct tasklet_struct tahvo_tasklet;
 +spinlock_t tahvo_lock = SPIN_LOCK_UNLOCKED;
 +
 +static struct completion device_release;
 +
 +struct tahvo_irq_handler_desc {
 +      int (*func)(unsigned long);
 +      unsigned long arg;
 +      char name[8];
 +};
 +
 +static struct tahvo_irq_handler_desc tahvo_irq_handlers[MAX_TAHVO_IRQ_HANDLERS];
 +
 +/**
 + * tahvo_read_reg - Read a value from a register in Tahvo
 + * @reg: the register to read from
 + *
 + * This function returns the contents of the specified register
 + */
 +int tahvo_read_reg(int reg)
 +{
 +      BUG_ON(!tahvo_initialized);
 +      return cbus_read_reg(cbus_host, TAHVO_ID, reg);
 +}
 +
 +/**
 + * tahvo_write_reg - Write a value to a register in Tahvo
 + * @reg: the register to write to
 + * @reg: the value to write to the register
 + *
 + * This function writes a value to the specified register
 + */
 +void tahvo_write_reg(int reg, u16 val)
 +{
 +      BUG_ON(!tahvo_initialized);
 +      cbus_write_reg(cbus_host, TAHVO_ID, reg, val);
 +}
 +
 +/**
 + * tahvo_set_clear_reg_bits - set and clear register bits atomically
 + * @reg: the register to write to
 + * @bits: the bits to set
 + *
 + * This function sets and clears the specified Tahvo register bits atomically
 + */
 +void tahvo_set_clear_reg_bits(int reg, u16 set, u16 clear)
 +{
 +      unsigned long flags;
 +      u16 w;
 +
 +      spin_lock_irqsave(&tahvo_lock, flags);
 +      w = tahvo_read_reg(reg);
 +      w &= ~clear;
 +      w |= set;
 +      tahvo_write_reg(reg, w);
 +      spin_unlock_irqrestore(&tahvo_lock, flags);
 +}
 +
 +/*
 + * Disable given TAHVO interrupt
 + */
 +void tahvo_disable_irq(int id)
 +{
 +      unsigned long flags;
 +      u16 mask;
 +
 +      spin_lock_irqsave(&tahvo_lock, flags);
 +      mask = tahvo_read_reg(TAHVO_REG_IMR);
 +      mask |= 1 << id;
 +      tahvo_write_reg(TAHVO_REG_IMR, mask);
 +      spin_unlock_irqrestore(&tahvo_lock, flags);
 +}
 +
 +/*
 + * Enable given TAHVO interrupt
 + */
 +void tahvo_enable_irq(int id)
 +{
 +      unsigned long flags;
 +      u16 mask;
 +
 +      spin_lock_irqsave(&tahvo_lock, flags);
 +      mask = tahvo_read_reg(TAHVO_REG_IMR);
 +      mask &= ~(1 << id);
 +      tahvo_write_reg(TAHVO_REG_IMR, mask);
 +      spin_unlock_irqrestore(&tahvo_lock, flags);
 +}
 +
 +/*
 + * Acknowledge given TAHVO interrupt
 + */
 +void tahvo_ack_irq(int id)
 +{
 +      tahvo_write_reg(TAHVO_REG_IDR, 1 << id);
 +}
 +
 +static int tahvo_7bit_backlight;
 +
 +int tahvo_get_backlight_level(void)
 +{
 +      int mask;
 +
 +      if (tahvo_7bit_backlight)
 +              mask = 0x7f;
 +      else
 +              mask = 0x0f;
 +      return tahvo_read_reg(TAHVO_REG_LEDPWMR) & mask;
 +}
 +
 +int tahvo_get_max_backlight_level(void)
 +{
 +      if (tahvo_7bit_backlight)
 +              return 0x7f;
 +      else
 +              return 0x0f;
 +}
 +
 +void tahvo_set_backlight_level(int level)
 +{
 +      int max_level;
 +
 +      max_level = tahvo_get_max_backlight_level();
 +      if (level > max_level)
 +              level = max_level;
 +      tahvo_write_reg(TAHVO_REG_LEDPWMR, level);
 +}
 +
 +/*
 + * TAHVO interrupt handler. Only schedules the tasklet.
 + */
 +static irqreturn_t tahvo_irq_handler(int irq, void *dev_id)
 +{
 +      tasklet_schedule(&tahvo_tasklet);
 +      return IRQ_HANDLED;
 +}
 +
 +/*
 + * Tasklet handler
 + */
 +static void tahvo_tasklet_handler(unsigned long data)
 +{
 +      struct tahvo_irq_handler_desc *hnd;
 +      u16 id;
 +      u16 im;
 +      int i;
 +
 +      for (;;) {
 +              id = tahvo_read_reg(TAHVO_REG_IDR);
 +              im = ~tahvo_read_reg(TAHVO_REG_IMR);
 +              id &= im;
 +
 +              if (!id)
 +                      break;
 +
 +              for (i = 0; id != 0; i++, id >>= 1) {
 +                      if (!(id & 1))
 +                              continue;
 +                      hnd = &tahvo_irq_handlers[i];
 +                      if (hnd->func == NULL) {
 +                              /* Spurious tahvo interrupt - just ack it */
 +                              printk(KERN_INFO "Spurious Tahvo interrupt "
 +                                               "(id %d)\n", i);
 +                              tahvo_disable_irq(i);
 +                              tahvo_ack_irq(i);
 +                              continue;
 +                      }
 +                      hnd->func(hnd->arg);
 +                      /*
 +                       * Don't acknowledge the interrupt here
 +                       * It must be done explicitly
 +                       */
 +              }
 +      }
 +}
 +
 +/*
 + * Register the handler for a given TAHVO interrupt source.
 + */
 +int tahvo_request_irq(int id, void *irq_handler, unsigned long arg, char *name)
 +{
 +      struct tahvo_irq_handler_desc *hnd;
 +
 +      if (irq_handler == NULL || id >= MAX_TAHVO_IRQ_HANDLERS ||
 +          name == NULL) {
 +              printk(KERN_ERR PFX "Invalid arguments to %s\n",
 +                     __FUNCTION__);
 +              return -EINVAL;
 +      }
 +      hnd = &tahvo_irq_handlers[id];
 +      if (hnd->func != NULL) {
 +              printk(KERN_ERR PFX "IRQ %d already reserved\n", id);
 +              return -EBUSY;
 +      }
 +      printk(KERN_INFO PFX "Registering interrupt %d for device %s\n",
 +             id, name);
 +      hnd->func = irq_handler;
 +      hnd->arg = arg;
 +      strlcpy(hnd->name, name, sizeof(hnd->name));
 +
 +      tahvo_ack_irq(id);
 +      tahvo_enable_irq(id);
 +
 +      return 0;
 +}
 +
 +/*
 + * Unregister the handler for a given TAHVO interrupt source.
 + */
 +void tahvo_free_irq(int id)
 +{
 +      struct tahvo_irq_handler_desc *hnd;
 +
 +      if (id >= MAX_TAHVO_IRQ_HANDLERS) {
 +              printk(KERN_ERR PFX "Invalid argument to %s\n",
 +                     __FUNCTION__);
 +              return;
 +      }
 +      hnd = &tahvo_irq_handlers[id];
 +      if (hnd->func == NULL) {
 +              printk(KERN_ERR PFX "IRQ %d already freed\n", id);
 +              return;
 +      }
 +
 +      tahvo_disable_irq(id);
 +      hnd->func = NULL;
 +}
 +
 +/**
 + * tahvo_probe - Probe for Tahvo ASIC
 + * @dev: the Tahvo device
 + *
 + * Probe for the Tahvo ASIC and allocate memory
 + * for its device-struct if found
 + */
 +static int __devinit tahvo_probe(struct device *dev)
 +{
 +      const struct omap_em_asic_bb5_config * em_asic_config;
 +      int rev, id, ret;
 +
 +      /* Prepare tasklet */
 +      tasklet_init(&tahvo_tasklet, tahvo_tasklet_handler, 0);
 +
 +      em_asic_config = omap_get_config(OMAP_TAG_EM_ASIC_BB5,
 +                                       struct omap_em_asic_bb5_config);
 +      if (em_asic_config == NULL) {
 +              printk(KERN_ERR PFX "Unable to retrieve config data\n");
 +              return -ENODATA;
 +      }
 +
 +      tahvo_initialized = 1;
 +
 +      rev = tahvo_read_reg(TAHVO_REG_ASICR);
 +
 +      id = (rev >> 8) & 0xff;
 +      if (id == 0x03) {
 +              if ((rev & 0xff) >= 0x50)
 +                      tahvo_7bit_backlight = 1;
 +      } else if (id == 0x0b) {
 +              tahvo_is_betty = 1;
 +              tahvo_7bit_backlight = 1;
 +      } else {
 +              printk(KERN_ERR "Tahvo/Betty chip not found");
 +              return -ENODEV;
 +      }
 +
 +      printk(KERN_INFO "%s v%d.%d found\n", tahvo_is_betty ? "Betty" : "Tahvo",
 +             (rev >> 4) & 0x0f, rev & 0x0f);
 +
 +      tahvo_irq_pin = em_asic_config->tahvo_irq_gpio;
 +
 +      if ((ret = omap_request_gpio(tahvo_irq_pin)) < 0) {
 +              printk(KERN_ERR PFX "Unable to reserve IRQ GPIO\n");
 +              return ret;
 +      }
 +
 +      /* Set the pin as input */
 +      omap_set_gpio_direction(tahvo_irq_pin, 1);
 +
 +      /* Rising edge triggers the IRQ */
++      set_irq_type(OMAP_GPIO_IRQ(tahvo_irq_pin), IRQ_TYPE_EDGE_RISING);
 +
 +      /* Mask all TAHVO interrupts */
 +      tahvo_write_reg(TAHVO_REG_IMR, 0xffff);
 +
 +      ret = request_irq(OMAP_GPIO_IRQ(tahvo_irq_pin), tahvo_irq_handler, 0,
 +                        "tahvo", 0);
 +      if (ret < 0) {
 +              printk(KERN_ERR PFX "Unable to register IRQ handler\n");
 +              omap_free_gpio(tahvo_irq_pin);
 +              return ret;
 +      }
 +#ifdef CONFIG_CBUS_TAHVO_USER
 +      /* Initialize user-space interface */
 +      if (tahvo_user_init() < 0) {
 +              printk(KERN_ERR "Unable to initialize driver\n");
 +              free_irq(OMAP_GPIO_IRQ(tahvo_irq_pin), 0);
 +              omap_free_gpio(tahvo_irq_pin);
 +              return ret;
 +      }
 +#endif
 +      return 0;
 +}
 +
 +static int tahvo_remove(struct device *dev)
 +{
 +#ifdef CONFIG_CBUS_TAHVO_USER
 +      tahvo_user_cleanup();
 +#endif
 +      /* Mask all TAHVO interrupts */
 +      tahvo_write_reg(TAHVO_REG_IMR, 0xffff);
 +      free_irq(OMAP_GPIO_IRQ(tahvo_irq_pin), 0);
 +      omap_free_gpio(tahvo_irq_pin);
 +      tasklet_kill(&tahvo_tasklet);
 +
 +      return 0;
 +}
 +
 +static void tahvo_device_release(struct device *dev)
 +{
 +      complete(&device_release);
 +}
 +
 +static struct device_driver tahvo_driver = {
 +      .name           = "tahvo",
 +      .bus            = &platform_bus_type,
 +      .probe          = tahvo_probe,
 +      .remove         = tahvo_remove,
 +};
 +
 +static struct platform_device tahvo_device = {
 +      .name           = "tahvo",
 +      .id             = -1,
 +      .dev = {
 +              .release = tahvo_device_release,
 +      }
 +};
 +
 +/**
 + * tahvo_init - initialise Tahvo driver
 + *
 + * Initialise the Tahvo driver and return 0 if everything worked ok
 + */
 +static int __init tahvo_init(void)
 +{
 +      int ret = 0;
 +
 +      printk(KERN_INFO "Tahvo/Betty driver initialising\n");
 +
 +      init_completion(&device_release);
 +
 +      if ((ret = driver_register(&tahvo_driver)) < 0)
 +              return ret;
 +
 +      if ((ret = platform_device_register(&tahvo_device)) < 0) {
 +              driver_unregister(&tahvo_driver);
 +              return ret;
 +      }
 +      return 0;
 +}
 +
 +/*
 + * Cleanup
 + */
 +static void __exit tahvo_exit(void)
 +{
 +      platform_device_unregister(&tahvo_device);
 +      driver_unregister(&tahvo_driver);
 +      wait_for_completion(&device_release);
 +}
 +
 +EXPORT_SYMBOL(tahvo_request_irq);
 +EXPORT_SYMBOL(tahvo_free_irq);
 +EXPORT_SYMBOL(tahvo_enable_irq);
 +EXPORT_SYMBOL(tahvo_disable_irq);
 +EXPORT_SYMBOL(tahvo_ack_irq);
 +EXPORT_SYMBOL(tahvo_read_reg);
 +EXPORT_SYMBOL(tahvo_write_reg);
 +EXPORT_SYMBOL(tahvo_get_backlight_level);
 +EXPORT_SYMBOL(tahvo_get_max_backlight_level);
 +EXPORT_SYMBOL(tahvo_set_backlight_level);
 +
 +subsys_initcall(tahvo_init);
 +module_exit(tahvo_exit);
 +
 +MODULE_DESCRIPTION("Tahvo ASIC control");
 +MODULE_LICENSE("GPL");
 +MODULE_AUTHOR("Juha Yrjölä, David Weinehall, and Mikko Ylinen");
diff --combined drivers/crypto/Kconfig
index 110c4dc781fe709e9ee8dbc38f2fe0b2567711e3,e522144cba3af9bc9d9e5e9bbc1e5dcb05e693c0..7fb9494e4d80d5757b4f6185795fa647c0fad104
@@@ -83,13 -83,6 +83,13 @@@ config ZCRYPT_MONOLITHI
          that contains all parts of the crypto device driver (ap bus,
          request router and all the card drivers).
  
 +config OMAP_SHA1_MD5
 +      tristate "Support for OMAP SHA1/MD5 hw engine"
 +      depends on ARCH_OMAP24XX && CRYPTO_SHA1 && CRYPTO_MD5
 +      help
 +        OMAP processors have SHA1/MD5 module accelerator. Select this if you
 +        want to use the OMAP module for SHA1/MD5 algorithms.
 +
  config CRYPTO_SHA1_S390
        tristate "SHA1 digest algorithm"
        depends on S390
@@@ -181,4 -174,30 +181,30 @@@ config CRYPTO_DEV_HIFN_795X_RN
          Select this option if you want to enable the random number generator
          on the HIFN 795x crypto adapters.
  
+ config CRYPTO_DEV_TALITOS
+       tristate "Talitos Freescale Security Engine (SEC)"
+       select CRYPTO_ALGAPI
+       select CRYPTO_AUTHENC
+       select HW_RANDOM
+       depends on FSL_SOC
+       help
+         Say 'Y' here to use the Freescale Security Engine (SEC)
+         to offload cryptographic algorithm computation.
+         The Freescale SEC is present on PowerQUICC 'E' processors, such
+         as the MPC8349E and MPC8548E.
+         To compile this driver as a module, choose M here: the module
+         will be called talitos.
+ config CRYPTO_DEV_IXP4XX
+       tristate "Driver for IXP4xx crypto hardware acceleration"
+       depends on ARCH_IXP4XX
+       select CRYPTO_DES
+       select CRYPTO_ALGAPI
+       select CRYPTO_AUTHENC
+       select CRYPTO_BLKCIPHER
+       help
+         Driver for the IXP4xx NPE crypto engine.
  endif # CRYPTO_HW
diff --combined drivers/crypto/Makefile
index 6549d4503a43730e95d898e5e9202308d71fe686,73557b2968d33710ae4c0a5745d6ac4bce0dedef..5da41a156fc7871d6a399d6eb90a00ff754de51a
@@@ -1,5 -1,6 +1,7 @@@
  obj-$(CONFIG_CRYPTO_DEV_PADLOCK_AES) += padlock-aes.o
  obj-$(CONFIG_CRYPTO_DEV_PADLOCK_SHA) += padlock-sha.o
  obj-$(CONFIG_CRYPTO_DEV_GEODE) += geode-aes.o
 +obj-$(CONFIG_OMAP_SHA1_MD5) += omap-sha1-md5.o
  obj-$(CONFIG_CRYPTO_DEV_HIFN_795X) += hifn_795x.o
+ obj-$(CONFIG_CRYPTO_DEV_TALITOS) += talitos.o
+ obj-$(CONFIG_CRYPTO_DEV_IXP4XX) += ixp4xx_crypto.o
index e3a0a02a103fa33a6f72a1b618e8750812741954,0000000000000000000000000000000000000000..4d7dcdd2658c01c7cfe8ffc7f50f72707e56f423
mode 100644,000000..100644
--- /dev/null
@@@ -1,3041 -1,0 +1,3041 @@@
-               if (find_task_by_pid(pl->pid) != NULL)
 +/*
 + * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
 + *
 + * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
 + *
 + * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * version 2 as published by the Free Software Foundation.
 + *
 + * 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., 51 Franklin St, Fifth Floor, Boston, MA
 + * 02110-1301 USA
 + *
 + */
 +
 +#include <linux/kernel.h>
 +#include <linux/module.h>
 +#include <linux/init.h>
 +#include <linux/major.h>
 +#include <linux/fs.h>
 +#include <linux/poll.h>
 +#include <linux/platform_device.h>
 +#include <linux/slab.h>
 +#include <linux/sched.h>
 +#include <linux/mm.h>
 +#include <linux/mutex.h>
 +#include <linux/interrupt.h>
 +#include <linux/kfifo.h>
 +#include <asm/uaccess.h>
 +#include <asm/io.h>
 +#include <asm/arch/mailbox.h>
 +#include <asm/arch/dsp.h>
 +#include "uaccess_dsp.h"
 +#include "dsp_mbcmd.h"
 +#include "dsp.h"
 +#include "ipbuf.h"
 +#include "proclist.h"
 +
 +/*
 + * devstate: task device state machine
 + * NOTASK:    task is not attached.
 + * ATTACHED:  task is attached.
 + * GARBAGE:   task is detached. waiting for all processes to close this device.
 + * ADDREQ:    requesting for tadd
 + * DELREQ:    requesting for tdel. no process is opening this device.
 + * FREEZED:   task is attached, but reserved to be killed.
 + * ADDFAIL:   tadd failed.
 + * ADDING:    tadd in process.
 + * DELING:    tdel in process.
 + * KILLING:   tkill in process.
 + */
 +#define TASKDEV_ST_NOTASK     0x00000001
 +#define TASKDEV_ST_ATTACHED   0x00000002
 +#define TASKDEV_ST_GARBAGE    0x00000004
 +#define TASKDEV_ST_INVALID    0x00000008
 +#define TASKDEV_ST_ADDREQ     0x00000100
 +#define TASKDEV_ST_DELREQ     0x00000200
 +#define TASKDEV_ST_FREEZED    0x00000400
 +#define TASKDEV_ST_ADDFAIL    0x00001000
 +#define TASKDEV_ST_ADDING     0x00010000
 +#define TASKDEV_ST_DELING     0x00020000
 +#define TASKDEV_ST_KILLING    0x00040000
 +#define TASKDEV_ST_STATE_MASK 0x7fffffff
 +#define TASKDEV_ST_STALE      0x80000000
 +
 +static struct {
 +      long state;
 +      char *name;
 +} devstate_desc[] = {
 +      { TASKDEV_ST_NOTASK,   "notask" },
 +      { TASKDEV_ST_ATTACHED, "attached" },
 +      { TASKDEV_ST_GARBAGE,  "garbage" },
 +      { TASKDEV_ST_INVALID,  "invalid" },
 +      { TASKDEV_ST_ADDREQ,   "addreq" },
 +      { TASKDEV_ST_DELREQ,   "delreq" },
 +      { TASKDEV_ST_FREEZED,  "freezed" },
 +      { TASKDEV_ST_ADDFAIL,  "addfail" },
 +      { TASKDEV_ST_ADDING,   "adding" },
 +      { TASKDEV_ST_DELING,   "deling" },
 +      { TASKDEV_ST_KILLING,  "killing" },
 +};
 +
 +static char *devstate_name(long state)
 +{
 +      int i;
 +      int max = ARRAY_SIZE(devstate_desc);
 +
 +      for (i = 0; i < max; i++) {
 +              if (state & devstate_desc[i].state)
 +                      return devstate_desc[i].name;
 +      }
 +      return "unknown";
 +}
 +
 +struct rcvdt_bk_struct {
 +      struct ipblink link;
 +      unsigned int rp;
 +};
 +
 +struct taskdev {
 +      struct bus_type *bus;
 +      struct device dev;      /* Generic device interface */
 +
 +      long state;
 +      struct rw_semaphore state_sem;
 +      wait_queue_head_t state_wait_q;
 +      struct mutex usecount_lock;
 +      unsigned int usecount;
 +      char name[TNM_LEN];
 +      struct file_operations fops;
 +      spinlock_t proc_list_lock;
 +      struct list_head proc_list;
 +      struct dsptask *task;
 +
 +      /* read stuff */
 +      wait_queue_head_t read_wait_q;
 +      struct mutex read_mutex;
 +      spinlock_t read_lock;
 +      union {
 +              struct kfifo *fifo;     /* for active word */
 +              struct rcvdt_bk_struct bk;
 +      } rcvdt;
 +
 +      /* write stuff */
 +      wait_queue_head_t write_wait_q;
 +      struct mutex write_mutex;
 +      spinlock_t wsz_lock;
 +      size_t wsz;
 +
 +      /* tctl stuff */
 +      wait_queue_head_t tctl_wait_q;
 +      struct mutex tctl_mutex;
 +      int tctl_stat;
 +      int tctl_ret;   /* return value for tctl_show() */
 +
 +      /* device lock */
 +      struct mutex lock;
 +      pid_t lock_pid;
 +};
 +
 +#define to_taskdev(n) container_of(n, struct taskdev, dev)
 +
 +struct dsptask {
 +      enum {
 +              TASK_ST_ERR = 0,
 +              TASK_ST_READY,
 +              TASK_ST_CFGREQ
 +      } state;
 +      u8 tid;
 +      char name[TNM_LEN];
 +      u16 ttyp;
 +      struct taskdev *dev;
 +
 +      /* read stuff */
 +      struct ipbuf_p *ipbuf_pvt_r;
 +
 +      /* write stuff */
 +      struct ipbuf_p *ipbuf_pvt_w;
 +
 +      /* mmap stuff */
 +      void *map_base;
 +      size_t map_length;
 +};
 +
 +#define sndtyp_acv(ttyp)      ((ttyp) & TTYP_ASND)
 +#define sndtyp_psv(ttyp)      (!((ttyp) & TTYP_ASND))
 +#define sndtyp_bk(ttyp)               ((ttyp) & TTYP_BKDM)
 +#define sndtyp_wd(ttyp)               (!((ttyp) & TTYP_BKDM))
 +#define sndtyp_pvt(ttyp)      ((ttyp) & TTYP_PVDM)
 +#define sndtyp_gbl(ttyp)      (!((ttyp) & TTYP_PVDM))
 +#define rcvtyp_acv(ttyp)      ((ttyp) & TTYP_ARCV)
 +#define rcvtyp_psv(ttyp)      (!((ttyp) & TTYP_ARCV))
 +#define rcvtyp_bk(ttyp)               ((ttyp) & TTYP_BKMD)
 +#define rcvtyp_wd(ttyp)               (!((ttyp) & TTYP_BKMD))
 +#define rcvtyp_pvt(ttyp)      ((ttyp) & TTYP_PVMD)
 +#define rcvtyp_gbl(ttyp)      (!((ttyp) & TTYP_PVMD))
 +
 +static inline int has_taskdev_lock(struct taskdev *dev);
 +static int dsp_rmdev_minor(unsigned char minor);
 +static int taskdev_init(struct taskdev *dev, char *name, unsigned char minor);
 +static void taskdev_delete(unsigned char minor);
 +static int taskdev_attach_task(struct taskdev *dev, struct dsptask *task);
 +static int dsp_tdel_bh(struct taskdev *dev, u16 type);
 +
 +static struct bus_type dsptask_bus = {
 +      .name = "dsptask",
 +};
 +
 +static struct class *dsp_task_class;
 +static DEFINE_MUTEX(devmgr_lock);
 +static struct taskdev *taskdev[TASKDEV_MAX];
 +static struct dsptask *dsptask[TASKDEV_MAX];
 +static DEFINE_MUTEX(cfg_lock);
 +static u16 cfg_cmd;
 +static u8 cfg_tid;
 +static DECLARE_WAIT_QUEUE_HEAD(cfg_wait_q);
 +static u8 n_task;     /* static task count */
 +static void *heap;
 +
 +#define is_dynamic_task(tid)  ((tid) >= n_task)
 +
 +#define devstate_read_lock(dev, devstate) \
 +              devstate_read_lock_timeout(dev, devstate, 0)
 +#define devstate_read_unlock(dev)     up_read(&(dev)->state_sem)
 +#define devstate_write_lock(dev, devstate) \
 +              devstate_write_lock_timeout(dev, devstate, 0)
 +#define devstate_write_unlock(dev)    up_write(&(dev)->state_sem)
 +
 +static ssize_t devname_show(struct device *d, struct device_attribute *attr,
 +                          char *buf);
 +static ssize_t devstate_show(struct device *d, struct device_attribute *attr,
 +                           char *buf);
 +static ssize_t proc_list_show(struct device *d, struct device_attribute *attr,
 +                            char *buf);
 +static ssize_t taskname_show(struct device *d, struct device_attribute *attr,
 +                           char *buf);
 +static ssize_t ttyp_show(struct device *d, struct device_attribute *attr,
 +                       char *buf);
 +static ssize_t fifosz_show(struct device *d, struct device_attribute *attr,
 +                         char *buf);
 +static int fifosz_store(struct device *d, struct device_attribute *attr,
 +                      const char *buf, size_t count);
 +static ssize_t fifocnt_show(struct device *d, struct device_attribute *attr,
 +                          char *buf);
 +static ssize_t ipblink_show(struct device *d, struct device_attribute *attr,
 +                          char *buf);
 +static ssize_t wsz_show(struct device *d, struct device_attribute *attr,
 +                      char *buf);
 +static ssize_t mmap_show(struct device *d, struct device_attribute *attr,
 +                       char *buf);
 +
 +#define __ATTR_RW(_name,_mode) { \
 +      .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE },     \
 +      .show   = _name##_show,                                 \
 +      .store  = _name##_store,                                        \
 +}
 +
 +static struct device_attribute dev_attr_devname   = __ATTR_RO(devname);
 +static struct device_attribute dev_attr_devstate  = __ATTR_RO(devstate);
 +static struct device_attribute dev_attr_proc_list = __ATTR_RO(proc_list);
 +static struct device_attribute dev_attr_taskname  = __ATTR_RO(taskname);
 +static struct device_attribute dev_attr_ttyp      = __ATTR_RO(ttyp);
 +static struct device_attribute dev_attr_fifosz    = __ATTR_RW(fifosz, 0666);
 +static struct device_attribute dev_attr_fifocnt   = __ATTR_RO(fifocnt);
 +static struct device_attribute dev_attr_ipblink   = __ATTR_RO(ipblink);
 +static struct device_attribute dev_attr_wsz       = __ATTR_RO(wsz);
 +static struct device_attribute dev_attr_mmap      = __ATTR_RO(mmap);
 +
 +static inline void set_taskdev_state(struct taskdev *dev, int state)
 +{
 +      pr_debug("omapdsp: devstate: CHANGE %s[%d]:\"%s\"->\"%s\"\n",
 +               dev->name,
 +               (dev->task ? dev->task->tid : -1),
 +               devstate_name(dev->state),
 +               devstate_name(state));
 +      dev->state = state;
 +}
 +
 +/*
 + * devstate_read_lock_timeout()
 + * devstate_write_lock_timeout():
 + * timeout != 0: dev->state can be diffeent from what you want.
 + * timeout == 0: no timeout
 + */
 +#define BUILD_DEVSTATE_LOCK_TIMEOUT(rw)                                               \
 +static int devstate_##rw##_lock_timeout(struct taskdev *dev, long devstate,     \
 +                                    int timeout)                              \
 +{                                                                             \
 +      DEFINE_WAIT(wait);                                                      \
 +      down_##rw(&dev->state_sem);                                             \
 +      while (!(dev->state & devstate)) {                                      \
 +              up_##rw(&dev->state_sem);                                       \
 +              prepare_to_wait(&dev->state_wait_q, &wait, TASK_INTERRUPTIBLE); \
 +              if (!timeout)                                                   \
 +                      timeout = MAX_SCHEDULE_TIMEOUT;                         \
 +              timeout = schedule_timeout(timeout);                            \
 +              finish_wait(&dev->state_wait_q, &wait);                         \
 +              if (timeout == 0)                                               \
 +                      return -ETIME;                                          \
 +              if (signal_pending(current))                                    \
 +                      return -EINTR;                                          \
 +              down_##rw(&dev->state_sem);                                     \
 +      }                                                                       \
 +      return 0;                                                               \
 +}
 +BUILD_DEVSTATE_LOCK_TIMEOUT(read)
 +BUILD_DEVSTATE_LOCK_TIMEOUT(write)
 +
 +#define BUILD_DEVSTATE_LOCK_AND_TEST(rw)                                      \
 +static int devstate_##rw##_lock_and_test(struct taskdev *dev, long devstate)  \
 +{                                                                             \
 +      down_##rw(&dev->state_sem);                                             \
 +      if (dev->state & devstate)                                              \
 +              return 1;       /* success */                                   \
 +      /* failure */                                                           \
 +      up_##rw(&dev->state_sem);                                               \
 +      return 0;                                                               \
 +}
 +BUILD_DEVSTATE_LOCK_AND_TEST(read)
 +BUILD_DEVSTATE_LOCK_AND_TEST(write)
 +
 +static int taskdev_lock_interruptible(struct taskdev *dev,
 +                                    struct mutex *lock)
 +{
 +      int ret;
 +
 +      if (has_taskdev_lock(dev))
 +              ret = mutex_lock_interruptible(lock);
 +      else {
 +              if ((ret = mutex_lock_interruptible(&dev->lock)) != 0)
 +                      return ret;
 +              ret = mutex_lock_interruptible(lock);
 +              mutex_unlock(&dev->lock);
 +      }
 +
 +      return ret;
 +}
 +
 +static int taskdev_lock_and_statelock_attached(struct taskdev *dev,
 +                                             struct mutex *lock)
 +{
 +      int ret;
 +
 +      if (!devstate_read_lock_and_test(dev, TASKDEV_ST_ATTACHED))
 +              return -ENODEV;
 +
 +      if ((ret = taskdev_lock_interruptible(dev, lock)) != 0)
 +              devstate_read_unlock(dev);
 +
 +      return ret;
 +}
 +
 +static inline void taskdev_unlock_and_stateunlock(struct taskdev *dev,
 +                                                    struct mutex *lock)
 +{
 +      mutex_unlock(lock);
 +      devstate_read_unlock(dev);
 +}
 +
 +/*
 + * taskdev_flush_buf()
 + * must be called under state_lock(ATTACHED) and dev->read_mutex.
 + */
 +static int taskdev_flush_buf(struct taskdev *dev)
 +{
 +      u16 ttyp = dev->task->ttyp;
 +
 +      if (sndtyp_wd(ttyp)) {
 +              /* word receiving */
 +              kfifo_reset(dev->rcvdt.fifo);
 +      } else {
 +              /* block receiving */
 +              struct rcvdt_bk_struct *rcvdt = &dev->rcvdt.bk;
 +
 +              if (sndtyp_gbl(ttyp))
 +                      ipblink_flush(&rcvdt->link);
 +              else {
 +                      ipblink_flush_pvt(&rcvdt->link);
 +                      release_ipbuf_pvt(dev->task->ipbuf_pvt_r);
 +              }
 +      }
 +
 +      return 0;
 +}
 +
 +/*
 + * taskdev_set_fifosz()
 + * must be called under dev->read_mutex.
 + */
 +static int taskdev_set_fifosz(struct taskdev *dev, unsigned long sz)
 +{
 +      u16 ttyp = dev->task->ttyp;
 +
 +      if (!(sndtyp_wd(ttyp) && sndtyp_acv(ttyp))) {
 +              printk(KERN_ERR
 +                     "omapdsp: buffer size can be changed only for "
 +                     "active word sending task.\n");
 +              return -EINVAL;
 +      }
 +      if ((sz == 0) || (sz & 1)) {
 +              printk(KERN_ERR "omapdsp: illegal buffer size! (%ld)\n"
 +                              "it must be even and non-zero value.\n", sz);
 +              return -EINVAL;
 +      }
 +
 +      if (kfifo_len(dev->rcvdt.fifo)) {
 +              printk(KERN_ERR "omapdsp: buffer is not empty!\n");
 +              return -EIO;
 +      }
 +
 +      kfifo_free(dev->rcvdt.fifo);
 +      dev->rcvdt.fifo = kfifo_alloc(sz, GFP_KERNEL, &dev->read_lock);
 +      if (IS_ERR(dev->rcvdt.fifo)) {
 +              printk(KERN_ERR
 +                     "omapdsp: unable to change receive buffer size. "
 +                     "(%ld bytes for %s)\n", sz, dev->name);
 +              return -ENOMEM;
 +      }
 +
 +      return 0;
 +}
 +
 +static inline int has_taskdev_lock(struct taskdev *dev)
 +{
 +      return (dev->lock_pid == current->pid);
 +}
 +
 +static int taskdev_lock(struct taskdev *dev)
 +{
 +      if (mutex_lock_interruptible(&dev->lock))
 +              return -EINTR;
 +      dev->lock_pid = current->pid;
 +      return 0;
 +}
 +
 +static int taskdev_unlock(struct taskdev *dev)
 +{
 +      if (!has_taskdev_lock(dev)) {
 +              printk(KERN_ERR
 +                     "omapdsp: an illegal process attempted to "
 +                     "unlock the dsptask lock!\n");
 +              return -EINVAL;
 +      }
 +      dev->lock_pid = 0;
 +      mutex_unlock(&dev->lock);
 +      return 0;
 +}
 +
 +static int dsp_task_config(struct dsptask *task, u8 tid)
 +{
 +      u16 ttyp;
 +      int ret;
 +
 +      task->tid = tid;
 +      dsptask[tid] = task;
 +
 +      /* TCFG request */
 +      task->state = TASK_ST_CFGREQ;
 +      if (mutex_lock_interruptible(&cfg_lock)) {
 +              ret = -EINTR;
 +              goto fail_out;
 +      }
 +      cfg_cmd = MBOX_CMD_DSP_TCFG;
 +      mbcompose_send_and_wait(TCFG, tid, 0, &cfg_wait_q);
 +      cfg_cmd = 0;
 +      mutex_unlock(&cfg_lock);
 +
 +      if (task->state != TASK_ST_READY) {
 +              printk(KERN_ERR "omapdsp: task %d configuration error!\n", tid);
 +              ret = -EINVAL;
 +              goto fail_out;
 +      }
 +
 +      if (strlen(task->name) <= 1)
 +              sprintf(task->name, "%d", tid);
 +      pr_info("omapdsp: task %d: name %s\n", tid, task->name);
 +
 +      ttyp = task->ttyp;
 +
 +      /*
 +       * task info sanity check
 +       */
 +
 +      /* task type check */
 +      if (rcvtyp_psv(ttyp) && rcvtyp_pvt(ttyp)) {
 +              printk(KERN_ERR "omapdsp: illegal task type(0x%04x), tid=%d\n",
 +                     tid, ttyp);
 +              ret = -EINVAL;
 +              goto fail_out;
 +      }
 +
 +      /* private buffer address check */
 +      if (sndtyp_pvt(ttyp) &&
 +          (ipbuf_p_validate(task->ipbuf_pvt_r, DIR_D2A) < 0)) {
 +              ret = -EINVAL;
 +              goto fail_out;
 +      }
 +      if (rcvtyp_pvt(ttyp) &&
 +          (ipbuf_p_validate(task->ipbuf_pvt_w, DIR_A2D) < 0)) {
 +              ret = -EINVAL;
 +              goto fail_out;
 +      }
 +
 +      /* mmap buffer configuration check */
 +      if ((task->map_length > 0) &&
 +          ((!ALIGN((unsigned long)task->map_base, PAGE_SIZE)) ||
 +           (!ALIGN(task->map_length, PAGE_SIZE)) ||
 +           (dsp_mem_type(task->map_base, task->map_length) != MEM_TYPE_EXTERN))) {
 +              printk(KERN_ERR
 +                     "omapdsp: illegal mmap buffer address(0x%p) or "
 +                     "length(0x%x).\n"
 +                     "  It needs to be page-aligned and located at "
 +                     "external memory.\n",
 +                     task->map_base, task->map_length);
 +              ret = -EINVAL;
 +              goto fail_out;
 +      }
 +
 +      return 0;
 +
 +fail_out:
 +      dsptask[tid] = NULL;
 +      return ret;
 +}
 +
 +static void dsp_task_init(struct dsptask *task)
 +{
 +      mbcompose_send(TCTL, task->tid, TCTL_TINIT);
 +}
 +
 +int dsp_task_config_all(u8 n)
 +{
 +      int i, ret;
 +      struct taskdev *devheap;
 +      struct dsptask *taskheap;
 +      size_t devheapsz, taskheapsz;
 +
 +      pr_info("omapdsp: found %d task(s)\n", n);
 +      if (n == 0)
 +              return 0;
 +
 +      /*
 +       * reducing kmalloc!
 +       */
 +      devheapsz  = sizeof(struct taskdev) * n;
 +      taskheapsz = sizeof(struct dsptask) * n;
 +      heap = kzalloc(devheapsz + taskheapsz, GFP_KERNEL);
 +      if (heap == NULL)
 +              return -ENOMEM;
 +      devheap  = heap;
 +      taskheap = heap + devheapsz;
 +
 +      n_task = n;
 +      for (i = 0; i < n; i++) {
 +              struct taskdev *dev  = &devheap[i];
 +              struct dsptask *task = &taskheap[i];
 +
 +              if ((ret = dsp_task_config(task, i)) < 0)
 +                      return ret;
 +              if ((ret = taskdev_init(dev, task->name, i)) < 0)
 +                      return ret;
 +              if ((ret = taskdev_attach_task(dev, task)) < 0)
 +                      return ret;
 +              dsp_task_init(task);
 +              pr_info("omapdsp: taskdev %s enabled.\n", dev->name);
 +      }
 +
 +      return 0;
 +}
 +
 +static void dsp_task_unconfig(struct dsptask *task)
 +{
 +      dsptask[task->tid] = NULL;
 +}
 +
 +void dsp_task_unconfig_all(void)
 +{
 +      unsigned char minor;
 +      u8 tid;
 +      struct dsptask *task;
 +
 +      for (minor = 0; minor < n_task; minor++) {
 +              /*
 +               * taskdev[minor] can be NULL in case of
 +               * configuration failure
 +               */
 +              if (taskdev[minor])
 +                      taskdev_delete(minor);
 +      }
 +      for (; minor < TASKDEV_MAX; minor++) {
 +              if (taskdev[minor])
 +                      dsp_rmdev_minor(minor);
 +      }
 +
 +      for (tid = 0; tid < n_task; tid++) {
 +              /*
 +               * dsptask[tid] can be NULL in case of
 +               * configuration failure
 +               */
 +              task = dsptask[tid];
 +              if (task)
 +                      dsp_task_unconfig(task);
 +      }
 +      for (; tid < TASKDEV_MAX; tid++) {
 +              task = dsptask[tid];
 +              if (task) {
 +                      /*
 +                       * on-demand tasks should be deleted in
 +                       * rmdev_minor(), but just in case.
 +                       */
 +                      dsp_task_unconfig(task);
 +                      kfree(task);
 +              }
 +      }
 +
 +      if (heap) {
 +              kfree(heap);
 +              heap = NULL;
 +      }
 +
 +      n_task = 0;
 +}
 +
 +static struct device_driver dsptask_driver = {
 +      .name   = "dsptask",
 +      .bus    = &dsptask_bus,
 +};
 +
 +u8 dsp_task_count(void)
 +{
 +      return n_task;
 +}
 +
 +int dsp_taskmod_busy(void)
 +{
 +      struct taskdev *dev;
 +      unsigned char minor;
 +      unsigned int usecount;
 +
 +      for (minor = 0; minor < TASKDEV_MAX; minor++) {
 +              dev = taskdev[minor];
 +              if (dev == NULL)
 +                      continue;
 +              if ((usecount = dev->usecount) > 0) {
 +                      printk("dsp_taskmod_busy(): %s: usecount=%d\n",
 +                             dev->name, usecount);
 +                      return 1;
 +              }
 +/*
 +              if ((dev->state & (TASKDEV_ST_ADDREQ |
 +                                 TASKDEV_ST_DELREQ)) {
 +*/
 +              if (dev->state & TASKDEV_ST_ADDREQ) {
 +                      printk("dsp_taskmod_busy(): %s is in %s\n",
 +                             dev->name, devstate_name(dev->state));
 +                      return 1;
 +              }
 +      }
 +      return 0;
 +}
 +
 +/*
 + * DSP task device file operations
 + */
 +static ssize_t dsp_task_read_wd_acv(struct file *file, char __user *buf,
 +                                  size_t count, loff_t *ppos)
 +{
 +      unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
 +      struct taskdev *dev = taskdev[minor];
 +      int ret = 0;
 +      DEFINE_WAIT(wait);
 +
 +      if (count == 0) {
 +              return 0;
 +      } else if (count & 0x1) {
 +              printk(KERN_ERR
 +                     "omapdsp: odd count is illegal for DSP task device.\n");
 +              return -EINVAL;
 +      }
 +
 +      if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex))
 +              return -ENODEV;
 +
 +
 +      prepare_to_wait(&dev->read_wait_q, &wait, TASK_INTERRUPTIBLE);
 +      if (kfifo_len(dev->rcvdt.fifo) == 0)
 +              schedule();
 +      finish_wait(&dev->read_wait_q, &wait);
 +      if (kfifo_len(dev->rcvdt.fifo) == 0) {
 +              /* failure */
 +              if (signal_pending(current))
 +                      ret = -EINTR;
 +              goto up_out;
 +      }
 +
 +
 +      ret = kfifo_get_to_user(dev->rcvdt.fifo, buf, count);
 +
 + up_out:
 +      taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
 +      return ret;
 +}
 +
 +static ssize_t dsp_task_read_bk_acv(struct file *file, char __user *buf,
 +                                  size_t count, loff_t *ppos)
 +{
 +      unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
 +      struct taskdev *dev = taskdev[minor];
 +      struct rcvdt_bk_struct *rcvdt = &dev->rcvdt.bk;
 +      ssize_t ret = 0;
 +      DEFINE_WAIT(wait);
 +
 +      if (count == 0) {
 +              return 0;
 +      } else if (count & 0x1) {
 +              printk(KERN_ERR
 +                     "omapdsp: odd count is illegal for DSP task device.\n");
 +              return -EINVAL;
 +      } else if ((int)buf & 0x1) {
 +              printk(KERN_ERR
 +                     "omapdsp: buf should be word aligned for "
 +                     "dsp_task_read().\n");
 +              return -EINVAL;
 +      }
 +
 +      if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex))
 +              return -ENODEV;
 +
 +      prepare_to_wait(&dev->read_wait_q, &wait, TASK_INTERRUPTIBLE);
 +      if (ipblink_empty(&rcvdt->link))
 +              schedule();
 +      finish_wait(&dev->read_wait_q, &wait);
 +      if (ipblink_empty(&rcvdt->link)) {
 +              /* failure */
 +              if (signal_pending(current))
 +                      ret = -EINTR;
 +              goto up_out;
 +      }
 +
 +      /* copy from delayed IPBUF */
 +      if (sndtyp_pvt(dev->task->ttyp)) {
 +              /* private */
 +              if (!ipblink_empty(&rcvdt->link)) {
 +                      struct ipbuf_p *ipbp = dev->task->ipbuf_pvt_r;
 +                      unsigned char *base, *src;
 +                      size_t bkcnt;
 +
 +                      if (dsp_mem_enable(ipbp) < 0) {
 +                              ret = -EBUSY;
 +                              goto up_out;
 +                      }
 +                      base = MKVIRT(ipbp->ah, ipbp->al);
 +                      bkcnt = ((unsigned long)ipbp->c) * 2 - rcvdt->rp;
 +                      if (dsp_address_validate(base, bkcnt,
 +                                               "task %s read buffer",
 +                                               dev->task->name) < 0) {
 +                              ret = -EINVAL;
 +                              goto pv_out1;
 +                      }
 +                      if (dsp_mem_enable(base) < 0) {
 +                              ret = -EBUSY;
 +                              goto pv_out1;
 +                      }
 +                      src = base + rcvdt->rp;
 +                      if (bkcnt > count) {
 +                              if (copy_to_user_dsp(buf, src, count)) {
 +                                      ret = -EFAULT;
 +                                      goto pv_out2;
 +                              }
 +                              ret = count;
 +                              rcvdt->rp += count;
 +                      } else {
 +                              if (copy_to_user_dsp(buf, src, bkcnt)) {
 +                                      ret = -EFAULT;
 +                                      goto pv_out2;
 +                              }
 +                              ret = bkcnt;
 +                              ipblink_del_pvt(&rcvdt->link);
 +                              release_ipbuf_pvt(ipbp);
 +                              rcvdt->rp = 0;
 +                      }
 +              pv_out2:
 +                      dsp_mem_disable(src);
 +              pv_out1:
 +                      dsp_mem_disable(ipbp);
 +              }
 +      } else {
 +              /* global */
 +              if (dsp_mem_enable_ipbuf() < 0) {
 +                      ret = -EBUSY;
 +                      goto up_out;
 +              }
 +              while (!ipblink_empty(&rcvdt->link)) {
 +                      unsigned char *src;
 +                      size_t bkcnt;
 +                      struct ipbuf_head *ipb_h = bid_to_ipbuf(rcvdt->link.top);
 +
 +                      src = ipb_h->p->d + rcvdt->rp;
 +                      bkcnt = ((unsigned long)ipb_h->p->c) * 2 - rcvdt->rp;
 +                      if (bkcnt > count) {
 +                              if (copy_to_user_dsp(buf, src, count)) {
 +                                      ret = -EFAULT;
 +                                      goto gb_out;
 +                              }
 +                              ret += count;
 +                              rcvdt->rp += count;
 +                              break;
 +                      } else {
 +                              if (copy_to_user_dsp(buf, src, bkcnt)) {
 +                                      ret = -EFAULT;
 +                                      goto gb_out;
 +                              }
 +                              ret += bkcnt;
 +                              buf += bkcnt;
 +                              count -= bkcnt;
 +                              ipblink_del_top(&rcvdt->link);
 +                              unuse_ipbuf(ipb_h);
 +                              rcvdt->rp = 0;
 +                      }
 +              }
 +      gb_out:
 +              dsp_mem_disable_ipbuf();
 +      }
 +
 + up_out:
 +      taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
 +      return ret;
 +}
 +
 +static ssize_t dsp_task_read_wd_psv(struct file *file, char __user *buf,
 +                                  size_t count, loff_t *ppos)
 +{
 +      unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
 +      struct taskdev *dev = taskdev[minor];
 +      int ret = 0;
 +
 +      if (count == 0) {
 +              return 0;
 +      } else if (count & 0x1) {
 +              printk(KERN_ERR
 +                     "omapdsp: odd count is illegal for DSP task device.\n");
 +              return -EINVAL;
 +      } else {
 +              /* force! */
 +              count = 2;
 +      }
 +
 +      if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex))
 +              return -ENODEV;
 +
 +      mbcompose_send_and_wait(WDREQ, dev->task->tid, 0, &dev->read_wait_q);
 +
 +      if (kfifo_len(dev->rcvdt.fifo) == 0) {
 +              /* failure */
 +              if (signal_pending(current))
 +                      ret = -EINTR;
 +              goto up_out;
 +      }
 +
 +      ret = kfifo_get_to_user(dev->rcvdt.fifo, buf, count);
 +
 +up_out:
 +      taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
 +      return ret;
 +}
 +
 +static ssize_t dsp_task_read_bk_psv(struct file *file, char __user *buf,
 +                                  size_t count, loff_t *ppos)
 +{
 +      unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
 +      struct taskdev *dev = taskdev[minor];
 +      struct rcvdt_bk_struct *rcvdt = &dev->rcvdt.bk;
 +      int ret = 0;
 +
 +      if (count == 0) {
 +              return 0;
 +      } else if (count & 0x1) {
 +              printk(KERN_ERR
 +                     "omapdsp: odd count is illegal for DSP task device.\n");
 +              return -EINVAL;
 +      } else if ((int)buf & 0x1) {
 +              printk(KERN_ERR
 +                     "omapdsp: buf should be word aligned for "
 +                     "dsp_task_read().\n");
 +              return -EINVAL;
 +      }
 +
 +      if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex))
 +              return -ENODEV;
 +
 +      mbcompose_send_and_wait(BKREQ, dev->task->tid, count/2,
 +                              &dev->read_wait_q);
 +
 +      if (ipblink_empty(&rcvdt->link)) {
 +              /* failure */
 +              if (signal_pending(current))
 +                      ret = -EINTR;
 +              goto up_out;
 +      }
 +
 +      /*
 +       * We will not receive more than requested count.
 +       */
 +      if (sndtyp_pvt(dev->task->ttyp)) {
 +              /* private */
 +              struct ipbuf_p *ipbp = dev->task->ipbuf_pvt_r;
 +              size_t rcvcnt;
 +              void *src;
 +
 +              if (dsp_mem_enable(ipbp) < 0) {
 +                      ret = -EBUSY;
 +                      goto up_out;
 +              }
 +              src = MKVIRT(ipbp->ah, ipbp->al);
 +              rcvcnt = ((unsigned long)ipbp->c) * 2;
 +              if (dsp_address_validate(src, rcvcnt, "task %s read buffer",
 +                                       dev->task->name) < 0) {
 +                      ret = -EINVAL;
 +                      goto pv_out1;
 +              }
 +              if (dsp_mem_enable(src) < 0) {
 +                      ret = -EBUSY;
 +                      goto pv_out1;
 +              }
 +              if (count > rcvcnt)
 +                      count = rcvcnt;
 +              if (copy_to_user_dsp(buf, src, count)) {
 +                      ret = -EFAULT;
 +                      goto pv_out2;
 +              }
 +              ipblink_del_pvt(&rcvdt->link);
 +              release_ipbuf_pvt(ipbp);
 +              ret = count;
 +pv_out2:
 +              dsp_mem_disable(src);
 +pv_out1:
 +              dsp_mem_disable(ipbp);
 +      } else {
 +              /* global */
 +              struct ipbuf_head *ipb_h = bid_to_ipbuf(rcvdt->link.top);
 +              size_t rcvcnt;
 +
 +              if (dsp_mem_enable_ipbuf() < 0) {
 +                      ret = -EBUSY;
 +                      goto up_out;
 +              }
 +              rcvcnt = ((unsigned long)ipb_h->p->c) * 2;
 +              if (count > rcvcnt)
 +                      count = rcvcnt;
 +              if (copy_to_user_dsp(buf, ipb_h->p->d, count)) {
 +                      ret = -EFAULT;
 +                      goto gb_out;
 +              }
 +              ipblink_del_top(&rcvdt->link);
 +              unuse_ipbuf(ipb_h);
 +              ret = count;
 +gb_out:
 +              dsp_mem_disable_ipbuf();
 +      }
 +
 +up_out:
 +      taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
 +      return ret;
 +}
 +
 +static ssize_t dsp_task_write_wd(struct file *file, const char __user *buf,
 +                               size_t count, loff_t *ppos)
 +{
 +      unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
 +      struct taskdev *dev = taskdev[minor];
 +      u16 wd;
 +      int ret = 0;
 +      DEFINE_WAIT(wait);
 +
 +      if (count == 0) {
 +              return 0;
 +      } else if (count & 0x1) {
 +              printk(KERN_ERR
 +                     "omapdsp: odd count is illegal for DSP task device.\n");
 +              return -EINVAL;
 +      } else {
 +              /* force! */
 +              count = 2;
 +      }
 +
 +      if (taskdev_lock_and_statelock_attached(dev, &dev->write_mutex))
 +              return -ENODEV;
 +
 +      prepare_to_wait(&dev->write_wait_q, &wait, TASK_INTERRUPTIBLE);
 +      if (dev->wsz == 0)
 +              schedule();
 +      finish_wait(&dev->write_wait_q, &wait);
 +      if (dev->wsz == 0) {
 +              /* failure */
 +              if (signal_pending(current))
 +                      ret = -EINTR;
 +              goto up_out;
 +      }
 +
 +      if (copy_from_user(&wd, buf, count)) {
 +              ret = -EFAULT;
 +              goto up_out;
 +      }
 +
 +      spin_lock(&dev->wsz_lock);
 +      if (mbcompose_send(WDSND, dev->task->tid, wd) < 0) {
 +              spin_unlock(&dev->wsz_lock);
 +              goto up_out;
 +      }
 +      ret = count;
 +      if (rcvtyp_acv(dev->task->ttyp))
 +              dev->wsz = 0;
 +      spin_unlock(&dev->wsz_lock);
 +
 + up_out:
 +      taskdev_unlock_and_stateunlock(dev, &dev->write_mutex);
 +      return ret;
 +}
 +
 +static ssize_t dsp_task_write_bk(struct file *file, const char __user *buf,
 +                               size_t count, loff_t *ppos)
 +{
 +      unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
 +      struct taskdev *dev = taskdev[minor];
 +      int ret = 0;
 +      DEFINE_WAIT(wait);
 +
 +      if (count == 0) {
 +              return 0;
 +      } else if (count & 0x1) {
 +              printk(KERN_ERR
 +                     "omapdsp: odd count is illegal for DSP task device.\n");
 +              return -EINVAL;
 +      } else if ((int)buf & 0x1) {
 +              printk(KERN_ERR
 +                     "omapdsp: buf should be word aligned for "
 +                     "dsp_task_write().\n");
 +              return -EINVAL;
 +      }
 +
 +      if (taskdev_lock_and_statelock_attached(dev, &dev->write_mutex))
 +              return -ENODEV;
 +
 +      prepare_to_wait(&dev->write_wait_q, &wait, TASK_INTERRUPTIBLE);
 +      if (dev->wsz == 0)
 +              schedule();
 +      finish_wait(&dev->write_wait_q, &wait);
 +      if (dev->wsz == 0) {
 +              /* failure */
 +              if (signal_pending(current))
 +                      ret = -EINTR;
 +              goto up_out;
 +      }
 +
 +      if (count > dev->wsz)
 +              count = dev->wsz;
 +
 +      if (rcvtyp_pvt(dev->task->ttyp)) {
 +              /* private */
 +              struct ipbuf_p *ipbp = dev->task->ipbuf_pvt_w;
 +              unsigned char *dst;
 +
 +              if (dsp_mem_enable(ipbp) < 0) {
 +                      ret = -EBUSY;
 +                      goto up_out;
 +              }
 +              dst = MKVIRT(ipbp->ah, ipbp->al);
 +              if (dsp_address_validate(dst, count, "task %s write buffer",
 +                                       dev->task->name) < 0) {
 +                      ret = -EINVAL;
 +                      goto pv_out1;
 +              }
 +              if (dsp_mem_enable(dst) < 0) {
 +                      ret = -EBUSY;
 +                      goto pv_out1;
 +              }
 +              if (copy_from_user_dsp(dst, buf, count)) {
 +                      ret = -EFAULT;
 +                      goto pv_out2;
 +              }
 +              ipbp->c = count/2;
 +              ipbp->s = dev->task->tid;
 +              spin_lock(&dev->wsz_lock);
 +              if (mbcompose_send(BKSNDP, dev->task->tid, 0) == 0) {
 +                      if (rcvtyp_acv(dev->task->ttyp))
 +                              dev->wsz = 0;
 +                      ret = count;
 +              }
 +              spin_unlock(&dev->wsz_lock);
 +      pv_out2:
 +              dsp_mem_disable(dst);
 +      pv_out1:
 +              dsp_mem_disable(ipbp);
 +      } else {
 +              /* global */
 +              struct ipbuf_head *ipb_h;
 +
 +              if (dsp_mem_enable_ipbuf() < 0) {
 +                      ret = -EBUSY;
 +                      goto up_out;
 +              }
 +              if ((ipb_h = get_free_ipbuf(dev->task->tid)) == NULL)
 +                      goto gb_out;
 +              if (copy_from_user_dsp(ipb_h->p->d, buf, count)) {
 +                      release_ipbuf(ipb_h);
 +                      ret = -EFAULT;
 +                      goto gb_out;
 +              }
 +              ipb_h->p->c  = count/2;
 +              ipb_h->p->sa = dev->task->tid;
 +              spin_lock(&dev->wsz_lock);
 +              if (mbcompose_send(BKSND, dev->task->tid, ipb_h->bid) == 0) {
 +                      if (rcvtyp_acv(dev->task->ttyp))
 +                              dev->wsz = 0;
 +                      ret = count;
 +                      ipb_bsycnt_inc(&ipbcfg);
 +              } else
 +                      release_ipbuf(ipb_h);
 +              spin_unlock(&dev->wsz_lock);
 +      gb_out:
 +              dsp_mem_disable_ipbuf();
 +      }
 +
 + up_out:
 +      taskdev_unlock_and_stateunlock(dev, &dev->write_mutex);
 +      return ret;
 +}
 +
 +static unsigned int dsp_task_poll(struct file * file, poll_table * wait)
 +{
 +      unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
 +      struct taskdev *dev = taskdev[minor];
 +      struct dsptask *task = dev->task;
 +      unsigned int mask = 0;
 +
 +      if (!devstate_read_lock_and_test(dev, TASKDEV_ST_ATTACHED))
 +              return 0;
 +      poll_wait(file, &dev->read_wait_q, wait);
 +      poll_wait(file, &dev->write_wait_q, wait);
 +      if (sndtyp_psv(task->ttyp) ||
 +          (sndtyp_wd(task->ttyp) && kfifo_len(dev->rcvdt.fifo)) ||
 +          (sndtyp_bk(task->ttyp) && !ipblink_empty(&dev->rcvdt.bk.link)))
 +              mask |= POLLIN | POLLRDNORM;
 +      if (dev->wsz)
 +              mask |= POLLOUT | POLLWRNORM;
 +      devstate_read_unlock(dev);
 +
 +      return mask;
 +}
 +
 +static int dsp_tctl_issue(struct taskdev *dev, u16 cmd, int argc, u16 argv[])
 +{
 +      int tctl_argc;
 +      struct mb_exarg mbarg, *mbargp;
 +      int interactive;
 +      u8 tid;
 +      int ret = 0;
 +
 +      if (cmd < 0x8000) {
 +              /*
 +               * 0x0000 - 0x7fff
 +               * system reserved TCTL commands
 +               */
 +              switch (cmd) {
 +              case TCTL_TEN:
 +              case TCTL_TDIS:
 +                      tctl_argc = 0;
 +                      interactive = 0;
 +                      break;
 +              default:
 +                      return -EINVAL;
 +              }
 +      }
 +      /*
 +       * 0x8000 - 0xffff
 +       * user-defined TCTL commands
 +       */
 +      else if (cmd < 0x8100) {
 +              /* 0x8000-0x80ff: no arg, non-interactive */
 +              tctl_argc = 0;
 +              interactive = 0;
 +      } else if (cmd < 0x8200) {
 +              /* 0x8100-0x81ff: 1 arg, non-interactive */
 +              tctl_argc = 1;
 +              interactive = 0;
 +      } else if (cmd < 0x9000) {
 +              /* 0x8200-0x8fff: reserved */
 +              return -EINVAL;
 +      } else if (cmd < 0x9100) {
 +              /* 0x9000-0x90ff: no arg, interactive */
 +              tctl_argc = 0;
 +              interactive = 1;
 +      } else if (cmd < 0x9200) {
 +              /* 0x9100-0x91ff: 1 arg, interactive */
 +              tctl_argc = 1;
 +              interactive = 1;
 +      } else {
 +              /* 0x9200-0xffff: reserved */
 +              return -EINVAL;
 +      }
 +
 +      /*
 +       * if argc < 0, use tctl_argc as is.
 +       * if argc >= 0, check arg count.
 +       */
 +      if ((argc >= 0) && (argc != tctl_argc))
 +              return -EINVAL;
 +
 +      /*
 +       * issue TCTL
 +       */
 +      if (taskdev_lock_interruptible(dev, &dev->tctl_mutex))
 +              return -EINTR;
 +
 +      tid = dev->task->tid;
 +      if (tctl_argc > 0) {
 +              mbarg.argc = tctl_argc;
 +              mbarg.tid  = tid;
 +              mbarg.argv = argv;
 +              mbargp = &mbarg;
 +      } else
 +              mbargp = NULL;
 +
 +      if (interactive) {
 +              dev->tctl_stat = -EINVAL;
 +
 +              mbcompose_send_and_wait_exarg(TCTL, tid, cmd, mbargp,
 +                                            &dev->tctl_wait_q);
 +              if (signal_pending(current)) {
 +                      ret = -EINTR;
 +                      goto up_out;
 +              }
 +              if ((ret = dev->tctl_stat) < 0) {
 +                      printk(KERN_ERR "omapdsp: TCTL not responding.\n");
 +                      goto up_out;
 +              }
 +      } else
 +              mbcompose_send_exarg(TCTL, tid, cmd, mbargp);
 +
 +up_out:
 +      mutex_unlock(&dev->tctl_mutex);
 +      return ret;
 +}
 +
 +static int dsp_task_ioctl(struct inode *inode, struct file *file,
 +                        unsigned int cmd, unsigned long arg)
 +{
 +      unsigned int minor = MINOR(inode->i_rdev);
 +      struct taskdev *dev = taskdev[minor];
 +      int ret;
 +
 +      if (cmd < 0x10000) {
 +              /* issue TCTL */
 +              u16 mbargv[1];
 +
 +              mbargv[0] = arg & 0xffff;
 +              return dsp_tctl_issue(dev, cmd, -1, mbargv);
 +      }
 +
 +      /* non TCTL ioctls */
 +      switch (cmd) {
 +
 +      case TASK_IOCTL_LOCK:
 +              ret = taskdev_lock(dev);
 +              break;
 +
 +      case TASK_IOCTL_UNLOCK:
 +              ret = taskdev_unlock(dev);
 +              break;
 +
 +      case TASK_IOCTL_BFLSH:
 +              if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex))
 +                      return -ENODEV;
 +              ret = taskdev_flush_buf(dev);
 +              taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
 +              break;
 +
 +      case TASK_IOCTL_SETBSZ:
 +              if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex))
 +                      return -ENODEV;
 +              ret = taskdev_set_fifosz(dev, arg);
 +              taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
 +              break;
 +
 +      case TASK_IOCTL_GETNAME:
 +              ret = 0;
 +              if (copy_to_user((void __user *)arg, dev->name,
 +                               strlen(dev->name) + 1))
 +                      ret = -EFAULT;
 +              break;
 +
 +      default:
 +              ret = -ENOIOCTLCMD;
 +
 +      }
 +
 +      return ret;
 +}
 +
 +static void dsp_task_mmap_open(struct vm_area_struct *vma)
 +{
 +      struct taskdev *dev = (struct taskdev *)vma->vm_private_data;
 +      struct dsptask *task;
 +      size_t len = vma->vm_end - vma->vm_start;
 +
 +      BUG_ON(!(dev->state & TASKDEV_ST_ATTACHED));
 +      task = dev->task;
 +      omap_mmu_exmap_use(&dsp_mmu, task->map_base, len);
 +}
 +
 +static void dsp_task_mmap_close(struct vm_area_struct *vma)
 +{
 +      struct taskdev *dev = (struct taskdev *)vma->vm_private_data;
 +      struct dsptask *task;
 +      size_t len = vma->vm_end - vma->vm_start;
 +
 +      BUG_ON(!(dev->state & TASKDEV_ST_ATTACHED));
 +      task = dev->task;
 +      omap_mmu_exmap_unuse(&dsp_mmu, task->map_base, len);
 +}
 +
 +/**
 + * On demand page allocation is not allowed. The mapping area is defined by
 + * corresponding DSP tasks.
 + */
 +static int dsp_task_mmap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 +{
 +      return VM_FAULT_NOPAGE;
 +}
 +
 +static struct vm_operations_struct dsp_task_vm_ops = {
 +      .open = dsp_task_mmap_open,
 +      .close = dsp_task_mmap_close,
 +      .fault = dsp_task_mmap_fault,
 +};
 +
 +static int dsp_task_mmap(struct file *filp, struct vm_area_struct *vma)
 +{
 +      void *tmp_vadr;
 +      unsigned long tmp_padr, tmp_vmadr, off;
 +      size_t req_len, tmp_len;
 +      unsigned int minor = MINOR(filp->f_dentry->d_inode->i_rdev);
 +      struct taskdev *dev = taskdev[minor];
 +      struct dsptask *task;
 +      int ret = 0;
 +
 +      if (!devstate_read_lock_and_test(dev, TASKDEV_ST_ATTACHED))
 +              return -ENODEV;
 +      task = dev->task;
 +
 +      /*
 +       * Don't swap this area out
 +       * Don't dump this area to a core file
 +       */
 +      vma->vm_flags |= VM_RESERVED | VM_IO;
 +
 +      /* Do not cache this area */
 +      vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 +
 +      req_len = vma->vm_end - vma->vm_start;
 +      off = vma->vm_pgoff << PAGE_SHIFT;
 +      tmp_vmadr = vma->vm_start;
 +      tmp_vadr = task->map_base + off;
 +      do {
 +              tmp_padr = omap_mmu_virt_to_phys(&dsp_mmu, tmp_vadr, &tmp_len);
 +              if (tmp_padr == 0) {
 +                      printk(KERN_ERR
 +                             "omapdsp: task %s: illegal address "
 +                             "for mmap: %p", task->name, tmp_vadr);
 +                      /* partial mapping will be cleared in upper layer */
 +                      ret = -EINVAL;
 +                      goto unlock_out;
 +              }
 +              if (tmp_len > req_len)
 +                      tmp_len = req_len;
 +
 +              pr_debug("omapdsp: mmap info: "
 +                       "vmadr = %08lx, padr = %08lx, len = %x\n",
 +                       tmp_vmadr, tmp_padr, tmp_len);
 +              if (remap_pfn_range(vma, tmp_vmadr, tmp_padr >> PAGE_SHIFT,
 +                                  tmp_len, vma->vm_page_prot) != 0) {
 +                      printk(KERN_ERR
 +                             "omapdsp: task %s: remap_page_range() failed.\n",
 +                             task->name);
 +                      /* partial mapping will be cleared in upper layer */
 +                      ret = -EINVAL;
 +                      goto unlock_out;
 +              }
 +
 +              req_len   -= tmp_len;
 +              tmp_vmadr += tmp_len;
 +              tmp_vadr  += tmp_len;
 +      } while (req_len);
 +
 +      vma->vm_ops = &dsp_task_vm_ops;
 +      vma->vm_private_data = dev;
 +      omap_mmu_exmap_use(&dsp_mmu, task->map_base, vma->vm_end - vma->vm_start);
 +
 +unlock_out:
 +      devstate_read_unlock(dev);
 +      return ret;
 +}
 +
 +static int dsp_task_open(struct inode *inode, struct file *file)
 +{
 +      unsigned int minor = MINOR(inode->i_rdev);
 +      struct taskdev *dev;
 +      int ret = 0;
 +
 +      if ((minor >= TASKDEV_MAX) || ((dev = taskdev[minor]) == NULL))
 +              return -ENODEV;
 +
 + restart:
 +      mutex_lock(&dev->usecount_lock);
 +      down_write(&dev->state_sem);
 +
 +      /* state can be NOTASK, ATTACHED/FREEZED, KILLING, GARBAGE or INVALID here. */
 +      switch (dev->state & TASKDEV_ST_STATE_MASK) {
 +      case TASKDEV_ST_NOTASK:
 +              break;
 +      case TASKDEV_ST_ATTACHED:
 +              goto attached;
 +
 +      case TASKDEV_ST_INVALID:
 +              up_write(&dev->state_sem);
 +              mutex_unlock(&dev->usecount_lock);
 +              return -ENODEV;
 +
 +      case TASKDEV_ST_FREEZED:
 +      case TASKDEV_ST_KILLING:
 +      case TASKDEV_ST_GARBAGE:
 +      case TASKDEV_ST_DELREQ:
 +              /* on the kill process. wait until it becomes NOTASK. */
 +              up_write(&dev->state_sem);
 +              mutex_unlock(&dev->usecount_lock);
 +              if (devstate_write_lock(dev, TASKDEV_ST_NOTASK) < 0)
 +                      return -EINTR;
 +              devstate_write_unlock(dev);
 +              goto restart;
 +      }
 +
 +      /* NOTASK */
 +      set_taskdev_state(dev, TASKDEV_ST_ADDREQ);
 +      /* wake up twch daemon for tadd */
 +      dsp_twch_touch();
 +      up_write(&dev->state_sem);
 +      if (devstate_write_lock(dev, TASKDEV_ST_ATTACHED |
 +                              TASKDEV_ST_ADDFAIL) < 0) {
 +              /* cancelled */
 +              if (!devstate_write_lock_and_test(dev, TASKDEV_ST_ADDREQ)) {
 +                      mutex_unlock(&dev->usecount_lock);
 +                      /* out of control ??? */
 +                      return -EINTR;
 +              }
 +              set_taskdev_state(dev, TASKDEV_ST_NOTASK);
 +              ret = -EINTR;
 +              goto change_out;
 +      }
 +      if (dev->state & TASKDEV_ST_ADDFAIL) {
 +              printk(KERN_ERR "omapdsp: task attach failed for %s!\n",
 +                     dev->name);
 +              ret = -EBUSY;
 +              set_taskdev_state(dev, TASKDEV_ST_NOTASK);
 +              goto change_out;
 +      }
 +
 + attached:
 +      ret = proc_list_add(&dev->proc_list_lock,
 +                          &dev->proc_list, current, file);
 +      if (ret)
 +              goto out;
 +
 +      dev->usecount++;
 +      file->f_op = &dev->fops;
 +      up_write(&dev->state_sem);
 +      mutex_unlock(&dev->usecount_lock);
 +
 +#ifdef DSP_PTE_FREE   /* not used currently. */
 +      dsp_map_update(current);
 +      dsp_cur_users_add(current);
 +#endif /* DSP_PTE_FREE */
 +      return 0;
 +
 + change_out:
 +      wake_up_interruptible_all(&dev->state_wait_q);
 + out:
 +      up_write(&dev->state_sem);
 +      mutex_unlock(&dev->usecount_lock);
 +      return ret;
 +}
 +
 +static int dsp_task_release(struct inode *inode, struct file *file)
 +{
 +      unsigned int minor = MINOR(inode->i_rdev);
 +      struct taskdev *dev = taskdev[minor];
 +
 +#ifdef DSP_PTE_FREE   /* not used currently. */
 +      dsp_cur_users_del(current);
 +#endif /* DSP_PTE_FREE */
 +
 +      if (has_taskdev_lock(dev))
 +              taskdev_unlock(dev);
 +
 +      proc_list_del(&dev->proc_list_lock, &dev->proc_list, current, file);
 +      mutex_lock(&dev->usecount_lock);
 +      if (--dev->usecount > 0) {
 +              /* other processes are using this device. no state change. */
 +              mutex_unlock(&dev->usecount_lock);
 +              return 0;
 +      }
 +
 +      /* usecount == 0 */
 +      down_write(&dev->state_sem);
 +
 +      /* state can be ATTACHED/FREEZED, KILLING or GARBAGE here. */
 +      switch (dev->state & TASKDEV_ST_STATE_MASK) {
 +
 +      case TASKDEV_ST_KILLING:
 +              break;
 +
 +      case TASKDEV_ST_GARBAGE:
 +              set_taskdev_state(dev, TASKDEV_ST_NOTASK);
 +              wake_up_interruptible_all(&dev->state_wait_q);
 +              break;
 +
 +      case TASKDEV_ST_ATTACHED:
 +      case TASKDEV_ST_FREEZED:
 +              if (is_dynamic_task(minor)) {
 +                      set_taskdev_state(dev, TASKDEV_ST_DELREQ);
 +                      /* wake up twch daemon for tdel */
 +                      dsp_twch_touch();
 +              }
 +              break;
 +
 +      }
 +
 +      up_write(&dev->state_sem);
 +      mutex_unlock(&dev->usecount_lock);
 +      return 0;
 +}
 +
 +/*
 + * mkdev / rmdev
 + */
 +int dsp_mkdev(char *name)
 +{
 +      struct taskdev *dev;
 +      int status;
 +      unsigned char minor;
 +      int ret;
 +
 +      if (dsp_cfgstat_get_stat() != CFGSTAT_READY) {
 +              printk(KERN_ERR "omapdsp: dsp has not been configured.\n");
 +              return -EINVAL;
 +      }
 +
 +      if (mutex_lock_interruptible(&devmgr_lock))
 +              return -EINTR;
 +
 +      /* naming check */
 +      for (minor = 0; minor < TASKDEV_MAX; minor++) {
 +              if (taskdev[minor] && !strcmp(taskdev[minor]->name, name)) {
 +                      printk(KERN_ERR
 +                             "omapdsp: task device name %s is already "
 +                             "in use.\n", name);
 +                      ret = -EINVAL;
 +                      goto out;
 +              }
 +      }
 +
 +      /* find free minor number */
 +      for (minor = n_task; minor < TASKDEV_MAX; minor++) {
 +              if (taskdev[minor] == NULL)
 +                      goto do_make;
 +      }
 +      printk(KERN_ERR "omapdsp: Too many task devices.\n");
 +      ret = -EBUSY;
 +      goto out;
 +
 +do_make:
 +      if ((dev = kzalloc(sizeof(struct taskdev), GFP_KERNEL)) == NULL) {
 +              ret = -ENOMEM;
 +              goto out;
 +      }
 +      if ((status = taskdev_init(dev, name, minor)) < 0) {
 +              kfree(dev);
 +              ret = status;
 +              goto out;
 +      }
 +      ret = minor;
 +
 +out:
 +      mutex_unlock(&devmgr_lock);
 +      return ret;
 +}
 +
 +int dsp_rmdev(char *name)
 +{
 +      unsigned char minor;
 +      int status;
 +      int ret;
 +
 +      if (dsp_cfgstat_get_stat() != CFGSTAT_READY) {
 +              printk(KERN_ERR "omapdsp: dsp has not been configured.\n");
 +              return -EINVAL;
 +      }
 +
 +      if (mutex_lock_interruptible(&devmgr_lock))
 +              return -EINTR;
 +
 +      /* find in dynamic devices */
 +      for (minor = n_task; minor < TASKDEV_MAX; minor++) {
 +              if (taskdev[minor] && !strcmp(taskdev[minor]->name, name))
 +                      goto do_remove;
 +      }
 +
 +      /* find in static devices */
 +      for (minor = 0; minor < n_task; minor++) {
 +              if (taskdev[minor] && !strcmp(taskdev[minor]->name, name)) {
 +                      printk(KERN_ERR
 +                             "omapdsp: task device %s is static.\n", name);
 +                      ret = -EINVAL;
 +                      goto out;
 +              }
 +      }
 +
 +      printk(KERN_ERR "omapdsp: task device %s not found.\n", name);
 +      return -EINVAL;
 +
 +do_remove:
 +      ret = minor;
 +      if ((status = dsp_rmdev_minor(minor)) < 0)
 +              ret = status;
 +out:
 +      mutex_unlock(&devmgr_lock);
 +      return ret;
 +}
 +
 +static int dsp_rmdev_minor(unsigned char minor)
 +{
 +      struct taskdev *dev = taskdev[minor];
 +
 +      while (!down_write_trylock(&dev->state_sem)) {
 +              down_read(&dev->state_sem);
 +              if (dev->state & (TASKDEV_ST_ATTACHED |
 +                                TASKDEV_ST_FREEZED)) {
 +                      /*
 +                       * task is working. kill it.
 +                       * ATTACHED -> FREEZED can be changed under
 +                       * down_read of state_sem..
 +                       */
 +                      set_taskdev_state(dev, TASKDEV_ST_FREEZED);
 +                      wake_up_interruptible_all(&dev->read_wait_q);
 +                      wake_up_interruptible_all(&dev->write_wait_q);
 +                      wake_up_interruptible_all(&dev->tctl_wait_q);
 +              }
 +              up_read(&dev->state_sem);
 +              schedule();
 +      }
 +
 +      switch (dev->state & TASKDEV_ST_STATE_MASK) {
 +
 +      case TASKDEV_ST_NOTASK:
 +      case TASKDEV_ST_INVALID:
 +              /* fine */
 +              goto notask;
 +
 +      case TASKDEV_ST_ATTACHED:
 +      case TASKDEV_ST_FREEZED:
 +              /* task is working. kill it. */
 +              set_taskdev_state(dev, TASKDEV_ST_KILLING);
 +              up_write(&dev->state_sem);
 +              dsp_tdel_bh(dev, TDEL_KILL);
 +              goto invalidate;
 +
 +      case TASKDEV_ST_ADDREQ:
 +              /* open() is waiting. drain it. */
 +              set_taskdev_state(dev, TASKDEV_ST_ADDFAIL);
 +              wake_up_interruptible_all(&dev->state_wait_q);
 +              break;
 +
 +      case TASKDEV_ST_DELREQ:
 +              /* nobody is waiting. */
 +              set_taskdev_state(dev, TASKDEV_ST_NOTASK);
 +              wake_up_interruptible_all(&dev->state_wait_q);
 +              break;
 +
 +      case TASKDEV_ST_ADDING:
 +      case TASKDEV_ST_DELING:
 +      case TASKDEV_ST_KILLING:
 +      case TASKDEV_ST_GARBAGE:
 +      case TASKDEV_ST_ADDFAIL:
 +              /* transient state. wait for a moment. */
 +              break;
 +
 +      }
 +
 +      up_write(&dev->state_sem);
 +
 +invalidate:
 +      /* wait for some time and hope the state is settled */
 +      devstate_read_lock_timeout(dev, TASKDEV_ST_NOTASK, 5 * HZ);
 +      if (!(dev->state & TASKDEV_ST_NOTASK)) {
 +              printk(KERN_WARNING
 +                     "omapdsp: illegal device state (%s) on rmdev %s.\n",
 +                     devstate_name(dev->state), dev->name);
 +      }
 +notask:
 +      set_taskdev_state(dev, TASKDEV_ST_INVALID);
 +      devstate_read_unlock(dev);
 +
 +      taskdev_delete(minor);
 +      kfree(dev);
 +
 +      return 0;
 +}
 +
 +static struct file_operations dsp_task_fops = {
 +      .owner   = THIS_MODULE,
 +      .poll    = dsp_task_poll,
 +      .ioctl   = dsp_task_ioctl,
 +      .open    = dsp_task_open,
 +      .release = dsp_task_release,
 +};
 +
 +static void dsptask_dev_release(struct device *dev)
 +{
 +}
 +
 +static int taskdev_init(struct taskdev *dev, char *name, unsigned char minor)
 +{
 +      int ret;
 +      struct device *task_dev;
 +
 +      taskdev[minor] = dev;
 +
 +      spin_lock_init(&dev->proc_list_lock);
 +      INIT_LIST_HEAD(&dev->proc_list);
 +      init_waitqueue_head(&dev->read_wait_q);
 +      init_waitqueue_head(&dev->write_wait_q);
 +      init_waitqueue_head(&dev->tctl_wait_q);
 +      mutex_init(&dev->read_mutex);
 +      mutex_init(&dev->write_mutex);
 +      mutex_init(&dev->tctl_mutex);
 +      mutex_init(&dev->lock);
 +      spin_lock_init(&dev->wsz_lock);
 +      dev->tctl_ret = -EINVAL;
 +      dev->lock_pid = 0;
 +
 +      strncpy(dev->name, name, TNM_LEN);
 +      dev->name[TNM_LEN-1] = '\0';
 +      set_taskdev_state(dev, (minor < n_task) ? TASKDEV_ST_ATTACHED : TASKDEV_ST_NOTASK);
 +      dev->usecount = 0;
 +      mutex_init(&dev->usecount_lock);
 +      memcpy(&dev->fops, &dsp_task_fops, sizeof(struct file_operations));
 +
 +      dev->dev.parent = omap_dsp->dev;
 +      dev->dev.bus = &dsptask_bus;
 +      sprintf(dev->dev.bus_id, "dsptask%d", minor);
 +      dev->dev.release = dsptask_dev_release;
 +      ret = device_register(&dev->dev);
 +      if (ret) {
 +              printk(KERN_ERR "device_register failed: %d\n", ret);
 +              return ret;
 +      }
 +      ret = device_create_file(&dev->dev, &dev_attr_devname);
 +      if (ret)
 +              goto fail_create_devname;
 +      ret = device_create_file(&dev->dev, &dev_attr_devstate);
 +      if (ret)
 +              goto fail_create_devstate;
 +      ret = device_create_file(&dev->dev, &dev_attr_proc_list);
 +      if (ret)
 +              goto fail_create_proclist;
 +
 +      task_dev = device_create(dsp_task_class, NULL,
 +                               MKDEV(OMAP_DSP_TASK_MAJOR, minor),
 +                               "dsptask%d", (int)minor);
 +
 +      if (unlikely(IS_ERR(task_dev))) {
 +              ret = -EINVAL;
 +              goto fail_create_taskclass;
 +      }
 +
 +      init_waitqueue_head(&dev->state_wait_q);
 +      init_rwsem(&dev->state_sem);
 +
 +      return 0;
 +
 + fail_create_taskclass:
 +      device_remove_file(&dev->dev, &dev_attr_proc_list);
 + fail_create_proclist:
 +      device_remove_file(&dev->dev, &dev_attr_devstate);
 + fail_create_devstate:
 +      device_remove_file(&dev->dev, &dev_attr_devname);
 + fail_create_devname:
 +      device_unregister(&dev->dev);
 +      return ret;
 +}
 +
 +static void taskdev_delete(unsigned char minor)
 +{
 +      struct taskdev *dev = taskdev[minor];
 +
 +      if (!dev)
 +              return;
 +      device_remove_file(&dev->dev, &dev_attr_devname);
 +      device_remove_file(&dev->dev, &dev_attr_devstate);
 +      device_remove_file(&dev->dev, &dev_attr_proc_list);
 +      device_destroy(dsp_task_class, MKDEV(OMAP_DSP_TASK_MAJOR, minor));
 +      device_unregister(&dev->dev);
 +      proc_list_flush(&dev->proc_list_lock, &dev->proc_list);
 +      taskdev[minor] = NULL;
 +}
 +
 +static int taskdev_attach_task(struct taskdev *dev, struct dsptask *task)
 +{
 +      u16 ttyp = task->ttyp;
 +      int ret;
 +
 +      dev->fops.read =
 +              sndtyp_acv(ttyp) ?
 +              sndtyp_wd(ttyp) ? dsp_task_read_wd_acv:
 +              /* sndtyp_bk */   dsp_task_read_bk_acv:
 +              /* sndtyp_psv */
 +              sndtyp_wd(ttyp) ? dsp_task_read_wd_psv:
 +              /* sndtyp_bk */   dsp_task_read_bk_psv;
 +      if (sndtyp_wd(ttyp)) {
 +              /* word */
 +              size_t fifosz = sndtyp_psv(ttyp) ? 2:32; /* passive:active */
 +
 +              dev->rcvdt.fifo = kfifo_alloc(fifosz, GFP_KERNEL,
 +                                            &dev->read_lock);
 +              if (IS_ERR(dev->rcvdt.fifo)) {
 +                      printk(KERN_ERR
 +                             "omapdsp: unable to allocate receive buffer. "
 +                             "(%d bytes for %s)\n", fifosz, dev->name);
 +                      return -ENOMEM;
 +              }
 +      } else {
 +              /* block */
 +              INIT_IPBLINK(&dev->rcvdt.bk.link);
 +              dev->rcvdt.bk.rp = 0;
 +      }
 +
 +      dev->fops.write =
 +              rcvtyp_wd(ttyp) ? dsp_task_write_wd:
 +              /* rcvbyp_bk */   dsp_task_write_bk;
 +      dev->wsz = rcvtyp_acv(ttyp) ? 0 :               /* active */
 +              rcvtyp_wd(ttyp)  ? 2 :          /* passive word */
 +              ipbcfg.lsz*2;   /* passive block */
 +
 +      if (task->map_length)
 +              dev->fops.mmap = dsp_task_mmap;
 +
 +      ret = device_create_file(&dev->dev, &dev_attr_taskname);
 +      if (unlikely(ret))
 +              goto fail_create_taskname;
 +      ret = device_create_file(&dev->dev, &dev_attr_ttyp);
 +      if (unlikely(ret))
 +              goto fail_create_ttyp;
 +      ret = device_create_file(&dev->dev, &dev_attr_wsz);
 +      if (unlikely(ret))
 +              goto fail_create_wsz;
 +      if (task->map_length) {
 +              ret = device_create_file(&dev->dev, &dev_attr_mmap);
 +              if (unlikely(ret))
 +                      goto fail_create_mmap;
 +      }
 +      if (sndtyp_wd(ttyp)) {
 +              ret = device_create_file(&dev->dev, &dev_attr_fifosz);
 +              if (unlikely(ret))
 +                      goto fail_create_fifosz;
 +              ret = device_create_file(&dev->dev, &dev_attr_fifocnt);
 +              if (unlikely(ret))
 +                      goto fail_create_fifocnt;
 +      } else {
 +              ret = device_create_file(&dev->dev, &dev_attr_ipblink);
 +              if (unlikely(ret))
 +                      goto fail_create_ipblink;
 +      }
 +
 +      dev->task = task;
 +      task->dev = dev;
 +
 +      return 0;
 +
 + fail_create_fifocnt:
 +      device_remove_file(&dev->dev, &dev_attr_fifosz);
 + fail_create_ipblink:
 + fail_create_fifosz:
 +      if (task->map_length)
 +              device_remove_file(&dev->dev, &dev_attr_mmap);
 + fail_create_mmap:
 +      device_remove_file(&dev->dev, &dev_attr_wsz);
 + fail_create_wsz:
 +      device_remove_file(&dev->dev, &dev_attr_ttyp);
 + fail_create_ttyp:
 +      device_remove_file(&dev->dev, &dev_attr_taskname);
 + fail_create_taskname:
 +      if (task->map_length)
 +              dev->fops.mmap = NULL;
 +
 +      dev->fops.write = NULL;
 +      dev->wsz = 0;
 +
 +      dev->fops.read = NULL;
 +      taskdev_flush_buf(dev);
 +
 +      if (sndtyp_wd(ttyp))
 +              kfifo_free(dev->rcvdt.fifo);
 +
 +      dev->task = NULL;
 +
 +      return ret;
 +}
 +
 +static void taskdev_detach_task(struct taskdev *dev)
 +{
 +      u16 ttyp = dev->task->ttyp;
 +
 +      device_remove_file(&dev->dev, &dev_attr_taskname);
 +      device_remove_file(&dev->dev, &dev_attr_ttyp);
 +      if (sndtyp_wd(ttyp)) {
 +              device_remove_file(&dev->dev, &dev_attr_fifosz);
 +              device_remove_file(&dev->dev, &dev_attr_fifocnt);
 +      } else
 +              device_remove_file(&dev->dev, &dev_attr_ipblink);
 +      device_remove_file(&dev->dev, &dev_attr_wsz);
 +      if (dev->task->map_length) {
 +              device_remove_file(&dev->dev, &dev_attr_mmap);
 +              dev->fops.mmap = NULL;
 +      }
 +
 +      dev->fops.read = NULL;
 +      taskdev_flush_buf(dev);
 +      if (sndtyp_wd(ttyp))
 +              kfifo_free(dev->rcvdt.fifo);
 +
 +      dev->fops.write = NULL;
 +      dev->wsz = 0;
 +
 +      pr_info("omapdsp: taskdev %s disabled.\n", dev->name);
 +      dev->task = NULL;
 +}
 +
 +/*
 + * tadd / tdel / tkill
 + */
 +static int dsp_tadd(struct taskdev *dev, dsp_long_t adr)
 +{
 +      struct dsptask *task;
 +      struct mb_exarg arg;
 +      u8 tid, tid_response;
 +      u16 argv[2];
 +      int ret = 0;
 +
 +      if (!devstate_write_lock_and_test(dev, TASKDEV_ST_ADDREQ)) {
 +              printk(KERN_ERR
 +                     "omapdsp: taskdev %s is not requesting for tadd. "
 +                     "(state is %s)\n", dev->name, devstate_name(dev->state));
 +              return -EINVAL;
 +      }
 +      set_taskdev_state(dev, TASKDEV_ST_ADDING);
 +      devstate_write_unlock(dev);
 +
 +      if (adr == TADD_ABORTADR) {
 +              /* aborting tadd intentionally */
 +              pr_info("omapdsp: tadd address is ABORTADR.\n");
 +              goto fail_out;
 +      }
 +      if (adr >= DSPSPACE_SIZE) {
 +              printk(KERN_ERR
 +                     "omapdsp: illegal address 0x%08x for tadd\n", adr);
 +              ret = -EINVAL;
 +              goto fail_out;
 +      }
 +
 +      adr >>= 1;      /* word address */
 +      argv[0] = adr >> 16;    /* addrh */
 +      argv[1] = adr & 0xffff; /* addrl */
 +
 +      if (mutex_lock_interruptible(&cfg_lock)) {
 +              ret = -EINTR;
 +              goto fail_out;
 +      }
 +      cfg_tid = TID_ANON;
 +      cfg_cmd = MBOX_CMD_DSP_TADD;
 +      arg.tid  = TID_ANON;
 +      arg.argc = 2;
 +      arg.argv = argv;
 +
 +      if (dsp_mem_sync_inc() < 0) {
 +              printk(KERN_ERR "omapdsp: memory sync failed!\n");
 +              ret = -EBUSY;
 +              goto fail_out;
 +      }
 +      mbcompose_send_and_wait_exarg(TADD, 0, 0, &arg, &cfg_wait_q);
 +
 +      tid = cfg_tid;
 +      cfg_tid = TID_ANON;
 +      cfg_cmd = 0;
 +      mutex_unlock(&cfg_lock);
 +
 +      if (tid == TID_ANON) {
 +              printk(KERN_ERR "omapdsp: tadd failed!\n");
 +              ret = -EINVAL;
 +              goto fail_out;
 +      }
 +      if ((tid < n_task) || dsptask[tid]) {
 +              printk(KERN_ERR "omapdsp: illegal tid (%d)!\n", tid);
 +              ret = -EINVAL;
 +              goto fail_out;
 +      }
 +      if ((task = kzalloc(sizeof(struct dsptask), GFP_KERNEL)) == NULL) {
 +              ret = -ENOMEM;
 +              goto del_out;
 +      }
 +
 +      if ((ret = dsp_task_config(task, tid)) < 0)
 +              goto free_out;
 +
 +      if (strcmp(dev->name, task->name)) {
 +              printk(KERN_ERR
 +                     "omapdsp: task name (%s) doesn't match with "
 +                     "device name (%s).\n", task->name, dev->name);
 +              ret = -EINVAL;
 +              goto free_out;
 +      }
 +
 +      if ((ret = taskdev_attach_task(dev, task)) < 0)
 +              goto free_out;
 +
 +      dsp_task_init(task);
 +      pr_info("omapdsp: taskdev %s enabled.\n", dev->name);
 +      set_taskdev_state(dev, TASKDEV_ST_ATTACHED);
 +      wake_up_interruptible_all(&dev->state_wait_q);
 +      return 0;
 +
 +free_out:
 +      kfree(task);
 +
 +del_out:
 +      printk(KERN_ERR "omapdsp: deleting the task...\n");
 +
 +      set_taskdev_state(dev, TASKDEV_ST_DELING);
 +
 +      if (mutex_lock_interruptible(&cfg_lock)) {
 +              printk(KERN_ERR "omapdsp: aborting tdel process. "
 +                              "DSP side could be corrupted.\n");
 +              goto fail_out;
 +      }
 +      cfg_tid = TID_ANON;
 +      cfg_cmd = MBOX_CMD_DSP_TDEL;
 +      mbcompose_send_and_wait(TDEL, tid, TDEL_KILL, &cfg_wait_q);
 +      tid_response = cfg_tid;
 +      cfg_tid = TID_ANON;
 +      cfg_cmd = 0;
 +      mutex_unlock(&cfg_lock);
 +
 +      if (tid_response != tid)
 +              printk(KERN_ERR "omapdsp: tdel failed. "
 +                              "DSP side could be corrupted.\n");
 +
 +fail_out:
 +      set_taskdev_state(dev, TASKDEV_ST_ADDFAIL);
 +      wake_up_interruptible_all(&dev->state_wait_q);
 +      return ret;
 +}
 +
 +int dsp_tadd_minor(unsigned char minor, dsp_long_t adr)
 +{
 +      struct taskdev *dev;
 +      int status;
 +      int ret;
 +
 +      if (mutex_lock_interruptible(&devmgr_lock))
 +              return -EINTR;
 +
 +      if ((minor >= TASKDEV_MAX) || ((dev = taskdev[minor]) == NULL)) {
 +              printk(KERN_ERR
 +                     "omapdsp: no task device with minor %d\n", minor);
 +              ret = -EINVAL;
 +              goto out;
 +      }
 +      ret = minor;
 +      if ((status = dsp_tadd(dev, adr)) < 0)
 +              ret = status;
 +
 +out:
 +      mutex_unlock(&devmgr_lock);
 +      return ret;
 +}
 +
 +static int dsp_tdel(struct taskdev *dev)
 +{
 +      if (!devstate_write_lock_and_test(dev, TASKDEV_ST_DELREQ)) {
 +              printk(KERN_ERR
 +                     "omapdsp: taskdev %s is not requesting for tdel. "
 +                     "(state is %s)\n", dev->name, devstate_name(dev->state));
 +              return -EINVAL;
 +      }
 +      set_taskdev_state(dev, TASKDEV_ST_DELING);
 +      devstate_write_unlock(dev);
 +
 +      return dsp_tdel_bh(dev, TDEL_SAFE);
 +}
 +
 +int dsp_tdel_minor(unsigned char minor)
 +{
 +      struct taskdev *dev;
 +      int status;
 +      int ret;
 +
 +      if (mutex_lock_interruptible(&devmgr_lock))
 +              return -EINTR;
 +
 +      if ((minor >= TASKDEV_MAX) || ((dev = taskdev[minor]) == NULL)) {
 +              printk(KERN_ERR
 +                     "omapdsp: no task device with minor %d\n", minor);
 +              ret = -EINVAL;
 +              goto out;
 +      }
 +
 +      ret = minor;
 +      if ((status = dsp_tdel(dev)) < 0)
 +              ret = status;
 +
 +out:
 +      mutex_unlock(&devmgr_lock);
 +      return ret;
 +}
 +
 +static int dsp_tkill(struct taskdev *dev)
 +{
 +      while (!down_write_trylock(&dev->state_sem)) {
 +              if (!devstate_read_lock_and_test(dev, (TASKDEV_ST_ATTACHED |
 +                                                     TASKDEV_ST_FREEZED))) {
 +                      printk(KERN_ERR
 +                             "omapdsp: task has not been attached for "
 +                             "taskdev %s\n", dev->name);
 +                      return -EINVAL;
 +              }
 +              /* ATTACHED -> FREEZED can be changed under read semaphore. */
 +              set_taskdev_state(dev, TASKDEV_ST_FREEZED);
 +              wake_up_interruptible_all(&dev->read_wait_q);
 +              wake_up_interruptible_all(&dev->write_wait_q);
 +              wake_up_interruptible_all(&dev->tctl_wait_q);
 +              devstate_read_unlock(dev);
 +              schedule();
 +      }
 +
 +      if (!(dev->state & (TASKDEV_ST_ATTACHED |
 +                          TASKDEV_ST_FREEZED))) {
 +              printk(KERN_ERR
 +                     "omapdsp: task has not been attached for taskdev %s\n",
 +                     dev->name);
 +              devstate_write_unlock(dev);
 +              return -EINVAL;
 +      }
 +      if (!is_dynamic_task(dev->task->tid)) {
 +              printk(KERN_ERR "omapdsp: task %s is not a dynamic task.\n",
 +                     dev->name);
 +              devstate_write_unlock(dev);
 +              return -EINVAL;
 +      }
 +      set_taskdev_state(dev, TASKDEV_ST_KILLING);
 +      devstate_write_unlock(dev);
 +
 +      return dsp_tdel_bh(dev, TDEL_KILL);
 +}
 +
 +int dsp_tkill_minor(unsigned char minor)
 +{
 +      struct taskdev *dev;
 +      int status;
 +      int ret;
 +
 +      if (mutex_lock_interruptible(&devmgr_lock))
 +              return -EINTR;
 +
 +      if ((minor >= TASKDEV_MAX) || ((dev = taskdev[minor]) == NULL)) {
 +              printk(KERN_ERR
 +                     "omapdsp: no task device with minor %d\n", minor);
 +              ret = -EINVAL;
 +              goto out;
 +      }
 +
 +      ret = minor;
 +      if ((status = dsp_tkill(dev)) < 0)
 +              ret = status;
 +
 +out:
 +      mutex_unlock(&devmgr_lock);
 +      return ret;
 +}
 +
 +static int dsp_tdel_bh(struct taskdev *dev, u16 type)
 +{
 +      struct dsptask *task;
 +      u8 tid, tid_response;
 +      int ret = 0;
 +
 +      task = dev->task;
 +      tid = task->tid;
 +      if (mutex_lock_interruptible(&cfg_lock)) {
 +              if (type == TDEL_SAFE) {
 +                      set_taskdev_state(dev, TASKDEV_ST_DELREQ);
 +                      return -EINTR;
 +              } else {
 +                      tid_response = TID_ANON;
 +                      ret = -EINTR;
 +                      goto detach_out;
 +              }
 +      }
 +      cfg_tid = TID_ANON;
 +      cfg_cmd = MBOX_CMD_DSP_TDEL;
 +      mbcompose_send_and_wait(TDEL, tid, type, &cfg_wait_q);
 +      tid_response = cfg_tid;
 +      cfg_tid = TID_ANON;
 +      cfg_cmd = 0;
 +      mutex_unlock(&cfg_lock);
 +
 +detach_out:
 +      taskdev_detach_task(dev);
 +      dsp_task_unconfig(task);
 +      kfree(task);
 +
 +      if (tid_response != tid) {
 +              printk(KERN_ERR "omapdsp: %s failed!\n",
 +                     (type == TDEL_SAFE) ? "tdel" : "tkill");
 +              ret = -EINVAL;
 +      }
 +      down_write(&dev->state_sem);
 +      set_taskdev_state(dev, (dev->usecount > 0) ? TASKDEV_ST_GARBAGE :
 +                                         TASKDEV_ST_NOTASK);
 +      wake_up_interruptible_all(&dev->state_wait_q);
 +      up_write(&dev->state_sem);
 +
 +      return ret;
 +}
 +
 +/*
 + * state inquiry
 + */
 +long taskdev_state_stale(unsigned char minor)
 +{
 +      if (taskdev[minor]) {
 +              long state = taskdev[minor]->state;
 +              taskdev[minor]->state |= TASKDEV_ST_STALE;
 +              return state;
 +      } else
 +              return TASKDEV_ST_NOTASK;
 +}
 +
 +/*
 + * functions called from mailbox interrupt routine
 + */
 +void mbox_wdsnd(struct mbcmd *mb)
 +{
 +      unsigned int n;
 +      u8 tid = mb->cmd_l;
 +      u16 data = mb->data;
 +      struct dsptask *task = dsptask[tid];
 +
 +      if ((tid >= TASKDEV_MAX) || (task == NULL)) {
 +              printk(KERN_ERR "mbox: WDSND with illegal tid! %d\n", tid);
 +              return;
 +      }
 +      if (sndtyp_bk(task->ttyp)) {
 +              printk(KERN_ERR
 +                     "mbox: WDSND from block sending task! (task%d)\n", tid);
 +              return;
 +      }
 +      if (sndtyp_psv(task->ttyp) &&
 +          !waitqueue_active(&task->dev->read_wait_q)) {
 +              printk(KERN_WARNING
 +                     "mbox: WDSND from passive sending task (task%d) "
 +                     "without request!\n", tid);
 +              return;
 +      }
 +
 +      n = kfifo_put(task->dev->rcvdt.fifo, (unsigned char *)&data,
 +                    sizeof(data));
 +      if (n != sizeof(data))
 +              printk(KERN_WARNING "Receive FIFO(%d) is full\n", tid);
 +
 +      wake_up_interruptible(&task->dev->read_wait_q);
 +}
 +
 +void mbox_wdreq(struct mbcmd *mb)
 +{
 +      u8 tid = mb->cmd_l;
 +      struct dsptask *task = dsptask[tid];
 +      struct taskdev *dev;
 +
 +      if ((tid >= TASKDEV_MAX) || (task == NULL)) {
 +              printk(KERN_ERR "mbox: WDREQ with illegal tid! %d\n", tid);
 +              return;
 +      }
 +      if (rcvtyp_psv(task->ttyp)) {
 +              printk(KERN_ERR
 +                     "mbox: WDREQ from passive receiving task! (task%d)\n",
 +                     tid);
 +              return;
 +      }
 +
 +      dev = task->dev;
 +      spin_lock(&dev->wsz_lock);
 +      dev->wsz = 2;
 +      spin_unlock(&dev->wsz_lock);
 +      wake_up_interruptible(&dev->write_wait_q);
 +}
 +
 +void mbox_bksnd(struct mbcmd *mb)
 +{
 +      u8 tid = mb->cmd_l;
 +      u16 bid = mb->data;
 +      struct dsptask *task = dsptask[tid];
 +      struct ipbuf_head *ipb_h;
 +      u16 cnt;
 +
 +      if (bid >= ipbcfg.ln) {
 +              printk(KERN_ERR "mbox: BKSND with illegal bid! %d\n", bid);
 +              return;
 +      }
 +      ipb_h = bid_to_ipbuf(bid);
 +      ipb_bsycnt_dec(&ipbcfg);
 +      if ((tid >= TASKDEV_MAX) || (task == NULL)) {
 +              printk(KERN_ERR "mbox: BKSND with illegal tid! %d\n", tid);
 +              goto unuse_ipbuf_out;
 +      }
 +      if (sndtyp_wd(task->ttyp)) {
 +              printk(KERN_ERR
 +                     "mbox: BKSND from word sending task! (task%d)\n", tid);
 +              goto unuse_ipbuf_out;
 +      }
 +      if (sndtyp_pvt(task->ttyp)) {
 +              printk(KERN_ERR
 +                     "mbox: BKSND from private sending task! (task%d)\n", tid);
 +              goto unuse_ipbuf_out;
 +      }
 +      if (sync_with_dsp(&ipb_h->p->sd, tid, 10) < 0) {
 +              printk(KERN_ERR "mbox: BKSND - IPBUF sync failed!\n");
 +              return;
 +      }
 +
 +      /* should be done in DSP, but just in case. */
 +      ipb_h->p->next = BID_NULL;
 +
 +      cnt = ipb_h->p->c;
 +      if (cnt > ipbcfg.lsz) {
 +              printk(KERN_ERR "mbox: BKSND cnt(%d) > ipbuf line size(%d)!\n",
 +                     cnt, ipbcfg.lsz);
 +              goto unuse_ipbuf_out;
 +      }
 +
 +      if (cnt == 0) {
 +              /* 0-byte send from DSP */
 +              unuse_ipbuf_nowait(ipb_h);
 +              goto done;
 +      }
 +      ipblink_add_tail(&task->dev->rcvdt.bk.link, bid);
 +      /* we keep coming bid and return alternative line to DSP. */
 +      balance_ipbuf();
 +
 +done:
 +      wake_up_interruptible(&task->dev->read_wait_q);
 +      return;
 +
 +unuse_ipbuf_out:
 +      unuse_ipbuf_nowait(ipb_h);
 +      return;
 +}
 +
 +void mbox_bkreq(struct mbcmd *mb)
 +{
 +      u8 tid = mb->cmd_l;
 +      u16 cnt = mb->data;
 +      struct dsptask *task = dsptask[tid];
 +      struct taskdev *dev;
 +
 +      if ((tid >= TASKDEV_MAX) || (task == NULL)) {
 +              printk(KERN_ERR "mbox: BKREQ with illegal tid! %d\n", tid);
 +              return;
 +      }
 +      if (rcvtyp_wd(task->ttyp)) {
 +              printk(KERN_ERR
 +                     "mbox: BKREQ from word receiving task! (task%d)\n", tid);
 +              return;
 +      }
 +      if (rcvtyp_pvt(task->ttyp)) {
 +              printk(KERN_ERR
 +                     "mbox: BKREQ from private receiving task! (task%d)\n",
 +                     tid);
 +              return;
 +      }
 +      if (rcvtyp_psv(task->ttyp)) {
 +              printk(KERN_ERR
 +                     "mbox: BKREQ from passive receiving task! (task%d)\n",
 +                     tid);
 +              return;
 +      }
 +
 +      dev = task->dev;
 +      spin_lock(&dev->wsz_lock);
 +      dev->wsz = cnt*2;
 +      spin_unlock(&dev->wsz_lock);
 +      wake_up_interruptible(&dev->write_wait_q);
 +}
 +
 +void mbox_bkyld(struct mbcmd *mb)
 +{
 +      u16 bid = mb->data;
 +      struct ipbuf_head *ipb_h;
 +
 +      if (bid >= ipbcfg.ln) {
 +              printk(KERN_ERR "mbox: BKYLD with illegal bid! %d\n", bid);
 +              return;
 +      }
 +      ipb_h = bid_to_ipbuf(bid);
 +
 +      /* should be done in DSP, but just in case. */
 +      ipb_h->p->next = BID_NULL;
 +
 +      /* we don't need to sync with DSP */
 +      ipb_bsycnt_dec(&ipbcfg);
 +      release_ipbuf(ipb_h);
 +}
 +
 +void mbox_bksndp(struct mbcmd *mb)
 +{
 +      u8 tid = mb->cmd_l;
 +      struct dsptask *task = dsptask[tid];
 +      struct ipbuf_p *ipbp;
 +
 +      if ((tid >= TASKDEV_MAX) || (task == NULL)) {
 +              printk(KERN_ERR "mbox: BKSNDP with illegal tid! %d\n", tid);
 +              return;
 +      }
 +      if (sndtyp_wd(task->ttyp)) {
 +              printk(KERN_ERR
 +                     "mbox: BKSNDP from word sending task! (task%d)\n", tid);
 +              return;
 +      }
 +      if (sndtyp_gbl(task->ttyp)) {
 +              printk(KERN_ERR
 +                     "mbox: BKSNDP from non-private sending task! (task%d)\n",
 +                     tid);
 +              return;
 +      }
 +
 +      /*
 +       * we should not have delayed block at this point
 +       * because read() routine releases the lock of the buffer and
 +       * until then DSP can't send next data.
 +       */
 +
 +      ipbp = task->ipbuf_pvt_r;
 +      if (sync_with_dsp(&ipbp->s, tid, 10) < 0) {
 +              printk(KERN_ERR "mbox: BKSNDP - IPBUF sync failed!\n");
 +              return;
 +      }
 +      pr_debug("mbox: ipbuf_pvt_r->a = 0x%08lx\n",
 +             MKLONG(ipbp->ah, ipbp->al));
 +      ipblink_add_pvt(&task->dev->rcvdt.bk.link);
 +      wake_up_interruptible(&task->dev->read_wait_q);
 +}
 +
 +void mbox_bkreqp(struct mbcmd *mb)
 +{
 +      u8 tid = mb->cmd_l;
 +      struct dsptask *task = dsptask[tid];
 +      struct taskdev *dev;
 +      struct ipbuf_p *ipbp;
 +
 +      if ((tid >= TASKDEV_MAX) || (task == NULL)) {
 +              printk(KERN_ERR "mbox: BKREQP with illegal tid! %d\n", tid);
 +              return;
 +      }
 +      if (rcvtyp_wd(task->ttyp)) {
 +              printk(KERN_ERR
 +                     "mbox: BKREQP from word receiving task! (task%d)\n", tid);
 +              return;
 +      }
 +      if (rcvtyp_gbl(task->ttyp)) {
 +              printk(KERN_ERR
 +                     "mbox: BKREQP from non-private receiving task! (task%d)\n", tid);
 +              return;
 +      }
 +      if (rcvtyp_psv(task->ttyp)) {
 +              printk(KERN_ERR
 +                     "mbox: BKREQP from passive receiving task! (task%d)\n", tid);
 +              return;
 +      }
 +
 +      ipbp = task->ipbuf_pvt_w;
 +      if (sync_with_dsp(&ipbp->s, TID_FREE, 10) < 0) {
 +              printk(KERN_ERR "mbox: BKREQP - IPBUF sync failed!\n");
 +              return;
 +      }
 +      pr_debug("mbox: ipbuf_pvt_w->a = 0x%08lx\n",
 +             MKLONG(ipbp->ah, ipbp->al));
 +      dev = task->dev;
 +      spin_lock(&dev->wsz_lock);
 +      dev->wsz = ipbp->c*2;
 +      spin_unlock(&dev->wsz_lock);
 +      wake_up_interruptible(&dev->write_wait_q);
 +}
 +
 +void mbox_tctl(struct mbcmd *mb)
 +{
 +      u8 tid = mb->cmd_l;
 +      struct dsptask *task = dsptask[tid];
 +
 +      if ((tid >= TASKDEV_MAX) || (task == NULL)) {
 +              printk(KERN_ERR "mbox: TCTL with illegal tid! %d\n", tid);
 +              return;
 +      }
 +
 +      if (!waitqueue_active(&task->dev->tctl_wait_q)) {
 +              printk(KERN_WARNING "mbox: unexpected TCTL from DSP!\n");
 +              return;
 +      }
 +
 +      task->dev->tctl_stat = mb->data;
 +      wake_up_interruptible(&task->dev->tctl_wait_q);
 +}
 +
 +void mbox_tcfg(struct mbcmd *mb)
 +{
 +      u8 tid = mb->cmd_l;
 +      struct dsptask *task = dsptask[tid];
 +      u16 *tnm;
 +      volatile u16 *buf;
 +      int i;
 +
 +      if ((tid >= TASKDEV_MAX) || (task == NULL)) {
 +              printk(KERN_ERR "mbox: TCFG with illegal tid! %d\n", tid);
 +              return;
 +      }
 +      if ((task->state != TASK_ST_CFGREQ) || (cfg_cmd != MBOX_CMD_DSP_TCFG)) {
 +              printk(KERN_WARNING "mbox: unexpected TCFG from DSP!\n");
 +              return;
 +      }
 +
 +      if (dsp_mem_enable(ipbuf_sys_da) < 0) {
 +              printk(KERN_ERR "mbox: TCFG - ipbuf_sys_da read failed!\n");
 +              dsp_mem_disable(ipbuf_sys_da);
 +              goto out;
 +      }
 +      if (sync_with_dsp(&ipbuf_sys_da->s, tid, 10) < 0) {
 +              printk(KERN_ERR "mbox: TCFG - IPBUF sync failed!\n");
 +              dsp_mem_disable(ipbuf_sys_da);
 +              goto out;
 +      }
 +
 +      /*
 +       * read configuration data on system IPBUF
 +       */
 +      buf = ipbuf_sys_da->d;
 +      task->ttyp        = buf[0];
 +      task->ipbuf_pvt_r = MKVIRT(buf[1], buf[2]);
 +      task->ipbuf_pvt_w = MKVIRT(buf[3], buf[4]);
 +      task->map_base    = MKVIRT(buf[5], buf[6]);
 +      task->map_length  = MKLONG(buf[7], buf[8]) << 1;        /* word -> byte */
 +      tnm               = MKVIRT(buf[9], buf[10]);
 +      release_ipbuf_pvt(ipbuf_sys_da);
 +      dsp_mem_disable(ipbuf_sys_da);
 +
 +      /*
 +       * copy task name string
 +       */
 +      if (dsp_address_validate(tnm, TNM_LEN, "task name buffer") < 0) {
 +              task->name[0] = '\0';
 +              goto out;
 +      }
 +
 +      for (i = 0; i < TNM_LEN-1; i++) {
 +              /* avoiding byte access */
 +              u16 tmp = tnm[i];
 +              task->name[i] = tmp & 0x00ff;
 +              if (!tmp)
 +                      break;
 +      }
 +      task->name[TNM_LEN-1] = '\0';
 +
 +      task->state = TASK_ST_READY;
 +out:
 +      wake_up_interruptible(&cfg_wait_q);
 +}
 +
 +void mbox_tadd(struct mbcmd *mb)
 +{
 +      u8 tid = mb->cmd_l;
 +
 +      if ((!waitqueue_active(&cfg_wait_q)) || (cfg_cmd != MBOX_CMD_DSP_TADD)) {
 +              printk(KERN_WARNING "mbox: unexpected TADD from DSP!\n");
 +              return;
 +      }
 +      cfg_tid = tid;
 +      wake_up_interruptible(&cfg_wait_q);
 +}
 +
 +void mbox_tdel(struct mbcmd *mb)
 +{
 +      u8 tid = mb->cmd_l;
 +
 +      if ((!waitqueue_active(&cfg_wait_q)) || (cfg_cmd != MBOX_CMD_DSP_TDEL)) {
 +              printk(KERN_WARNING "mbox: unexpected TDEL from DSP!\n");
 +              return;
 +      }
 +      cfg_tid = tid;
 +      wake_up_interruptible(&cfg_wait_q);
 +}
 +
 +void mbox_err_fatal(u8 tid)
 +{
 +      struct dsptask *task = dsptask[tid];
 +      struct taskdev *dev;
 +
 +      if ((tid >= TASKDEV_MAX) || (task == NULL)) {
 +              printk(KERN_ERR "mbox: FATAL ERR with illegal tid! %d\n", tid);
 +              return;
 +      }
 +
 +      /* wake up waiting processes */
 +      dev = task->dev;
 +      wake_up_interruptible_all(&dev->read_wait_q);
 +      wake_up_interruptible_all(&dev->write_wait_q);
 +      wake_up_interruptible_all(&dev->tctl_wait_q);
 +}
 +
 +static u16 *dbg_buf;
 +static u16 dbg_buf_sz, dbg_line_sz;
 +static int dbg_rp;
 +
 +int dsp_dbg_config(u16 *buf, u16 sz, u16 lsz)
 +{
 +#ifdef OLD_BINARY_SUPPORT
 +      if ((mbox_revision == MBREV_3_0) || (mbox_revision == MBREV_3_2)) {
 +              dbg_buf = NULL;
 +              dbg_buf_sz = 0;
 +              dbg_line_sz = 0;
 +              dbg_rp = 0;
 +              return 0;
 +      }
 +#endif
 +
 +      if (dsp_address_validate(buf, sz, "debug buffer") < 0)
 +              return -1;
 +
 +      if (lsz > sz) {
 +              printk(KERN_ERR
 +                     "omapdsp: dbg_buf lsz (%d) is greater than its "
 +                     "buffer size (%d)\n", lsz, sz);
 +              return -1;
 +      }
 +
 +      dbg_buf = buf;
 +      dbg_buf_sz = sz;
 +      dbg_line_sz = lsz;
 +      dbg_rp = 0;
 +
 +      return 0;
 +}
 +
 +void dsp_dbg_stop(void)
 +{
 +      dbg_buf = NULL;
 +}
 +
 +#ifdef OLD_BINARY_SUPPORT
 +static void mbox_dbg_old(struct mbcmd *mb);
 +#endif
 +
 +void mbox_dbg(struct mbcmd *mb)
 +{
 +      u8 tid = mb->cmd_l;
 +      int cnt = mb->data;
 +      char s[80], *s_end = &s[79], *p;
 +      u16 *src;
 +      int i;
 +
 +#ifdef OLD_BINARY_SUPPORT
 +      if ((mbox_revision == MBREV_3_0) || (mbox_revision == MBREV_3_2)) {
 +              mbox_dbg_old(mb);
 +              return;
 +      }
 +#endif
 +
 +      if (((tid >= TASKDEV_MAX) || (dsptask[tid] == NULL)) &&
 +          (tid != TID_ANON)) {
 +              printk(KERN_ERR "mbox: DBG with illegal tid! %d\n", tid);
 +              return;
 +      }
 +      if (dbg_buf == NULL) {
 +              printk(KERN_ERR "mbox: DBG command received, but "
 +                     "dbg_buf has not been configured yet.\n");
 +              return;
 +      }
 +
 +      if (dsp_mem_enable(dbg_buf) < 0)
 +              return;
 +
 +      src = &dbg_buf[dbg_rp];
 +      p = s;
 +      for (i = 0; i < cnt; i++) {
 +              u16 tmp;
 +              /*
 +               * Be carefull that dbg_buf should not be read with
 +               * 1-byte access since it might be placed in DARAM/SARAM
 +               * and it can cause unexpected byteswap.
 +               * For example,
 +               *   *(p++) = *(src++) & 0xff;
 +               * causes 1-byte access!
 +               */
 +              tmp = *src++;
 +              *(p++) = tmp & 0xff;
 +              if (*(p-1) == '\n') {
 +                      *p = '\0';
 +                      pr_info("%s", s);
 +                      p = s;
 +                      continue;
 +              }
 +              if (p == s_end) {
 +                      *p = '\0';
 +                      pr_info("%s\n", s);
 +                      p = s;
 +                      continue;
 +              }
 +      }
 +      if (p > s) {
 +              *p = '\0';
 +              pr_info("%s\n", s);
 +      }
 +      if ((dbg_rp += cnt + 1) > dbg_buf_sz - dbg_line_sz)
 +              dbg_rp = 0;
 +
 +      dsp_mem_disable(dbg_buf);
 +}
 +
 +#ifdef OLD_BINARY_SUPPORT
 +static void mbox_dbg_old(struct mbcmd *mb)
 +{
 +      u8 tid = mb->cmd_l;
 +      char s[80], *s_end = &s[79], *p;
 +      u16 *src;
 +      volatile u16 *buf;
 +      int cnt;
 +      int i;
 +
 +      if (((tid >= TASKDEV_MAX) || (dsptask[tid] == NULL)) &&
 +          (tid != TID_ANON)) {
 +              printk(KERN_ERR "mbox: DBG with illegal tid! %d\n", tid);
 +              return;
 +      }
 +      if (dsp_mem_enable(ipbuf_sys_da) < 0) {
 +              printk(KERN_ERR "mbox: DBG - ipbuf_sys_da read failed!\n");
 +              return;
 +      }
 +      if (sync_with_dsp(&ipbuf_sys_da->s, tid, 10) < 0) {
 +              printk(KERN_ERR "mbox: DBG - IPBUF sync failed!\n");
 +              goto out1;
 +      }
 +      buf = ipbuf_sys_da->d;
 +      cnt = buf[0];
 +      src = MKVIRT(buf[1], buf[2]);
 +      if (dsp_address_validate(src, cnt, "dbg buffer") < 0)
 +              goto out2;
 +
 +      if (dsp_mem_enable(src) < 0)
 +              goto out2;
 +
 +      p = s;
 +      for (i = 0; i < cnt; i++) {
 +              u16 tmp;
 +              /*
 +               * Be carefull that ipbuf should not be read with
 +               * 1-byte access since it might be placed in DARAM/SARAM
 +               * and it can cause unexpected byteswap.
 +               * For example,
 +               *   *(p++) = *(src++) & 0xff;
 +               * causes 1-byte access!
 +               */
 +              tmp = *src++;
 +              *(p++) = tmp & 0xff;
 +              if (*(p-1) == '\n') {
 +                      *p = '\0';
 +                      pr_info("%s", s);
 +                      p = s;
 +                      continue;
 +              }
 +              if (p == s_end) {
 +                      *p = '\0';
 +                      pr_info("%s\n", s);
 +                      p = s;
 +                      continue;
 +              }
 +      }
 +      if (p > s) {
 +              *p = '\0';
 +              pr_info("%s\n", s);
 +      }
 +
 +      dsp_mem_disable(src);
 +out2:
 +      release_ipbuf_pvt(ipbuf_sys_da);
 +out1:
 +      dsp_mem_disable(ipbuf_sys_da);
 +}
 +#endif /* OLD_BINARY_SUPPORT */
 +
 +/*
 + * sysfs files: for each device
 + */
 +
 +/* devname */
 +static ssize_t devname_show(struct device *d, struct device_attribute *attr,
 +                          char *buf)
 +{
 +      return sprintf(buf, "%s\n", to_taskdev(d)->name);
 +}
 +
 +/* devstate */
 +static ssize_t devstate_show(struct device *d, struct device_attribute *attr,
 +                           char *buf)
 +{
 +      return sprintf(buf, "%s\n", devstate_name(to_taskdev(d)->state));
 +}
 +
 +/* proc_list */
 +static ssize_t proc_list_show(struct device *d, struct device_attribute *attr,
 +                            char *buf)
 +{
 +      struct taskdev *dev;
 +      struct proc_list *pl;
 +      int len = 0;
 +
 +      dev = to_taskdev(d);
 +      spin_lock(&dev->proc_list_lock);
 +      list_for_each_entry(pl, &dev->proc_list, list_head) {
 +              /* need to lock tasklist_lock before calling
 +               * find_task_by_pid_type. */
++              if (find_task_by_pid_type_ns(PIDTYPE_PID, pl->pid, &init_pid_ns) != NULL)
 +                      len += sprintf(buf + len, "%d\n", pl->pid);
 +              read_unlock(&tasklist_lock);
 +      }
 +      spin_unlock(&dev->proc_list_lock);
 +
 +      return len;
 +}
 +
 +/* taskname */
 +static ssize_t taskname_show(struct device *d, struct device_attribute *attr,
 +                           char *buf)
 +{
 +      struct taskdev *dev = to_taskdev(d);
 +      int len;
 +
 +      if (!devstate_read_lock_and_test(dev, TASKDEV_ST_ATTACHED))
 +              return -ENODEV;
 +
 +      len = sprintf(buf, "%s\n", dev->task->name);
 +
 +      devstate_read_unlock(dev);
 +      return len;
 +}
 +
 +/* ttyp */
 +static ssize_t ttyp_show(struct device *d, struct device_attribute *attr,
 +                       char *buf)
 +{
 +      struct taskdev *dev = to_taskdev(d);
 +      u16 ttyp;
 +      int len = 0;
 +
 +      if (!devstate_read_lock_and_test(dev, TASKDEV_ST_ATTACHED))
 +              return -ENODEV;
 +
 +      ttyp = dev->task->ttyp;
 +      len += sprintf(buf + len, "0x%04x\n", ttyp);
 +      len += sprintf(buf + len, "%s %s send\n",
 +                      (sndtyp_acv(ttyp)) ? "active" :
 +                                           "passive",
 +                      (sndtyp_wd(ttyp))  ? "word" :
 +                      (sndtyp_pvt(ttyp)) ? "private block" :
 +                                           "global block");
 +      len += sprintf(buf + len, "%s %s receive\n",
 +                      (rcvtyp_acv(ttyp)) ? "active" :
 +                                           "passive",
 +                      (rcvtyp_wd(ttyp))  ? "word" :
 +                      (rcvtyp_pvt(ttyp)) ? "private block" :
 +                                           "global block");
 +
 +      devstate_read_unlock(dev);
 +      return len;
 +}
 +
 +/* fifosz */
 +static ssize_t fifosz_show(struct device *d, struct device_attribute *attr,
 +                         char *buf)
 +{
 +      struct kfifo *fifo = to_taskdev(d)->rcvdt.fifo;
 +      return sprintf(buf, "%d\n", fifo->size);
 +}
 +
 +static int fifosz_store(struct device *d, struct device_attribute *attr,
 +                      const char *buf, size_t count)
 +{
 +      struct taskdev *dev = to_taskdev(d);
 +      unsigned long fifosz;
 +      int ret;
 +
 +      fifosz = simple_strtol(buf, NULL, 10);
 +      if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex))
 +              return -ENODEV;
 +      ret = taskdev_set_fifosz(dev, fifosz);
 +      taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
 +
 +      return (ret < 0) ? ret : strlen(buf);
 +}
 +
 +/* fifocnt */
 +static ssize_t fifocnt_show(struct device *d, struct device_attribute *attr,
 +                          char *buf)
 +{
 +      struct kfifo *fifo = to_taskdev(d)->rcvdt.fifo;
 +      return sprintf(buf, "%d\n", fifo->size);
 +}
 +
 +/* ipblink */
 +static inline char *bid_name(u16 bid)
 +{
 +      static char s[6];
 +
 +      switch (bid) {
 +      case BID_NULL:
 +              return "NULL";
 +      case BID_PVT:
 +              return "PRIVATE";
 +      default:
 +              sprintf(s, "%d", bid);
 +              return s;
 +      }
 +}
 +
 +static ssize_t ipblink_show(struct device *d, struct device_attribute *attr,
 +                          char *buf)
 +{
 +      struct rcvdt_bk_struct *rcvdt = &to_taskdev(d)->rcvdt.bk;
 +      int len;
 +
 +      spin_lock(&rcvdt->link.lock);
 +      len = sprintf(buf, "top  %s\ntail %s\n",
 +                    bid_name(rcvdt->link.top), bid_name(rcvdt->link.tail));
 +      spin_unlock(&rcvdt->link.lock);
 +
 +      return len;
 +}
 +
 +/* wsz */
 +static ssize_t wsz_show(struct device *d, struct device_attribute *attr,
 +                      char *buf)
 +{
 +      return sprintf(buf, "%d\n", to_taskdev(d)->wsz);
 +}
 +
 +/* mmap */
 +static ssize_t mmap_show(struct device *d, struct device_attribute *attr,
 +                       char *buf)
 +{
 +      struct dsptask *task = to_taskdev(d)->task;
 +      return sprintf(buf, "0x%p 0x%x\n", task->map_base, task->map_length);
 +}
 +
 +/*
 + * called from ipbuf_show()
 + */
 +int ipbuf_is_held(u8 tid, u16 bid)
 +{
 +      struct dsptask *task = dsptask[tid];
 +      struct ipblink *link;
 +      u16 b;
 +      int ret = 0;
 +
 +      if (task == NULL)
 +              return 0;
 +
 +      link = &task->dev->rcvdt.bk.link;
 +      spin_lock(&link->lock);
 +      ipblink_for_each(b, link) {
 +              if (b == bid) { /* found */
 +                      ret = 1;
 +                      break;
 +              }
 +      }
 +      spin_unlock(&link->lock);
 +
 +      return ret;
 +}
 +
 +int __init dsp_taskmod_init(void)
 +{
 +      int retval;
 +
 +      memset(taskdev, 0, sizeof(void *) * TASKDEV_MAX);
 +      memset(dsptask, 0, sizeof(void *) * TASKDEV_MAX);
 +
 +      retval = register_chrdev(OMAP_DSP_TASK_MAJOR, "dsptask",
 +                               &dsp_task_fops);
 +      if (retval < 0) {
 +              printk(KERN_ERR
 +                     "omapdsp: failed to register task device: %d\n", retval);
 +              return retval;
 +      }
 +
 +      retval = bus_register(&dsptask_bus);
 +      if (retval) {
 +              printk(KERN_ERR
 +                     "omapdsp: failed to register DSP task bus: %d\n",
 +                     retval);
 +              unregister_chrdev(OMAP_DSP_TASK_MAJOR, "dsptask");
 +              return -EINVAL;
 +      }
 +      retval = driver_register(&dsptask_driver);
 +      if (retval) {
 +              printk(KERN_ERR
 +                     "omapdsp: failed to register DSP task driver: %d\n",
 +                     retval);
 +              bus_unregister(&dsptask_bus);
 +              unregister_chrdev(OMAP_DSP_TASK_MAJOR, "dsptask");
 +              return -EINVAL;
 +      }
 +      dsp_task_class = class_create(THIS_MODULE, "dsptask");
 +      if (IS_ERR(dsp_task_class)) {
 +              printk(KERN_ERR "omapdsp: failed to create DSP task class\n");
 +              driver_unregister(&dsptask_driver);
 +              bus_unregister(&dsptask_bus);
 +              unregister_chrdev(OMAP_DSP_TASK_MAJOR, "dsptask");
 +              return -EINVAL;
 +      }
 +
 +      return 0;
 +}
 +
 +void dsp_taskmod_exit(void)
 +{
 +      class_destroy(dsp_task_class);
 +      driver_unregister(&dsptask_driver);
 +      bus_unregister(&dsptask_bus);
 +      unregister_chrdev(OMAP_DSP_TASK_MAJOR, "dsptask");
 +}
diff --combined drivers/hwmon/Kconfig
index 7b1f24ff99fbab02432724ed550d42da56e3fff9,c882fd05cf2920d464da928eb165b3e7914044f3..8cecd1f6f40c304a27fcddb7efb986405837c1d5
@@@ -394,13 -394,24 +394,24 @@@ config SENSORS_LM7
        tristate "National Semiconductor LM75 and compatibles"
        depends on I2C
        help
-         If you say yes here you get support for National Semiconductor LM75
-         sensor chips and clones: Dallas Semiconductor DS75 and DS1775 (in
-         9-bit precision mode), and TelCom (now Microchip) TCN75.
-         The DS75 and DS1775 in 10- to 12-bit precision modes will require
-         a force module parameter. The driver will not handle the extra
-         precision anyhow.
+         If you say yes here you get support for one common type of
+         temperature sensor chip, with models including:
+               - Dallas Semiconductor DS75 and DS1775
+               - Maxim MAX6625 and MAX6626
+               - Microchip MCP980x
+               - National Semiconductor LM75
+               - NXP's LM75A
+               - ST Microelectronics STDS75
+               - TelCom (now Microchip) TCN75
+               - Texas Instruments TMP100, TMP101, TMP75, TMP175, TMP275
+         This driver supports driver model based binding through board
+         specific I2C device tables.
+         It also supports the "legacy" style of driver binding.  To use
+         that with some chips which don't replicate LM75 quirks exactly,
+         you may need the "force" module parameter.
  
          This driver can also be built as a module.  If so, the module
          will be called lm75.
@@@ -799,22 -810,6 +810,22 @@@ config SENSORS_APPLESM
          Say Y here if you have an applicable laptop and want to experience
          the awesome power of applesmc.
  
 +config SENSORS_TSC210X
 +      tristate "TI TSC210x battery & temperature sensors"
 +      depends on HWMON && SPI_MASTER
 +      select SPI_TSC210X
 +      help
 +        Say Y if your board has a TSC210x chip and you want to
 +        have its battery state, auxiliary input and/or temperature
 +        sensors exported through hwmon.
 +
 +        This driver can also be built as a module.  In this case
 +        the module will be called tsc210x_sensors.
 +
 +config SENSORS_OMAP34XX
 +      tristate "TI OMAP34xx internal temperature sensor"
 +      depends on ARCH_OMAP3 && HIGH_RES_TIMERS
 +
  config HWMON_DEBUG_CHIP
        bool "Hardware Monitoring Chip debugging messages"
        default n
index 9204f711fd515655a32db1d0569b24bef08f1b00,6ee997b2817c450b3ac2fae2bf32e5ad035ff5d3..eb94378cab7590e9aa78e4c71e4b8baf2251df55
@@@ -4,6 -4,9 +4,9 @@@
  
  menu "I2C Hardware Bus support"
  
+ comment "PC SMBus host controller drivers"
+       depends on PCI
  config I2C_ALI1535
        tristate "ALI 1535"
        depends on PCI
@@@ -73,94 -76,6 +76,6 @@@ config I2C_AMD811
          This driver can also be built as a module.  If so, the module
          will be called i2c-amd8111.
  
- config I2C_AT91
-       tristate "Atmel AT91 I2C Two-Wire interface (TWI)"
-       depends on ARCH_AT91 && EXPERIMENTAL && BROKEN
-       help
-         This supports the use of the I2C interface on Atmel AT91
-         processors.
-         This driver is BROKEN because the controller which it uses
-         will easily trigger RX overrun and TX underrun errors.  Using
-         low I2C clock rates may partially work around those issues
-         on some systems.  Another serious problem is that there is no
-         documented way to issue repeated START conditions, as needed
-         to support combined I2C messages.  Use the i2c-gpio driver
-         unless your system can cope with those limitations.
- config I2C_AU1550
-       tristate "Au1550/Au1200 SMBus interface"
-       depends on SOC_AU1550 || SOC_AU1200
-       help
-         If you say yes to this option, support will be included for the
-         Au1550 and Au1200 SMBus interface.
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-au1550.
- config I2C_BLACKFIN_TWI
-       tristate "Blackfin TWI I2C support"
-       depends on BLACKFIN
-       help
-         This is the TWI I2C device driver for Blackfin BF522, BF525,
-         BF527, BF534, BF536, BF537 and BF54x. For other Blackfin processors,
-         please don't use this driver.
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-bfin-twi.
- config I2C_BLACKFIN_TWI_CLK_KHZ
-       int "Blackfin TWI I2C clock (kHz)"
-       depends on I2C_BLACKFIN_TWI
-       range 10 400
-       default 50
-       help
-         The unit of the TWI clock is kHz.
- config I2C_DAVINCI
-       tristate "DaVinci I2C driver"
-       depends on ARCH_DAVINCI
-       help
-         Support for TI DaVinci I2C controller driver.
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-davinci.
-         Please note that this driver might be needed to bring up other
-         devices such as DaVinci NIC.
-         For details please see http://www.ti.com/davinci
- config I2C_ELEKTOR
-       tristate "Elektor ISA card"
-       depends on ISA && BROKEN_ON_SMP
-       select I2C_ALGOPCF
-       help
-         This supports the PCF8584 ISA bus I2C adapter.  Say Y if you own
-         such an adapter.
-         This support is also available as a module.  If so, the module
-         will be called i2c-elektor.
- config I2C_GPIO
-       tristate "GPIO-based bitbanging I2C"
-       depends on GENERIC_GPIO
-       select I2C_ALGOBIT
-       help
-         This is a very simple bitbanging I2C driver utilizing the
-         arch-neutral GPIO API to control the SCL and SDA lines.
- config I2C_HYDRA
-       tristate "CHRP Apple Hydra Mac I/O I2C interface"
-       depends on PCI && PPC_CHRP && EXPERIMENTAL
-       select I2C_ALGOBIT
-       help
-         This supports the use of the I2C interface in the Apple Hydra Mac
-         I/O chip on some CHRP machines (e.g. the LongTrail).  Say Y if you
-         have such a machine.
-         This support is also available as a module.  If so, the module
-         will be called i2c-hydra.
  config I2C_I801
        tristate "Intel 82801 (ICH)"
        depends on PCI
          This driver can also be built as a module.  If so, the module
          will be called i2c-i801.
  
- config I2C_I810
-       tristate "Intel 810/815 (DEPRECATED)"
-       default n
+ config I2C_ISCH
+       tristate "Intel SCH SMBus 1.0"
        depends on PCI
-       select I2C_ALGOBIT
-       help
-         If you say yes to this option, support will be included for the Intel
-         810/815 family of mainboard I2C interfaces.  Specifically, the
-         following versions of the chipset are supported:
-           i810AA
-           i810AB
-           i810E
-           i815
-           i845G
-         This driver is deprecated in favor of the i810fb and intelfb drivers.
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-i810.
- config I2C_PXA
-       tristate "Intel PXA2XX I2C adapter (EXPERIMENTAL)"
-       depends on EXPERIMENTAL && ARCH_PXA
        help
-         If you have devices in the PXA I2C bus, say yes to this option.
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-pxa.
+         Say Y here if you want to use SMBus controller on the Intel SCH
+         based systems.
  
- config I2C_PXA_SLAVE
-       bool "Intel PXA2XX I2C Slave comms support"
-       depends on I2C_PXA
-       help
-         Support I2C slave mode communications on the PXA I2C bus.  This
-         is necessary for systems where the PXA may be a target on the
-         I2C bus.
+         This driver can also be built as a module. If so, the module
+         will be called i2c-isch.
  
  config I2C_PIIX4
        tristate "Intel PIIX4 and compatible (ATI/Serverworks/Broadcom/SMSC)"
          This driver can also be built as a module.  If so, the module
          will be called i2c-piix4.
  
- config I2C_IBM_IIC
-       tristate "IBM PPC 4xx on-chip I2C interface"
-       depends on 4xx
+ config I2C_NFORCE2
+       tristate "Nvidia nForce2, nForce3 and nForce4"
+       depends on PCI
        help
-         Say Y here if you want to use IIC peripheral found on
-         embedded IBM PPC 4xx based systems.
+         If you say yes to this option, support will be included for the Nvidia
+         nForce2, nForce3 and nForce4 families of mainboard I2C interfaces.
  
          This driver can also be built as a module.  If so, the module
-         will be called i2c-ibm_iic.
+         will be called i2c-nforce2.
  
- config I2C_IOP3XX
-       tristate "Intel IOPx3xx and IXP4xx on-chip I2C interface"
-       depends on ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX || ARCH_IOP13XX
+ config I2C_NFORCE2_S4985
+       tristate "SMBus multiplexing on the Tyan S4985"
+       depends on I2C_NFORCE2 && EXPERIMENTAL
        help
-         Say Y here if you want to use the IIC bus controller on
-         the Intel IOPx3xx I/O Processors or IXP4xx Network Processors.
+         Enabling this option will add specific SMBus support for the Tyan
+         S4985 motherboard.  On this 4-CPU board, the SMBus is multiplexed
+         over 4 different channels, where the various memory module EEPROMs
+         live.  Saying yes here will give you access to these in addition
+         to the trunk.
  
          This driver can also be built as a module.  If so, the module
-         will be called i2c-iop3xx.
+         will be called i2c-nforce2-s4985.
  
- config I2C_IXP2000
-       tristate "IXP2000 GPIO-Based I2C Interface (DEPRECATED)"
-       depends on ARCH_IXP2000
+ config I2C_SIS5595
+       tristate "SiS 5595"
+       depends on PCI
+       help
+         If you say yes to this option, support will be included for the
+         SiS5595 SMBus (a subset of I2C) interface.
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-sis5595.
+ config I2C_SIS630
+       tristate "SiS 630/730"
+       depends on PCI
+       help
+         If you say yes to this option, support will be included for the
+         SiS630 and SiS730 SMBus (a subset of I2C) interface.
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-sis630.
+ config I2C_SIS96X
+       tristate "SiS 96x"
+       depends on PCI
+       help
+         If you say yes to this option, support will be included for the SiS
+         96x SMBus (a subset of I2C) interfaces.  Specifically, the following
+         chipsets are supported:
+           645/961
+           645DX/961
+           645DX/962
+           648/961
+           650/961
+           735
+           745
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-sis96x.
+ config I2C_VIA
+       tristate "VIA VT82C586B"
+       depends on PCI && EXPERIMENTAL
        select I2C_ALGOBIT
        help
-         Say Y here if you have an Intel IXP2000 (2400, 2800, 2850) based
-         system and are using GPIO lines for an I2C bus.
+         If you say yes to this option, support will be included for the VIA
+           82C586B I2C interface
  
-         This support is also available as a module. If so, the module
-         will be called i2c-ixp2000.
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-via.
  
-         This driver is deprecated and will be dropped soon. Use i2c-gpio
-         instead.
+ config I2C_VIAPRO
+       tristate "VIA VT82C596/82C686/82xx and CX700"
+       depends on PCI
+       help
+         If you say yes to this option, support will be included for the VIA
+         VT82C596 and later SMBus interface.  Specifically, the following
+         chipsets are supported:
+           VT82C596A/B
+           VT82C686A/B
+           VT8231
+           VT8233/A
+           VT8235
+           VT8237R/A/S
+           VT8251
+           CX700
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-viapro.
+ comment "Mac SMBus host controller drivers"
+       depends on PPC_CHRP || PPC_PMAC
+ config I2C_HYDRA
+       tristate "CHRP Apple Hydra Mac I/O I2C interface"
+       depends on PCI && PPC_CHRP && EXPERIMENTAL
+       select I2C_ALGOBIT
+       help
+         This supports the use of the I2C interface in the Apple Hydra Mac
+         I/O chip on some CHRP machines (e.g. the LongTrail).  Say Y if you
+         have such a machine.
+         This support is also available as a module.  If so, the module
+         will be called i2c-hydra.
  
  config I2C_POWERMAC
        tristate "Powermac I2C interface"
          This support is also available as a module.  If so, the module
          will be called i2c-powermac.
  
- config I2C_MPC
-       tristate "MPC107/824x/85xx/52xx/86xx"
-       depends on PPC32
+ comment "I2C system bus drivers (mostly embedded / system-on-chip)"
+ config I2C_AT91
+       tristate "Atmel AT91 I2C Two-Wire interface (TWI)"
+       depends on ARCH_AT91 && EXPERIMENTAL && BROKEN
        help
-         If you say yes to this option, support will be included for the
-         built-in I2C interface on the MPC107/Tsi107/MPC8240/MPC8245 and
-         MPC85xx/MPC8641 family processors. The driver may also work on 52xx
-         family processors, though interrupts are known not to work.
+         This supports the use of the I2C interface on Atmel AT91
+         processors.
  
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-mpc.
+         This driver is BROKEN because the controller which it uses
+         will easily trigger RX overrun and TX underrun errors.  Using
+         low I2C clock rates may partially work around those issues
+         on some systems.  Another serious problem is that there is no
+         documented way to issue repeated START conditions, as needed
+         to support combined I2C messages.  Use the i2c-gpio driver
+         unless your system can cope with those limitations.
  
- config I2C_NFORCE2
-       tristate "Nvidia nForce2, nForce3 and nForce4"
-       depends on PCI
+ config I2C_AU1550
+       tristate "Au1550/Au1200 SMBus interface"
+       depends on SOC_AU1550 || SOC_AU1200
        help
-         If you say yes to this option, support will be included for the Nvidia
-         nForce2, nForce3 and nForce4 families of mainboard I2C interfaces.
+         If you say yes to this option, support will be included for the
+         Au1550 and Au1200 SMBus interface.
  
          This driver can also be built as a module.  If so, the module
-         will be called i2c-nforce2.
+         will be called i2c-au1550.
  
- config I2C_OCORES
-       tristate "OpenCores I2C Controller"
-       depends on EXPERIMENTAL
+ config I2C_BLACKFIN_TWI
+       tristate "Blackfin TWI I2C support"
+       depends on BLACKFIN
+       depends on !BF561 && !BF531 && !BF532 && !BF533
        help
-         If you say yes to this option, support will be included for the
-         OpenCores I2C controller. For details see
-         http://www.opencores.org/projects.cgi/web/i2c/overview
+         This is the I2C bus driver for Blackfin on-chip TWI interface.
  
          This driver can also be built as a module.  If so, the module
-         will be called i2c-ocores.
+         will be called i2c-bfin-twi.
+ config I2C_BLACKFIN_TWI_CLK_KHZ
+       int "Blackfin TWI I2C clock (kHz)"
+       depends on I2C_BLACKFIN_TWI
+       range 10 400
+       default 50
+       help
+         The unit of the TWI clock is kHz.
+ config I2C_CPM
+       tristate "Freescale CPM1 or CPM2 (MPC8xx/826x)"
+       depends on (CPM1 || CPM2) && OF_I2C
+       help
+         This supports the use of the I2C interface on Freescale
+         processors with CPM1 or CPM2.
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-cpm.
+ config I2C_DAVINCI
+       tristate "DaVinci I2C driver"
+       depends on ARCH_DAVINCI
+       help
+         Support for TI DaVinci I2C controller driver.
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-davinci.
+         Please note that this driver might be needed to bring up other
+         devices such as DaVinci NIC.
+         For details please see http://www.ti.com/davinci
+ config I2C_GPIO
+       tristate "GPIO-based bitbanging I2C"
+       depends on GENERIC_GPIO
+       select I2C_ALGOBIT
+       help
+         This is a very simple bitbanging I2C driver utilizing the
+         arch-neutral GPIO API to control the SCL and SDA lines.
+ config I2C_IBM_IIC
+       tristate "IBM PPC 4xx on-chip I2C interface"
+       depends on 4xx
+       help
+         Say Y here if you want to use IIC peripheral found on
+         embedded IBM PPC 4xx based systems.
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-ibm_iic.
+ config I2C_IOP3XX
+       tristate "Intel IOPx3xx and IXP4xx on-chip I2C interface"
+       depends on ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX || ARCH_IOP13XX
+       help
+         Say Y here if you want to use the IIC bus controller on
+         the Intel IOPx3xx I/O Processors or IXP4xx Network Processors.
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-iop3xx.
+ config I2C_IXP2000
+       tristate "IXP2000 GPIO-Based I2C Interface (DEPRECATED)"
+       depends on ARCH_IXP2000
+       select I2C_ALGOBIT
+       help
+         Say Y here if you have an Intel IXP2000 (2400, 2800, 2850) based
+         system and are using GPIO lines for an I2C bus.
+         This support is also available as a module. If so, the module
+         will be called i2c-ixp2000.
+         This driver is deprecated and will be dropped soon. Use i2c-gpio
+         instead.
+ config I2C_MPC
+       tristate "MPC107/824x/85xx/52xx/86xx"
+       depends on PPC32
+       help
+         If you say yes to this option, support will be included for the
+         built-in I2C interface on the MPC107/Tsi107/MPC8240/MPC8245 and
+         MPC85xx/MPC8641 family processors. The driver may also work on 52xx
+         family processors, though interrupts are known not to work.
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-mpc.
+ config I2C_MV64XXX
+       tristate "Marvell mv64xxx I2C Controller"
+       depends on (MV64X60 || PLAT_ORION) && EXPERIMENTAL
+       help
+         If you say yes to this option, support will be included for the
+         built-in I2C interface on the Marvell 64xxx line of host bridges.
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-mv64xxx.
+ config I2C_OCORES
+       tristate "OpenCores I2C Controller"
+       depends on EXPERIMENTAL
+       help
+         If you say yes to this option, support will be included for the
+         OpenCores I2C controller. For details see
+         http://www.opencores.org/projects.cgi/web/i2c/overview
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-ocores.
  
  config I2C_OMAP
        tristate "OMAP I2C adapter"
        default y if MACH_OMAP_H3 || MACH_OMAP_OSK
        help
          If you say yes to this option, support will be included for the
 -        I2C interface on the Texas Instruments OMAP1/2 family of processors.
 -        Like OMAP1510/1610/1710/5912 and OMAP242x.
 +        I2C interface on the Texas Instruments OMAP1/2/3 family of
 +        processors.
 +        Like OMAP1510/1610/1710/5912, OMAP242x, OMAP34x and OMAP35x.
          For details see http://www.ti.com/omap.
  
- config I2C_PARPORT
-       tristate "Parallel port adapter"
-       depends on PARPORT
-       select I2C_ALGOBIT
-       help
-         This supports parallel port I2C adapters such as the ones made by
-         Philips or Velleman, Analog Devices evaluation boards, and more.
-         Basically any adapter using the parallel port as an I2C bus with
-         no extra chipset is supported by this driver, or could be.
-         This driver is a replacement for (and was inspired by) an older
-         driver named i2c-philips-par.  The new driver supports more devices,
-         and makes it easier to add support for new devices.
-         An adapter type parameter is now mandatory.  Please read the file
-         Documentation/i2c/busses/i2c-parport for details.
-         Another driver exists, named i2c-parport-light, which doesn't depend
-         on the parport driver.  This is meant for embedded systems. Don't say
-         Y here if you intend to say Y or M there.
-         This support is also available as a module.  If so, the module
-         will be called i2c-parport.
- config I2C_PARPORT_LIGHT
-       tristate "Parallel port adapter (light)"
-       select I2C_ALGOBIT
-       help
-         This supports parallel port I2C adapters such as the ones made by
-         Philips or Velleman, Analog Devices evaluation boards, and more.
-         Basically any adapter using the parallel port as an I2C bus with
-         no extra chipset is supported by this driver, or could be.
-         This driver is a light version of i2c-parport.  It doesn't depend
-         on the parport driver, and uses direct I/O access instead.  This
-         might be preferred on embedded systems where wasting memory for
-         the clean but heavy parport handling is not an option.  The
-         drawback is a reduced portability and the impossibility to
-         daisy-chain other parallel port devices.
-         Don't say Y here if you said Y or M to i2c-parport.  Saying M to
-         both is possible but both modules should not be loaded at the same
-         time.
-         This support is also available as a module.  If so, the module
-         will be called i2c-parport-light.
 +config I2C2_OMAP_BEAGLE
 +      bool "Enable I2C2 for OMAP3 BeagleBoard"
 +      depends on ARCH_OMAP && MACH_OMAP3_BEAGLE
 +      select OMAP_MUX
 +      default n
 +      help
 +        Say Y here if you want to enable I2C bus 2 at OMAP3 based
 +        BeagleBoard.
 +        I2C2 at BeagleBoard is connected to expansion connector, i.e. unused
 +        if nothing is connected to this connector. As internal OMAP3 pull up
 +        resistors are not strong enough, enabled but unused I2C2 bus results
 +        in error messages (e.g. I2C timeouts). Enable this only if you have
 +        something connected to I2C2 at board's expansion connector and this
 +        extension has additional pull up resistors for I2C2 bus.
 +
  config I2C_PASEMI
        tristate "PA Semi SMBus interface"
        depends on PPC_PASEMI && PCI
        help
          Supports the PA Semi PWRficient on-chip SMBus interfaces.
  
- config I2C_PROSAVAGE
-       tristate "S3/VIA (Pro)Savage (DEPRECATED)"
-       default n
-       depends on PCI
-       select I2C_ALGOBIT
+ config I2C_PNX
+       tristate "I2C bus support for Philips PNX targets"
+       depends on ARCH_PNX4008
        help
-         If you say yes to this option, support will be included for the
-         I2C bus and DDC bus of the S3VIA embedded Savage4 and ProSavage8
-         graphics processors.
-         chipsets supported:
-           S3/VIA KM266/VT8375 aka ProSavage8
-           S3/VIA KM133/VT8365 aka Savage4
+         This driver supports the Philips IP3204 I2C IP block master and/or
+         slave controller
  
-         This driver is deprecated in favor of the savagefb driver.
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-pnx.
  
-         This support is also available as a module.  If so, the module
-         will be called i2c-prosavage.
+ config I2C_PXA
+       tristate "Intel PXA2XX I2C adapter (EXPERIMENTAL)"
+       depends on EXPERIMENTAL && ARCH_PXA
+       help
+         If you have devices in the PXA I2C bus, say yes to this option.
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-pxa.
+ config I2C_PXA_SLAVE
+       bool "Intel PXA2XX I2C Slave comms support"
+       depends on I2C_PXA
+       help
+         Support I2C slave mode communications on the PXA I2C bus.  This
+         is necessary for systems where the PXA may be a target on the
+         I2C bus.
  
  config I2C_S3C2410
        tristate "S3C2410 I2C Driver"
          Say Y here to include support for I2C controller in the
          Samsung S3C2410 based System-on-Chip devices.
  
- config I2C_SAVAGE4
-       tristate "S3 Savage 4 (DEPRECATED)"
-       default n
-       depends on PCI
-       select I2C_ALGOBIT
+ config I2C_SH7760
+       tristate "Renesas SH7760 I2C Controller"
+       depends on CPU_SUBTYPE_SH7760
        help
-         If you say yes to this option, support will be included for the
-         S3 Savage 4 I2C interface.
-         This driver is deprecated in favor of the savagefb driver.
+         This driver supports the 2 I2C interfaces on the Renesas SH7760.
  
          This driver can also be built as a module.  If so, the module
-         will be called i2c-savage4.
+         will be called i2c-sh7760.
  
- config I2C_SIBYTE
-       tristate "SiByte SMBus interface"
-       depends on SIBYTE_SB1xxx_SOC
+ config I2C_SH_MOBILE
+       tristate "SuperH Mobile I2C Controller"
+       depends on SUPERH
        help
-         Supports the SiByte SOC on-chip I2C interfaces (2 channels).
+         If you say yes to this option, support will be included for the
+         built-in I2C interface on the Renesas SH-Mobile processor.
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-sh_mobile.
  
  config I2C_SIMTEC
        tristate "Simtec Generic I2C interface"
          This driver can also be built as a module. If so, the module
          will be called i2c-simtec.
  
- config SCx200_I2C
-       tristate "NatSemi SCx200 I2C using GPIO pins (DEPRECATED)"
-       depends on SCx200_GPIO
+ config I2C_VERSATILE
+       tristate "ARM Versatile/Realview I2C bus support"
+       depends on ARCH_VERSATILE || ARCH_REALVIEW
        select I2C_ALGOBIT
        help
-         Enable the use of two GPIO pins of a SCx200 processor as an I2C bus.
-         If you don't know what to do here, say N.
+         Say yes if you want to support the I2C serial bus on ARMs Versatile
+         range of platforms.
  
-         This support is also available as a module.  If so, the module
-         will be called scx200_i2c.
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-versatile.
  
-         This driver is deprecated and will be dropped soon. Use i2c-gpio
-         (or scx200_acb) instead.
+ comment "External I2C/SMBus adapter drivers"
  
- config SCx200_I2C_SCL
-       int "GPIO pin used for SCL"
-       depends on SCx200_I2C
-       default "12"
+ config I2C_PARPORT
+       tristate "Parallel port adapter"
+       depends on PARPORT
+       select I2C_ALGOBIT
        help
-         Enter the GPIO pin number used for the SCL signal.  This value can
-         also be specified with a module parameter.
+         This supports parallel port I2C adapters such as the ones made by
+         Philips or Velleman, Analog Devices evaluation boards, and more.
+         Basically any adapter using the parallel port as an I2C bus with
+         no extra chipset is supported by this driver, or could be.
  
- config SCx200_I2C_SDA
-       int "GPIO pin used for SDA"
-       depends on SCx200_I2C
-       default "13"
-       help
-         Enter the GPIO pin number used for the SSA signal.  This value can
-         also be specified with a module parameter.
+         This driver is a replacement for (and was inspired by) an older
+         driver named i2c-philips-par.  The new driver supports more devices,
+         and makes it easier to add support for new devices.
  
- config SCx200_ACB
-       tristate "Geode ACCESS.bus support"
-       depends on X86_32 && PCI
-       help
-         Enable the use of the ACCESS.bus controllers on the Geode SCx200 and
-         SC1100 processors and the CS5535 and CS5536 Geode companion devices.
+         An adapter type parameter is now mandatory.  Please read the file
+         Documentation/i2c/busses/i2c-parport for details.
  
-         If you don't know what to do here, say N.
+         Another driver exists, named i2c-parport-light, which doesn't depend
+         on the parport driver.  This is meant for embedded systems. Don't say
+         Y here if you intend to say Y or M there.
  
          This support is also available as a module.  If so, the module
-         will be called scx200_acb.
- config I2C_SIS5595
-       tristate "SiS 5595"
-       depends on PCI
-       help
-         If you say yes to this option, support will be included for the
-         SiS5595 SMBus (a subset of I2C) interface.
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-sis5595.
+         will be called i2c-parport.
  
- config I2C_SIS630
-       tristate "SiS 630/730"
-       depends on PCI
+ config I2C_PARPORT_LIGHT
+       tristate "Parallel port adapter (light)"
+       select I2C_ALGOBIT
        help
-         If you say yes to this option, support will be included for the
-         SiS630 and SiS730 SMBus (a subset of I2C) interface.
+         This supports parallel port I2C adapters such as the ones made by
+         Philips or Velleman, Analog Devices evaluation boards, and more.
+         Basically any adapter using the parallel port as an I2C bus with
+         no extra chipset is supported by this driver, or could be.
  
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-sis630.
+         This driver is a light version of i2c-parport.  It doesn't depend
+         on the parport driver, and uses direct I/O access instead.  This
+         might be preferred on embedded systems where wasting memory for
+         the clean but heavy parport handling is not an option.  The
+         drawback is a reduced portability and the impossibility to
+         daisy-chain other parallel port devices.
  
- config I2C_SIS96X
-       tristate "SiS 96x"
-       depends on PCI
-       help
-         If you say yes to this option, support will be included for the SiS
-         96x SMBus (a subset of I2C) interfaces.  Specifically, the following
-         chipsets are supported:
-           645/961
-           645DX/961
-           645DX/962
-           648/961
-           650/961
-           735
-           745
+         Don't say Y here if you said Y or M to i2c-parport.  Saying M to
+         both is possible but both modules should not be loaded at the same
+         time.
  
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-sis96x.
+         This support is also available as a module.  If so, the module
+         will be called i2c-parport-light.
  
  config I2C_TAOS_EVM
        tristate "TAOS evaluation module"
          This support is also available as a module.  If so, the module
          will be called i2c-taos-evm.
  
- config I2C_STUB
-       tristate "I2C/SMBus Test Stub"
-       depends on EXPERIMENTAL && m
-       default 'n'
-       help
-         This module may be useful to developers of SMBus client drivers,
-         especially for certain kinds of sensor chips.
-         If you do build this module, be sure to read the notes and warnings
-         in <file:Documentation/i2c/i2c-stub>.
-         If you don't know what to do here, definitely say N.
  config I2C_TINY_USB
-       tristate "I2C-Tiny-USB"
+       tristate "Tiny-USB adapter"
        depends on USB
        help
          If you say yes to this option, support will be included for the
          This driver can also be built as a module.  If so, the module
          will be called i2c-tiny-usb.
  
- config I2C_VERSATILE
-       tristate "ARM Versatile/Realview I2C bus support"
-       depends on ARCH_VERSATILE || ARCH_REALVIEW
+ comment "Graphics adapter I2C/DDC channel drivers"
+       depends on PCI
+ config I2C_VOODOO3
+       tristate "Voodoo 3"
+       depends on PCI
        select I2C_ALGOBIT
        help
-         Say yes if you want to support the I2C serial bus on ARMs Versatile
-         range of platforms.
+         If you say yes to this option, support will be included for the
+         Voodoo 3 I2C interface.
  
          This driver can also be built as a module.  If so, the module
-         will be called i2c-versatile.
+         will be called i2c-voodoo3.
+ comment "Other I2C/SMBus bus drivers"
  
  config I2C_ACORN
        tristate "Acorn IOC/IOMD I2C bus support"
  
          If you don't know, say Y.
  
- config I2C_VIA
-       tristate "VIA 82C586B"
-       depends on PCI && EXPERIMENTAL
-       select I2C_ALGOBIT
-       help
-         If you say yes to this option, support will be included for the VIA
-           82C586B I2C interface
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-via.
- config I2C_VIAPRO
-       tristate "VIA VT82C596/82C686/82xx and CX700"
-       depends on PCI
-       help
-         If you say yes to this option, support will be included for the VIA
-         VT82C596 and later SMBus interface.  Specifically, the following
-         chipsets are supported:
-           VT82C596A/B
-           VT82C686A/B
-           VT8231
-           VT8233/A
-           VT8235
-           VT8237R/A/S
-           VT8251
-           CX700
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-viapro.
- config I2C_VOODOO3
-       tristate "Voodoo 3"
-       depends on PCI
-       select I2C_ALGOBIT
+ config I2C_ELEKTOR
+       tristate "Elektor ISA card"
+       depends on ISA && BROKEN_ON_SMP
+       select I2C_ALGOPCF
        help
-         If you say yes to this option, support will be included for the
-         Voodoo 3 I2C interface.
+         This supports the PCF8584 ISA bus I2C adapter.  Say Y if you own
+         such an adapter.
  
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-voodoo3.
+         This support is also available as a module.  If so, the module
+         will be called i2c-elektor.
  
  config I2C_PCA_ISA
        tristate "PCA9564 on an ISA bus"
@@@ -674,26 -629,6 +645,6 @@@ config I2C_PCA_PLATFOR
          This driver can also be built as a module.  If so, the module
          will be called i2c-pca-platform.
  
- config I2C_MV64XXX
-       tristate "Marvell mv64xxx I2C Controller"
-       depends on (MV64X60 || PLAT_ORION) && EXPERIMENTAL
-       help
-         If you say yes to this option, support will be included for the
-         built-in I2C interface on the Marvell 64xxx line of host bridges.
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-mv64xxx.
- config I2C_PNX
-       tristate "I2C bus support for Philips PNX targets"
-       depends on ARCH_PNX4008
-       help
-         This driver supports the Philips IP3204 I2C IP block master and/or
-         slave controller
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-pnx.
  config I2C_PMCMSP
        tristate "PMC MSP I2C TWI Controller"
        depends on PMC_MSP
          This driver can also be built as module. If so, the module
          will be called i2c-pmcmsp.
  
- config I2C_SH7760
-       tristate "Renesas SH7760 I2C Controller"
-       depends on CPU_SUBTYPE_SH7760
+ config I2C_SIBYTE
+       tristate "SiByte SMBus interface"
+       depends on SIBYTE_SB1xxx_SOC
        help
-         This driver supports the 2 I2C interfaces on the Renesas SH7760.
+         Supports the SiByte SOC on-chip I2C interfaces (2 channels).
  
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-sh7760.
+ config I2C_STUB
+       tristate "I2C/SMBus Test Stub"
+       depends on EXPERIMENTAL && m
+       default 'n'
+       help
+         This module may be useful to developers of SMBus client drivers,
+         especially for certain kinds of sensor chips.
  
- config I2C_SH_MOBILE
-       tristate "SuperH Mobile I2C Controller"
-       depends on SUPERH
+         If you do build this module, be sure to read the notes and warnings
+         in <file:Documentation/i2c/i2c-stub>.
+         If you don't know what to do here, definitely say N.
+ config SCx200_I2C
+       tristate "NatSemi SCx200 I2C using GPIO pins (DEPRECATED)"
+       depends on SCx200_GPIO
+       select I2C_ALGOBIT
        help
-         If you say yes to this option, support will be included for the
-         built-in I2C interface on the Renesas SH-Mobile processor.
+         Enable the use of two GPIO pins of a SCx200 processor as an I2C bus.
  
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-sh_mobile.
+         If you don't know what to do here, say N.
+         This support is also available as a module.  If so, the module
+         will be called scx200_i2c.
+         This driver is deprecated and will be dropped soon. Use i2c-gpio
+         (or scx200_acb) instead.
+ config SCx200_I2C_SCL
+       int "GPIO pin used for SCL"
+       depends on SCx200_I2C
+       default "12"
+       help
+         Enter the GPIO pin number used for the SCL signal.  This value can
+         also be specified with a module parameter.
+ config SCx200_I2C_SDA
+       int "GPIO pin used for SDA"
+       depends on SCx200_I2C
+       default "13"
+       help
+         Enter the GPIO pin number used for the SSA signal.  This value can
+         also be specified with a module parameter.
+ config SCx200_ACB
+       tristate "Geode ACCESS.bus support"
+       depends on X86_32 && PCI
+       help
+         Enable the use of the ACCESS.bus controllers on the Geode SCx200 and
+         SC1100 processors and the CS5535 and CS5536 Geode companion devices.
+         If you don't know what to do here, say N.
+         This support is also available as a module.  If so, the module
+         will be called scx200_acb.
  
  endmenu
index 889fcc0520ae85a4fccebb26e03dbc36a20307b5,97dbfa2107fee2fe7b7170219c9aebf552b8381b..d4dc22da8cc7b9fccbbaefe82db7c8fcec05c512
@@@ -2,60 -2,70 +2,71 @@@
  # Makefile for the i2c bus drivers.
  #
  
+ # PC SMBus host controller drivers
  obj-$(CONFIG_I2C_ALI1535)     += i2c-ali1535.o
  obj-$(CONFIG_I2C_ALI1563)     += i2c-ali1563.o
  obj-$(CONFIG_I2C_ALI15X3)     += i2c-ali15x3.o
  obj-$(CONFIG_I2C_AMD756)      += i2c-amd756.o
  obj-$(CONFIG_I2C_AMD756_S4882)        += i2c-amd756-s4882.o
  obj-$(CONFIG_I2C_AMD8111)     += i2c-amd8111.o
+ obj-$(CONFIG_I2C_I801)                += i2c-i801.o
+ obj-$(CONFIG_I2C_ISCH)                += i2c-isch.o
+ obj-$(CONFIG_I2C_NFORCE2)     += i2c-nforce2.o
+ obj-$(CONFIG_I2C_NFORCE2_S4985)       += i2c-nforce2-s4985.o
+ obj-$(CONFIG_I2C_PIIX4)               += i2c-piix4.o
+ obj-$(CONFIG_I2C_SIS5595)     += i2c-sis5595.o
+ obj-$(CONFIG_I2C_SIS630)      += i2c-sis630.o
+ obj-$(CONFIG_I2C_SIS96X)      += i2c-sis96x.o
+ obj-$(CONFIG_I2C_VIA)         += i2c-via.o
+ obj-$(CONFIG_I2C_VIAPRO)      += i2c-viapro.o
+ # Mac SMBus host controller drivers
+ obj-$(CONFIG_I2C_HYDRA)               += i2c-hydra.o
+ obj-$(CONFIG_I2C_POWERMAC)    += i2c-powermac.o
+ # Embebbed system I2C/SMBus host controller drivers
  obj-$(CONFIG_I2C_AT91)                += i2c-at91.o
  obj-$(CONFIG_I2C_AU1550)      += i2c-au1550.o
  obj-$(CONFIG_I2C_BLACKFIN_TWI)        += i2c-bfin-twi.o
+ obj-$(CONFIG_I2C_CPM)         += i2c-cpm.o
  obj-$(CONFIG_I2C_DAVINCI)     += i2c-davinci.o
- obj-$(CONFIG_I2C_ELEKTOR)     += i2c-elektor.o
  obj-$(CONFIG_I2C_GPIO)                += i2c-gpio.o
- obj-$(CONFIG_I2C_HYDRA)               += i2c-hydra.o
- obj-$(CONFIG_I2C_I801)                += i2c-i801.o
- obj-$(CONFIG_I2C_I810)                += i2c-i810.o
  obj-$(CONFIG_I2C_IBM_IIC)     += i2c-ibm_iic.o
  obj-$(CONFIG_I2C_IOP3XX)      += i2c-iop3xx.o
  obj-$(CONFIG_I2C_IXP2000)     += i2c-ixp2000.o
- obj-$(CONFIG_I2C_POWERMAC)    += i2c-powermac.o
  obj-$(CONFIG_I2C_MPC)         += i2c-mpc.o
  obj-$(CONFIG_I2C_MV64XXX)     += i2c-mv64xxx.o
- obj-$(CONFIG_I2C_NFORCE2)     += i2c-nforce2.o
  obj-$(CONFIG_I2C_OCORES)      += i2c-ocores.o
  obj-$(CONFIG_I2C_OMAP)                += i2c-omap.o
- obj-$(CONFIG_I2C_PARPORT)     += i2c-parport.o
- obj-$(CONFIG_I2C_PARPORT_LIGHT)       += i2c-parport-light.o
  obj-$(CONFIG_I2C_PASEMI)      += i2c-pasemi.o
- obj-$(CONFIG_I2C_PCA_ISA)     += i2c-pca-isa.o
- obj-$(CONFIG_I2C_PCA_PLATFORM)        += i2c-pca-platform.o
- obj-$(CONFIG_I2C_PIIX4)               += i2c-piix4.o
- obj-$(CONFIG_I2C_PMCMSP)      += i2c-pmcmsp.o
  obj-$(CONFIG_I2C_PNX)         += i2c-pnx.o
- obj-$(CONFIG_I2C_PROSAVAGE)   += i2c-prosavage.o
  obj-$(CONFIG_I2C_PXA)         += i2c-pxa.o
  obj-$(CONFIG_I2C_S3C2410)     += i2c-s3c2410.o
- obj-$(CONFIG_I2C_SAVAGE4)     += i2c-savage4.o
  obj-$(CONFIG_I2C_SH7760)      += i2c-sh7760.o
  obj-$(CONFIG_I2C_SH_MOBILE)   += i2c-sh_mobile.o
- obj-$(CONFIG_I2C_SIBYTE)      += i2c-sibyte.o
  obj-$(CONFIG_I2C_SIMTEC)      += i2c-simtec.o
- obj-$(CONFIG_I2C_SIS5595)     += i2c-sis5595.o
- obj-$(CONFIG_I2C_SIS630)      += i2c-sis630.o
- obj-$(CONFIG_I2C_SIS96X)      += i2c-sis96x.o
- obj-$(CONFIG_I2C_STUB)                += i2c-stub.o
+ obj-$(CONFIG_I2C_VERSATILE)   += i2c-versatile.o
+ # External I2C/SMBus adapter drivers
+ obj-$(CONFIG_I2C_PARPORT)     += i2c-parport.o
+ obj-$(CONFIG_I2C_PARPORT_LIGHT)       += i2c-parport-light.o
  obj-$(CONFIG_I2C_TAOS_EVM)    += i2c-taos-evm.o
  obj-$(CONFIG_I2C_TINY_USB)    += i2c-tiny-usb.o
- obj-$(CONFIG_I2C_VERSATILE)   += i2c-versatile.o
- obj-$(CONFIG_I2C_ACORN)               += i2c-acorn.o
- obj-$(CONFIG_I2C_VIA)         += i2c-via.o
- obj-$(CONFIG_I2C_VIAPRO)      += i2c-viapro.o
+ # Graphics adapter I2C/DDC channel drivers
  obj-$(CONFIG_I2C_VOODOO3)     += i2c-voodoo3.o
+ # Other I2C/SMBus bus drivers
+ obj-$(CONFIG_I2C_ACORN)               += i2c-acorn.o
+ obj-$(CONFIG_I2C_ELEKTOR)     += i2c-elektor.o
+ obj-$(CONFIG_I2C_PCA_ISA)     += i2c-pca-isa.o
+ obj-$(CONFIG_I2C_PCA_PLATFORM)        += i2c-pca-platform.o
+ obj-$(CONFIG_I2C_PMCMSP)      += i2c-pmcmsp.o
+ obj-$(CONFIG_I2C_SIBYTE)      += i2c-sibyte.o
+ obj-$(CONFIG_I2C_STUB)                += i2c-stub.o
  obj-$(CONFIG_SCx200_ACB)      += scx200_acb.o
  obj-$(CONFIG_SCx200_I2C)      += scx200_i2c.o
 +obj-$(CONFIG_I2C_OMAP)          += i2c-omap.o
  
  ifeq ($(CONFIG_I2C_DEBUG_BUS),y)
  EXTRA_CFLAGS += -DDEBUG
index b421727af9200e50a27e70277d7131cb3feccbc1,a95cb9465d656949bed4429279a75c35fb547b23..e91be601d69f30438caa1aa549222968b1b41d6e
@@@ -14,6 -14,32 +14,32 @@@ config DS168
          This driver can also be built as a module.  If so, the module
          will be called ds1682.
  
+ config AT24
+       tristate "EEPROMs from most vendors"
+       depends on SYSFS && EXPERIMENTAL
+       help
+         Enable this driver to get read/write support to most I2C EEPROMs,
+         after you configure the driver to know about each EEPROM on
+         your target board.  Use these generic chip names, instead of
+         vendor-specific ones like at24c64 or 24lc02:
+            24c00, 24c01, 24c02, spd (readonly 24c02), 24c04, 24c08,
+            24c16, 24c32, 24c64, 24c128, 24c256, 24c512, 24c1024
+         Unless you like data loss puzzles, always be sure that any chip
+         you configure as a 24c32 (32 kbit) or larger is NOT really a
+         24c16 (16 kbit) or smaller, and vice versa. Marking the chip
+         as read-only won't help recover from this. Also, if your chip
+         has any software write-protect mechanism you may want to review the
+         code to make sure this driver won't turn it on by accident.
+         If you use this with an SMBus adapter instead of an I2C adapter,
+         full functionality is not available.  Only smaller devices are
+         supported (24c16 and below, max 4 kByte).
+         This driver can also be built as a module.  If so, the module
+         will be called at24.
  config SENSORS_EEPROM
        tristate "EEPROM reader"
        depends on EXPERIMENTAL
@@@ -26,8 -52,8 +52,8 @@@
          will be called eeprom.
  
  config SENSORS_PCF8574
-       tristate "Philips PCF8574 and PCF8574A"
-       depends on EXPERIMENTAL
+       tristate "Philips PCF8574 and PCF8574A (DEPRECATED)"
+       depends on EXPERIMENTAL && GPIO_PCF857X = "n"
        default n
        help
          If you say yes here you get support for Philips PCF8574 and 
          This driver can also be built as a module.  If so, the module
          will be called pcf8574.
  
+         This driver is deprecated and will be dropped soon. Use
+         drivers/gpio/pcf857x.c instead.
          These devices are hard to detect and rarely found on mainstream
          hardware.  If unsure, say N.
  
  config PCF8575
-       tristate "Philips PCF8575"
+       tristate "Philips PCF8575 (DEPRECATED)"
        default n
+       depends on GPIO_PCF857X = "n"
        help
          If you say yes here you get support for Philips PCF8575 chip.
          This chip is a 16-bit I/O expander for the I2C bus.  Several other
          This driver can also be built as a module.  If so, the module
          will be called pcf8575.
  
+         This driver is deprecated and will be dropped soon. Use
+         drivers/gpio/pcf857x.c instead.
          This device is hard to detect and is rarely found on mainstream
          hardware.  If unsure, say N.
  
  config SENSORS_PCA9539
        tristate "Philips PCA9539 16-bit I/O port (DEPRECATED)"
-       depends on EXPERIMENTAL && GPIO_PCA9539 = "n"
+       depends on EXPERIMENTAL && GPIO_PCA953X = "n"
        help
          If you say yes here you get support for the Philips PCA9539
          16-bit I/O port.
@@@ -64,7 -97,7 +97,7 @@@
          will be called pca9539.
  
          This driver is deprecated and will be dropped soon. Use
-         drivers/gpio/pca9539.c instead.
+         drivers/gpio/pca953x.c instead.
  
  config SENSORS_PCF8591
        tristate "Philips PCF8591"
@@@ -93,7 -126,7 +126,7 @@@ config ISP1301_OMA
  
  config TPS65010
        tristate "TPS6501x Power Management chips"
-       depends on HAVE_GPIO_LIB
+       depends on GPIOLIB
        default y if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_OSK
        help
          If you say yes here you get support for the TPS6501x series of
          This driver can also be built as a module.  If so, the module
          will be called tps65010.
  
 +config SENSORS_TLV320AIC23
 +      tristate "Texas Instruments TLV320AIC23 Codec"
 +      depends on I2C && I2C_OMAP
 +      help
 +        If you say yes here you get support for the I2C control
 +        interface for Texas Instruments TLV320AIC23 audio codec.
 +
 +config GPIOEXPANDER_OMAP
 +      bool "GPIO Expander PCF8574PWR for OMAP"
 +      depends on I2C && (ARCH_OMAP16XX || ARCH_OMAP24XX)
 +      help
 +        If you say yes here you get support for I/O expander calls
 +        to configure IrDA, Camera and audio devices.
 +
 +config TWL4030_CORE
 +      bool "TI's TWL4030 companion chip Core Driver Support"
 +      depends on I2C=y && (ARCH_OMAP24XX || ARCH_OMAP34XX)
 +      help
 +        Say yes here if you have TWL4030 chip on your board
 +
 +config TWL4030_GPIO
 +      bool "TWL4030 GPIO Driver"
 +      depends on TWL4030_CORE
 +
 +config TWL4030_MADC
 +      tristate "TWL4030 MADC Driver"
 +      depends on TWL4030_CORE
 +      help
 +        The TWL4030 Monitoring ADC driver enables the host
 +        processor to monitor analog signals using analog-to-digital
 +        conversions on the input source. TWL4030 MADC provides the
 +        following features:
 +         - Single 10-bit ADC with successive approximation register (SAR) conversion;
 +         - Analog multiplexer for 16 inputs;
 +         - Seven (of the 16) inputs are freely available;
 +         - Battery voltage monitoring;
 +         - Concurrent conversion request management;
 +         - Interrupt signal to Primary Interrupt Handler;
 +         - Averaging feature;
 +         - Selective enable/disable of the averaging feature.
 +
 +        Say 'y' here to statically link this module into the kernel or 'm'
 +        to build it as a dinamically loadable module. The module will be
 +        called twl4030-madc.ko
 +
 +config TWL4030_USB
 +      tristate "TWL4030 USB Transceiver Driver"
 +      depends on TWL4030_CORE
 +
 +choice
 +      prompt "Transceiver mode"
 +      depends on TWL4030_USB
 +      help
 +        TWL4030 USB transceiver can operate in various
 +        mutually-exclusive modes. Select one of them.
 +
 +config TWL4030_USB_HS_ULPI
 +      depends on TWL4030_USB
 +      bool "High-speed ULPI"
 +      help
 +        Say Y here if the TWL4030 is connected to high-speed USB
 +        controller through a ULPI interface.
 +
 +endchoice
 +
 +config TWL4030_PWRBUTTON
 +      tristate "TWL4030 Power button Driver"
 +      depends on TWL4030_CORE
 +
 +config TWL4030_POWEROFF
 +      tristate "TWL4030 device poweroff"
 +      depends on TWL4030_CORE
 +
  config SENSORS_MAX6875
        tristate "Maxim MAX6875 Power supply supervisor"
        depends on EXPERIMENTAL
@@@ -202,23 -162,6 +235,23 @@@ config SENSORS_TSL255
          This driver can also be built as a module.  If so, the module
          will be called tsl2550.
  
 +config SENSORS_TSL2563
 +       tristate "Taos TSL2563 ambient light sensor"
 +       depends on I2C && HWMON
 +       help
 +         If you say yes here you get support for the Taos TSL2563
 +         ambient light sensor.
 +
 +         This driver can also be built as a module.  If so, the module
 +         will be called tsl2563.
 +
 +config LP5521
 +      tristate "LP5521 LED driver chip"
 +      depends on I2C
 +      help
 +        If you say yes here you get support for the National Semiconductor
 +        LP5521 LED driver.
 +
  config MENELAUS
        bool "TWL92330/Menelaus PM chip"
        depends on I2C=y && ARCH_OMAP24XX
index 1f81ebd5b1524110b2fdabe855875e316b9b5c41,39e3e69ed1256bf93de0be16b9687bd15eb8e4a9..9e245b1ee74b6490a37744742ce04cb165ce79dc
@@@ -10,6 -10,7 +10,7 @@@
  #
  
  obj-$(CONFIG_DS1682)          += ds1682.o
+ obj-$(CONFIG_AT24)            += at24.o
  obj-$(CONFIG_SENSORS_EEPROM)  += eeprom.o
  obj-$(CONFIG_SENSORS_MAX6875) += max6875.o
  obj-$(CONFIG_SENSORS_PCA9539) += pca9539.o
@@@ -18,20 -19,10 +19,20 @@@ obj-$(CONFIG_PCF8575)              += pcf8575.
  obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
  obj-$(CONFIG_ISP1301_OMAP)    += isp1301_omap.o
  obj-$(CONFIG_TPS65010)                += tps65010.o
 +obj-$(CONFIG_SENSORS_TLV320AIC23) += tlv320aic23.o
 +obj-$(CONFIG_GPIOEXPANDER_OMAP)       += gpio_expander_omap.o
  obj-$(CONFIG_MENELAUS)                += menelaus.o
  obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o
 +obj-$(CONFIG_SENSORS_TSL2563) += tsl2563.o
 +obj-$(CONFIG_TWL4030_CORE)    += twl4030-core.o twl4030-pwrirq.o
 +obj-$(CONFIG_TWL4030_GPIO)    += twl4030-gpio.o
 +obj-$(CONFIG_TWL4030_USB)     += twl4030-usb.o
 +obj-$(CONFIG_TWL4030_POWEROFF)        += twl4030-poweroff.o
 +obj-$(CONFIG_TWL4030_PWRBUTTON)       += twl4030-pwrbutton.o
 +obj-$(CONFIG_TWL4030_MADC)    += twl4030-madc.o
 +obj-$(CONFIG_RTC_X1205_I2C)   += x1205.o
 +obj-$(CONFIG_LP5521)          += lp5521.o
  
  ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
  EXTRA_CFLAGS += -DDEBUG
  endif
 -
index 632431f435a937abd21cd3ad7a29fd34e13d1a24,0000000000000000000000000000000000000000..1a8e4137c058151ef106d57a6f81f4dd9f553dd7
mode 100644,000000..100644
--- /dev/null
@@@ -1,1006 -1,0 +1,1006 @@@
-       set_irq_type(irq_num, IRQT_FALLING);
 +/*
 + * twl4030_core.c - driver for TWL4030 PM and audio CODEC device
 + *
 + * Copyright (C) 2005-2006 Texas Instruments, Inc.
 + *
 + * Modifications to defer interrupt handling to a kernel thread:
 + * Copyright (C) 2006 MontaVista Software, Inc.
 + *
 + * Based on tlv320aic23.c:
 + * Copyright (c) by Kai Svahn <kai.svahn@nokia.com>
 + *
 + * Code cleanup and modifications to IRQ handler.
 + * by syed khasim <x0khasim@ti.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.
 + *
 + * 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/module.h>
 +#include <linux/kernel_stat.h>
 +#include <linux/init.h>
 +#include <linux/time.h>
 +#include <linux/mutex.h>
 +#include <linux/interrupt.h>
 +#include <linux/random.h>
 +#include <linux/syscalls.h>
 +#include <linux/kthread.h>
 +
 +#include <linux/i2c.h>
 +#include <linux/i2c/twl4030.h>
 +#include <linux/i2c/twl4030-gpio.h>
 +#include <linux/i2c/twl4030-madc.h>
 +#include <linux/i2c/twl4030-pwrirq.h>
 +#include <linux/slab.h>
 +#include <linux/clk.h>
 +#include <linux/device.h>
 +#include <linux/irq.h>
 +
 +#include <asm/mach/irq.h>
 +
 +#include <asm/arch/gpio.h>
 +#include <asm/arch/mux.h>
 +
 +#define DRIVER_NAME                   "twl4030"
 +
 +/* Macro Definitions */
 +#define TWL_CLIENT_STRING             "TWL4030-ID"
 +#define TWL_CLIENT_USED                       1
 +#define TWL_CLIENT_FREE                       0
 +
 +/* IRQ Flags */
 +#define FREE                          0
 +#define USED                          1
 +
 +/* Primary Interrupt Handler on TWL4030 Registers */
 +
 +/* Register Definitions */
 +
 +#define REG_PIH_ISR_P1                        (0x1)
 +#define REG_PIH_ISR_P2                        (0x2)
 +#define REG_PIH_SIR                   (0x3)
 +
 +/* Triton Core internal information (BEGIN) */
 +
 +/* Last - for index max*/
 +#define TWL4030_MODULE_LAST           TWL4030_MODULE_SECURED_REG
 +
 +/* Slave address */
 +#define TWL4030_NUM_SLAVES            0x04
 +#define TWL4030_SLAVENUM_NUM0         0x00
 +#define TWL4030_SLAVENUM_NUM1         0x01
 +#define TWL4030_SLAVENUM_NUM2         0x02
 +#define TWL4030_SLAVENUM_NUM3         0x03
 +#define TWL4030_SLAVEID_ID0           0x48
 +#define TWL4030_SLAVEID_ID1           0x49
 +#define TWL4030_SLAVEID_ID2           0x4A
 +#define TWL4030_SLAVEID_ID3           0x4B
 +
 +/* Base Address defns */
 +/* USB ID */
 +#define TWL4030_BASEADD_USB           0x0000
 +/* AUD ID */
 +#define TWL4030_BASEADD_AUDIO_VOICE   0x0000
 +#define TWL4030_BASEADD_GPIO          0x0098
 +
 +#define TWL4030_BASEADD_INTBR         0x0085
 +#define TWL4030_BASEADD_PIH           0x0080
 +#define TWL4030_BASEADD_TEST          0x004C
 +/* AUX ID */
 +#define TWL4030_BASEADD_INTERRUPTS    0x00B9
 +#define TWL4030_BASEADD_LED           0x00EE
 +#define TWL4030_BASEADD_MADC          0x0000
 +#define TWL4030_BASEADD_MAIN_CHARGE   0x0074
 +#define TWL4030_BASEADD_PRECHARGE     0x00AA
 +#define TWL4030_BASEADD_PWM0          0x00F8
 +#define TWL4030_BASEADD_PWM1          0x00FB
 +#define TWL4030_BASEADD_PWMA          0x00EF
 +#define TWL4030_BASEADD_PWMB          0x00F1
 +#define TWL4030_BASEADD_KEYPAD                0x00D2
 +/* POWER ID */
 +#define TWL4030_BASEADD_BACKUP                0x0014
 +#define TWL4030_BASEADD_INT           0x002E
 +#define TWL4030_BASEADD_PM_MASTER     0x0036
 +#define TWL4030_BASEADD_PM_RECEIVER   0x005B
 +#define TWL4030_BASEADD_RTC           0x001C
 +#define TWL4030_BASEADD_SECURED_REG   0x0000
 +
 +/* TWL4030 BCI registers */
 +#define TWL4030_INTERRUPTS_BCIIMR1A   0x2
 +#define TWL4030_INTERRUPTS_BCIIMR2A   0x3
 +#define TWL4030_INTERRUPTS_BCIIMR1B   0x6
 +#define TWL4030_INTERRUPTS_BCIIMR2B   0x7
 +#define TWL4030_INTERRUPTS_BCIISR1A   0x0
 +#define TWL4030_INTERRUPTS_BCIISR2A   0x1
 +#define TWL4030_INTERRUPTS_BCIISR1B   0x4
 +#define TWL4030_INTERRUPTS_BCIISR2B   0x5
 +
 +/* TWL4030 keypad registers */
 +#define TWL4030_KEYPAD_KEYP_IMR1      0x12
 +#define TWL4030_KEYPAD_KEYP_IMR2      0x14
 +#define TWL4030_KEYPAD_KEYP_ISR1      0x11
 +#define TWL4030_KEYPAD_KEYP_ISR2      0x13
 +
 +
 +/* Triton Core internal information (END) */
 +
 +/* Few power values */
 +#define R_CFG_BOOT                    0x05
 +#define R_PROTECT_KEY                 0x0E
 +
 +/* access control */
 +#define KEY_UNLOCK1                   0xce
 +#define KEY_UNLOCK2                   0xec
 +#define KEY_LOCK                      0x00
 +
 +#define HFCLK_FREQ_19p2_MHZ           (1 << 0)
 +#define HFCLK_FREQ_26_MHZ             (2 << 0)
 +#define HFCLK_FREQ_38p4_MHZ           (3 << 0)
 +#define HIGH_PERF_SQ                  (1 << 3)
 +
 +/* on I2C-1 for 2430SDP */
 +#define CONFIG_I2C_TWL4030_ID         1
 +
 +/* SIH_CTRL registers that aren't defined elsewhere */
 +#define TWL4030_INTERRUPTS_BCISIHCTRL 0x0d
 +#define TWL4030_MADC_MADC_SIH_CTRL    0x67
 +#define TWL4030_KEYPAD_KEYP_SIH_CTRL  0x17
 +
 +#define TWL4030_SIH_CTRL_COR_MASK     (1 << 2)
 +
 +/**
 + * struct twl4030_mod_iregs - TWL module IMR/ISR regs to mask/clear at init
 + * @mod_no: TWL4030 module number (e.g., TWL4030_MODULE_GPIO)
 + * @sih_ctrl: address of module SIH_CTRL register
 + * @reg_cnt: number of IMR/ISR regs
 + * @imrs: pointer to array of TWL module interrupt mask register indices
 + * @isrs: pointer to array of TWL module interrupt status register indices
 + *
 + * Ties together TWL4030 modules and lists of IMR/ISR registers to mask/clear
 + * during twl_init_irq().
 + */
 +struct twl4030_mod_iregs {
 +      const u8 mod_no;
 +      const u8 sih_ctrl;
 +      const u8 reg_cnt;
 +      const u8 *imrs;
 +      const u8 *isrs;
 +};
 +
 +/* TWL4030 INT module interrupt mask registers */
 +static const u8 __initconst twl4030_int_imr_regs[] = {
 +      TWL4030_INT_PWR_IMR1,
 +      TWL4030_INT_PWR_IMR2,
 +};
 +
 +/* TWL4030 INT module interrupt status registers */
 +static const u8 __initconst twl4030_int_isr_regs[] = {
 +      TWL4030_INT_PWR_ISR1,
 +      TWL4030_INT_PWR_ISR2,
 +};
 +
 +/* TWL4030 INTERRUPTS module interrupt mask registers */
 +static const u8 __initconst twl4030_interrupts_imr_regs[] = {
 +      TWL4030_INTERRUPTS_BCIIMR1A,
 +      TWL4030_INTERRUPTS_BCIIMR1B,
 +      TWL4030_INTERRUPTS_BCIIMR2A,
 +      TWL4030_INTERRUPTS_BCIIMR2B,
 +};
 +
 +/* TWL4030 INTERRUPTS module interrupt status registers */
 +static const u8 __initconst twl4030_interrupts_isr_regs[] = {
 +      TWL4030_INTERRUPTS_BCIISR1A,
 +      TWL4030_INTERRUPTS_BCIISR1B,
 +      TWL4030_INTERRUPTS_BCIISR2A,
 +      TWL4030_INTERRUPTS_BCIISR2B,
 +};
 +
 +/* TWL4030 MADC module interrupt mask registers */
 +static const u8 __initconst twl4030_madc_imr_regs[] = {
 +      TWL4030_MADC_IMR1,
 +      TWL4030_MADC_IMR2,
 +};
 +
 +/* TWL4030 MADC module interrupt status registers */
 +static const u8 __initconst twl4030_madc_isr_regs[] = {
 +      TWL4030_MADC_ISR1,
 +      TWL4030_MADC_ISR2,
 +};
 +
 +/* TWL4030 keypad module interrupt mask registers */
 +static const u8 __initconst twl4030_keypad_imr_regs[] = {
 +      TWL4030_KEYPAD_KEYP_IMR1,
 +      TWL4030_KEYPAD_KEYP_IMR2,
 +};
 +
 +/* TWL4030 keypad module interrupt status registers */
 +static const u8 __initconst twl4030_keypad_isr_regs[] = {
 +      TWL4030_KEYPAD_KEYP_ISR1,
 +      TWL4030_KEYPAD_KEYP_ISR2,
 +};
 +
 +/* TWL4030 GPIO module interrupt mask registers */
 +static const u8 __initconst twl4030_gpio_imr_regs[] = {
 +      REG_GPIO_IMR1A,
 +      REG_GPIO_IMR1B,
 +      REG_GPIO_IMR2A,
 +      REG_GPIO_IMR2B,
 +      REG_GPIO_IMR3A,
 +      REG_GPIO_IMR3B,
 +};
 +
 +/* TWL4030 GPIO module interrupt status registers */
 +static const u8 __initconst twl4030_gpio_isr_regs[] = {
 +      REG_GPIO_ISR1A,
 +      REG_GPIO_ISR1B,
 +      REG_GPIO_ISR2A,
 +      REG_GPIO_ISR2B,
 +      REG_GPIO_ISR3A,
 +      REG_GPIO_ISR3B,
 +};
 +
 +/* TWL4030 modules that have IMR/ISR registers that must be masked/cleared */
 +static const struct twl4030_mod_iregs __initconst twl4030_mod_regs[] = {
 +      {
 +              .mod_no   = TWL4030_MODULE_INT,
 +              .sih_ctrl = TWL4030_INT_PWR_SIH_CTRL,
 +              .reg_cnt  = ARRAY_SIZE(twl4030_int_imr_regs),
 +              .imrs     = twl4030_int_imr_regs,
 +              .isrs     = twl4030_int_isr_regs,
 +      },
 +      {
 +              .mod_no   = TWL4030_MODULE_INTERRUPTS,
 +              .sih_ctrl = TWL4030_INTERRUPTS_BCISIHCTRL,
 +              .reg_cnt  = ARRAY_SIZE(twl4030_interrupts_imr_regs),
 +              .imrs     = twl4030_interrupts_imr_regs,
 +              .isrs     = twl4030_interrupts_isr_regs,
 +      },
 +      {
 +              .mod_no   = TWL4030_MODULE_MADC,
 +              .sih_ctrl = TWL4030_MADC_MADC_SIH_CTRL,
 +              .reg_cnt  = ARRAY_SIZE(twl4030_madc_imr_regs),
 +              .imrs     = twl4030_madc_imr_regs,
 +              .isrs     = twl4030_madc_isr_regs,
 +      },
 +      {
 +              .mod_no   = TWL4030_MODULE_KEYPAD,
 +              .sih_ctrl = TWL4030_KEYPAD_KEYP_SIH_CTRL,
 +              .reg_cnt  = ARRAY_SIZE(twl4030_keypad_imr_regs),
 +              .imrs     = twl4030_keypad_imr_regs,
 +              .isrs     = twl4030_keypad_isr_regs,
 +      },
 +      {
 +              .mod_no   = TWL4030_MODULE_GPIO,
 +              .sih_ctrl = REG_GPIO_SIH_CTRL,
 +              .reg_cnt  = ARRAY_SIZE(twl4030_gpio_imr_regs),
 +              .imrs     = twl4030_gpio_imr_regs,
 +              .isrs     = twl4030_gpio_isr_regs,
 +      },
 +};
 +
 +
 +/* Helper functions */
 +static int
 +twl4030_detect_client(struct i2c_adapter *adapter, unsigned char sid);
 +static int twl4030_attach_adapter(struct i2c_adapter *adapter);
 +static int twl4030_detach_client(struct i2c_client *client);
 +static void do_twl4030_irq(unsigned int irq, irq_desc_t *desc);
 +
 +static void twl_init_irq(void);
 +
 +/* Data Structures */
 +/* To have info on T2 IRQ substem activated or not */
 +static unsigned char twl_irq_used = FREE;
 +static struct completion irq_event;
 +
 +/* Structure to define on TWL4030 Slave ID */
 +struct twl4030_client {
 +      struct i2c_client client;
 +      const char client_name[sizeof(TWL_CLIENT_STRING) + 1];
 +      const unsigned char address;
 +      const char adapter_index;
 +      unsigned char inuse;
 +
 +      /* max numb of i2c_msg required is for read =2 */
 +      struct i2c_msg xfer_msg[2];
 +
 +      /* To lock access to xfer_msg */
 +      struct mutex xfer_lock;
 +};
 +
 +/* Module Mapping */
 +struct twl4030mapping {
 +      unsigned char sid;      /* Slave ID */
 +      unsigned char base;     /* base address */
 +};
 +
 +/* mapping the module id to slave id and base address */
 +static struct twl4030mapping twl4030_map[TWL4030_MODULE_LAST + 1] = {
 +      { TWL4030_SLAVENUM_NUM0, TWL4030_BASEADD_USB },
 +      { TWL4030_SLAVENUM_NUM1, TWL4030_BASEADD_AUDIO_VOICE },
 +      { TWL4030_SLAVENUM_NUM1, TWL4030_BASEADD_GPIO },
 +      { TWL4030_SLAVENUM_NUM1, TWL4030_BASEADD_INTBR },
 +      { TWL4030_SLAVENUM_NUM1, TWL4030_BASEADD_PIH },
 +      { TWL4030_SLAVENUM_NUM1, TWL4030_BASEADD_TEST },
 +      { TWL4030_SLAVENUM_NUM2, TWL4030_BASEADD_KEYPAD },
 +      { TWL4030_SLAVENUM_NUM2, TWL4030_BASEADD_MADC },
 +      { TWL4030_SLAVENUM_NUM2, TWL4030_BASEADD_INTERRUPTS },
 +      { TWL4030_SLAVENUM_NUM2, TWL4030_BASEADD_LED },
 +      { TWL4030_SLAVENUM_NUM2, TWL4030_BASEADD_MAIN_CHARGE },
 +      { TWL4030_SLAVENUM_NUM2, TWL4030_BASEADD_PRECHARGE },
 +      { TWL4030_SLAVENUM_NUM2, TWL4030_BASEADD_PWM0 },
 +      { TWL4030_SLAVENUM_NUM2, TWL4030_BASEADD_PWM1 },
 +      { TWL4030_SLAVENUM_NUM2, TWL4030_BASEADD_PWMA },
 +      { TWL4030_SLAVENUM_NUM2, TWL4030_BASEADD_PWMB },
 +      { TWL4030_SLAVENUM_NUM3, TWL4030_BASEADD_BACKUP },
 +      { TWL4030_SLAVENUM_NUM3, TWL4030_BASEADD_INT },
 +      { TWL4030_SLAVENUM_NUM3, TWL4030_BASEADD_PM_MASTER },
 +      { TWL4030_SLAVENUM_NUM3, TWL4030_BASEADD_PM_RECEIVER },
 +      { TWL4030_SLAVENUM_NUM3, TWL4030_BASEADD_RTC },
 +      { TWL4030_SLAVENUM_NUM3, TWL4030_BASEADD_SECURED_REG },
 +};
 +
 +static struct twl4030_client twl4030_modules[TWL4030_NUM_SLAVES] = {
 +      {
 +              .address        = TWL4030_SLAVEID_ID0,
 +              .client_name    = TWL_CLIENT_STRING "0",
 +              .adapter_index  = CONFIG_I2C_TWL4030_ID,
 +      },
 +      {
 +              .address        = TWL4030_SLAVEID_ID1,
 +              .client_name    = TWL_CLIENT_STRING "1",
 +              .adapter_index  = CONFIG_I2C_TWL4030_ID,
 +      },
 +      {
 +              .address        = TWL4030_SLAVEID_ID2,
 +              .client_name    = TWL_CLIENT_STRING "2",
 +              .adapter_index  = CONFIG_I2C_TWL4030_ID,
 +      },
 +      {
 +              .address        = TWL4030_SLAVEID_ID3,
 +              .client_name    = TWL_CLIENT_STRING "3",
 +              .adapter_index  = CONFIG_I2C_TWL4030_ID,
 +      },
 +};
 +
 +/* One Client Driver , 4 Clients */
 +static struct i2c_driver twl4030_driver = {
 +      .driver = {
 +              .name   = DRIVER_NAME,
 +              .owner  = THIS_MODULE,
 +      },
 +      .attach_adapter = twl4030_attach_adapter,
 +      .detach_client  = twl4030_detach_client,
 +};
 +
 +/*
 + * TWL4030 doesn't have PIH mask, hence dummy function for mask
 + * and unmask.
 + */
 +
 +static void twl4030_i2c_ackirq(unsigned int irq) {}
 +static void twl4030_i2c_disableint(unsigned int irq) {}
 +static void twl4030_i2c_enableint(unsigned int irq) {}
 +
 +/* information for processing in the Work Item */
 +static struct irq_chip twl4030_irq_chip = {
 +      .name   = "twl4030",
 +      .ack    = twl4030_i2c_ackirq,
 +      .mask   = twl4030_i2c_disableint,
 +      .unmask = twl4030_i2c_enableint,
 +};
 +
 +/* Global Functions */
 +
 +/**
 + * twl4030_i2c_write - Writes a n bit register in TWL4030
 + * @mod_no: module number
 + * @value: an array of num_bytes+1 containing data to write
 + * @reg: register address (just offset will do)
 + * @num_bytes: number of bytes to transfer
 + *
 + * IMPORTANT: for 'value' parameter: Allocate value num_bytes+1 and
 + * valid data starts at Offset 1.
 + *
 + * Returns the result of operation - 0 is success
 + */
 +int twl4030_i2c_write(u8 mod_no, u8 *value, u8 reg, u8 num_bytes)
 +{
 +      int ret;
 +      int sid;
 +      struct twl4030_client *twl;
 +      struct i2c_msg *msg;
 +
 +      if (unlikely(mod_no > TWL4030_MODULE_LAST)) {
 +              pr_err("Invalid module Number\n");
 +              return -EPERM;
 +      }
 +      sid = twl4030_map[mod_no].sid;
 +      twl = &twl4030_modules[sid];
 +
 +      if (unlikely(twl->inuse != TWL_CLIENT_USED)) {
 +              pr_err("I2C Client[%d] is not initialized[%d]\n",
 +                     sid, __LINE__);
 +              return -EPERM;
 +      }
 +      mutex_lock(&twl->xfer_lock);
 +      /*
 +       * [MSG1]: fill the register address data
 +       * fill the data Tx buffer
 +       */
 +      msg = &twl->xfer_msg[0];
 +      msg->addr = twl->address;
 +      msg->len = num_bytes + 1;
 +      msg->flags = 0;
 +      msg->buf = value;
 +      /* over write the first byte of buffer with the register address */
 +      *value = twl4030_map[mod_no].base + reg;
 +      ret = i2c_transfer(twl->client.adapter, twl->xfer_msg, 1);
 +      mutex_unlock(&twl->xfer_lock);
 +
 +      /* i2cTransfer returns num messages.translate it pls.. */
 +      if (ret >= 0)
 +              ret = 0;
 +      return ret;
 +}
 +EXPORT_SYMBOL(twl4030_i2c_write);
 +
 +/**
 + * twl4030_i2c_read - Reads a n bit register in TWL4030
 + * @mod_no: module number
 + * @value: an array of num_bytes containing data to be read
 + * @reg: register address (just offset will do)
 + * @num_bytes: number of bytes to transfer
 + *
 + * Returns result of operation - num_bytes is success else failure.
 + */
 +int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, u8 num_bytes)
 +{
 +      int ret;
 +      u8 val;
 +      int sid;
 +      struct twl4030_client *twl;
 +      struct i2c_msg *msg;
 +
 +      if (unlikely(mod_no > TWL4030_MODULE_LAST)) {
 +              pr_err("Invalid module Number\n");
 +              return -EPERM;
 +      }
 +      sid = twl4030_map[mod_no].sid;
 +      twl = &twl4030_modules[sid];
 +
 +      if (unlikely(twl->inuse != TWL_CLIENT_USED)) {
 +              pr_err("I2C Client[%d] is not initialized[%d]\n", sid,
 +                     __LINE__);
 +              return -EPERM;
 +      }
 +      mutex_lock(&twl->xfer_lock);
 +      /* [MSG1] fill the register address data */
 +      msg = &twl->xfer_msg[0];
 +      msg->addr = twl->address;
 +      msg->len = 1;
 +      msg->flags = 0; /* Read the register value */
 +      val = twl4030_map[mod_no].base + reg;
 +      msg->buf = &val;
 +      /* [MSG2] fill the data rx buffer */
 +      msg = &twl->xfer_msg[1];
 +      msg->addr = twl->address;
 +      msg->flags = I2C_M_RD;  /* Read the register value */
 +      msg->len = num_bytes;   /* only n bytes */
 +      msg->buf = value;
 +      ret = i2c_transfer(twl->client.adapter, twl->xfer_msg, 2);
 +      mutex_unlock(&twl->xfer_lock);
 +
 +      /* i2cTransfer returns num messages.translate it pls.. */
 +      if (ret >= 0)
 +              ret = 0;
 +      return ret;
 +}
 +EXPORT_SYMBOL(twl4030_i2c_read);
 +
 +/**
 + * twl4030_i2c_write_u8 - Writes a 8 bit register in TWL4030
 + * @mod_no: module number
 + * @value: the value to be written 8 bit
 + * @reg: register address (just offset will do)
 + *
 + * Returns result of operation - 0 is success
 + */
 +int twl4030_i2c_write_u8(u8 mod_no, u8 value, u8 reg)
 +{
 +
 +      /* 2 bytes offset 1 contains the data offset 0 is used by i2c_write */
 +      u8 temp_buffer[2] = { 0 };
 +      /* offset 1 contains the data */
 +      temp_buffer[1] = value;
 +      return twl4030_i2c_write(mod_no, temp_buffer, reg, 1);
 +}
 +EXPORT_SYMBOL(twl4030_i2c_write_u8);
 +
 +/**
 + * twl4030_i2c_read_u8 - Reads a 8 bit register from TWL4030
 + * @mod_no: module number
 + * @value: the value read 8 bit
 + * @reg: register address (just offset will do)
 + *
 + * Returns result of operation - 0 is success
 + */
 +int twl4030_i2c_read_u8(u8 mod_no, u8 *value, u8 reg)
 +{
 +      return twl4030_i2c_read(mod_no, value, reg, 1);
 +}
 +EXPORT_SYMBOL(twl4030_i2c_read_u8);
 +
 +/* Helper Functions */
 +
 +/*
 + * do_twl4030_module_irq() is the desc->handle method for each of the twl4030
 + * module interrupts.  It executes in kernel thread context.
 + * On entry, cpu interrupts are disabled.
 + */
 +static void do_twl4030_module_irq(unsigned int irq, irq_desc_t *desc)
 +{
 +      struct irqaction *action;
 +      const unsigned int cpu = smp_processor_id();
 +
 +      /*
 +       * Earlier this was desc->triggered = 1;
 +       */
 +      desc->status |= IRQ_LEVEL;
 +
 +      /*
 +       * The desc->handle method would normally call the desc->chip->ack
 +       * method here, but we won't bother since our ack method is NULL.
 +       */
 +
 +      if (!desc->depth) {
 +              kstat_cpu(cpu).irqs[irq]++;
 +
 +              action = desc->action;
 +              if (action) {
 +                      int ret;
 +                      int status = 0;
 +                      int retval = 0;
 +
 +                      local_irq_enable();
 +
 +                      do {
 +                              /* Call the ISR with cpu interrupts enabled */
 +                              ret = action->handler(irq, action->dev_id);
 +                              if (ret == IRQ_HANDLED)
 +                                      status |= action->flags;
 +                              retval |= ret;
 +                              action = action->next;
 +                      } while (action);
 +
 +                      if (status & IRQF_SAMPLE_RANDOM)
 +                              add_interrupt_randomness(irq);
 +
 +                      local_irq_disable();
 +
 +                      if (retval != IRQ_HANDLED)
 +                              printk(KERN_ERR "ISR for TWL4030 module"
 +                                      " irq %d can't handle interrupt\n",
 +                                      irq);
 +
 +                      /*
 +                       * Here is where we should call the unmask method, but
 +                       * again we won't bother since it is NULL.
 +                       */
 +              } else
 +                      printk(KERN_CRIT "TWL4030 module irq %d has no ISR"
 +                                      " but can't be masked!\n", irq);
 +      } else
 +              printk(KERN_CRIT "TWL4030 module irq %d is disabled but can't"
 +                              " be masked!\n", irq);
 +}
 +
 +/*
 + * twl4030_irq_thread() runs as a kernel thread.  It queries the twl4030
 + * interrupt controller to see which modules are generating interrupt requests
 + * and then calls the desc->handle method for each module requesting service.
 + */
 +static int twl4030_irq_thread(void *data)
 +{
 +      int irq = (int)data;
 +      irq_desc_t *desc = irq_desc + irq;
 +      static unsigned i2c_errors;
 +      const static unsigned max_i2c_errors = 100;
 +
 +      daemonize("twl4030-irq");
 +      current->flags |= PF_NOFREEZE;
 +
 +      while (!kthread_should_stop()) {
 +              int ret;
 +              int module_irq;
 +              u8 pih_isr;
 +
 +              wait_for_completion_interruptible(&irq_event);
 +
 +              ret = twl4030_i2c_read_u8(TWL4030_MODULE_PIH, &pih_isr,
 +                                        REG_PIH_ISR_P1);
 +              if (ret) {
 +                      printk(KERN_WARNING "I2C error %d while reading TWL4030"
 +                                      " PIH ISR register.\n", ret);
 +                      if (++i2c_errors >= max_i2c_errors) {
 +                              printk(KERN_ERR "Maximum I2C error count"
 +                                              " exceeded.  Terminating %s.\n",
 +                                              __func__);
 +                              break;
 +                      }
 +                      continue;
 +              }
 +
 +              for (module_irq = TWL4030_IRQ_BASE; 0 != pih_isr;
 +                       pih_isr >>= 1, module_irq++) {
 +                      if (pih_isr & 0x1) {
 +                              irq_desc_t *d = irq_desc + module_irq;
 +
 +                              local_irq_disable();
 +
 +                              d->handle_irq(module_irq, d);
 +
 +                              local_irq_enable();
 +                      }
 +              }
 +
 +              desc->chip->unmask(irq);
 +      }
 +
 +      return 0;
 +}
 +
 +/*
 + * do_twl4030_irq() is the desc->handle method for the twl4030 interrupt.
 + * This is a chained interrupt, so there is no desc->action method for it.
 + * Now we need to query the interrupt controller in the twl4030 to determine
 + * which module is generating the interrupt request.  However, we can't do i2c
 + * transactions in interrupt context, so we must defer that work to a kernel
 + * thread.  All we do here is acknowledge and mask the interrupt and wakeup
 + * the kernel thread.
 + */
 +static void do_twl4030_irq(unsigned int irq, irq_desc_t *desc)
 +{
 +      const unsigned int cpu = smp_processor_id();
 +
 +      /*
 +       * Earlier this was desc->triggered = 1;
 +       */
 +      desc->status |= IRQ_LEVEL;
 +
 +      /*
 +       * Acknowledge, clear _AND_ disable the interrupt.
 +       */
 +      desc->chip->ack(irq);
 +
 +      if (!desc->depth) {
 +              kstat_cpu(cpu).irqs[irq]++;
 +
 +              complete(&irq_event);
 +      }
 +}
 +
 +/* attach a client to the adapter */
 +static int __init twl4030_detect_client(struct i2c_adapter *adapter,
 +                                      unsigned char sid)
 +{
 +      int err = 0;
 +      struct twl4030_client *twl;
 +
 +      if (unlikely(sid >= TWL4030_NUM_SLAVES)) {
 +              pr_err("sid[%d] > MOD_LAST[%d]\n", sid, TWL4030_NUM_SLAVES);
 +              return -EPERM;
 +      }
 +
 +      /* Check basic functionality */
 +      err = i2c_check_functionality(adapter,
 +                      I2C_FUNC_SMBUS_WORD_DATA
 +                      | I2C_FUNC_SMBUS_WRITE_BYTE);
 +      if (!err) {
 +              pr_err("SlaveID=%d functionality check failed\n", sid);
 +              return err;
 +      }
 +      twl = &twl4030_modules[sid];
 +      if (unlikely(twl->inuse)) {
 +              pr_err("Client %s is already in use\n", twl->client_name);
 +              return -EPERM;
 +      }
 +
 +      memset(&twl->client, 0, sizeof(struct i2c_client));
 +
 +      twl->client.addr        = twl->address;
 +      twl->client.adapter     = adapter;
 +      twl->client.driver      = &twl4030_driver;
 +
 +      memcpy(&twl->client.name, twl->client_name,
 +                      sizeof(TWL_CLIENT_STRING) + 1);
 +
 +      pr_info("TWL4030: TRY attach Slave %s on Adapter %s [%x]\n",
 +                              twl->client_name, adapter->name, err);
 +
 +      err = i2c_attach_client(&twl->client);
 +      if (err) {
 +              pr_err("Couldn't attach Slave %s on Adapter"
 +                     "%s [%x]\n", twl->client_name, adapter->name, err);
 +      } else {
 +              twl->inuse = TWL_CLIENT_USED;
 +              mutex_init(&twl->xfer_lock);
 +      }
 +
 +      return err;
 +}
 +
 +/* adapter callback */
 +static int __init twl4030_attach_adapter(struct i2c_adapter *adapter)
 +{
 +      int i;
 +      int ret = 0;
 +      static int twl_i2c_adapter = 1;
 +
 +      for (i = 0; i < TWL4030_NUM_SLAVES; i++) {
 +              /* Check if I need to hook on to this adapter or not */
 +              if (twl4030_modules[i].adapter_index == twl_i2c_adapter) {
 +                      ret = twl4030_detect_client(adapter, i);
 +                      if (ret)
 +                              goto free_client;
 +              }
 +      }
 +      twl_i2c_adapter++;
 +
 +      /*
 +       * Check if the PIH module is initialized, if yes, then init
 +       * the T2 Interrupt subsystem
 +       */
 +      if ((twl4030_modules[twl4030_map[TWL4030_MODULE_PIH].sid].inuse ==
 +              TWL_CLIENT_USED) && (twl_irq_used != USED)) {
 +              twl_init_irq();
 +              twl_irq_used = USED;
 +      }
 +      return 0;
 +
 +free_client:
 +      pr_err("TWL_CLIENT(Idx=%d] registration failed[0x%x]\n", i, ret);
 +
 +      /* ignore current slave..it never got registered */
 +      i--;
 +      while (i >= 0) {
 +              /* now remove all those from the current adapter... */
 +              if (twl4030_modules[i].adapter_index == twl_i2c_adapter)
 +                      (void)twl4030_detach_client(&twl4030_modules[i].client);
 +              i--;
 +      }
 +      return ret;
 +}
 +
 +/* adapter's callback */
 +static int twl4030_detach_client(struct i2c_client *client)
 +{
 +      int err;
 +      err = i2c_detach_client(client);
 +      if (err) {
 +              pr_err("Client detach failed\n");
 +              return err;
 +      }
 +      return 0;
 +}
 +
 +static struct task_struct * __init start_twl4030_irq_thread(int irq)
 +{
 +      struct task_struct *thread;
 +
 +      init_completion(&irq_event);
 +      thread = kthread_run(twl4030_irq_thread, (void *)irq,
 +                           "twl4030 irq %d", irq);
 +      if (!thread)
 +              pr_err("%s: could not create twl4030 irq %d thread!\n",
 +                     __func__, irq);
 +
 +      return thread;
 +}
 +
 +/*
 + * These three functions should be part of Voltage frame work
 + * added here to complete the functionality for now.
 + */
 +static int __init protect_pm_master(void)
 +{
 +      int e = 0;
 +
 +      e = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_LOCK,
 +                      R_PROTECT_KEY);
 +      return e;
 +}
 +
 +static int __init unprotect_pm_master(void)
 +{
 +      int e = 0;
 +
 +      e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_UNLOCK1,
 +                      R_PROTECT_KEY);
 +      e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_UNLOCK2,
 +                      R_PROTECT_KEY);
 +      return e;
 +}
 +
 +static int __init power_companion_init(void)
 +{
 +      struct clk *osc;
 +      u32 rate;
 +      u8 ctrl = HFCLK_FREQ_26_MHZ;
 +      int e = 0;
 +
 +      if (cpu_is_omap2430())
 +              osc = clk_get(NULL, "osc_ck");
 +      else
 +              osc = clk_get(NULL, "osc_sys_ck");
 +      if (IS_ERR(osc)) {
 +              printk(KERN_WARNING "Skipping twl3040 internal clock init and "
 +                              "using bootloader value (unknown osc rate)\n");
 +              return 0;
 +      }
 +
 +      rate = clk_get_rate(osc);
 +      clk_put(osc);
 +
 +      switch (rate) {
 +      case 19200000 : ctrl = HFCLK_FREQ_19p2_MHZ; break;
 +      case 26000000 : ctrl = HFCLK_FREQ_26_MHZ; break;
 +      case 38400000 : ctrl = HFCLK_FREQ_38p4_MHZ; break;
 +      }
 +
 +      ctrl |= HIGH_PERF_SQ;
 +      e |= unprotect_pm_master();
 +      /* effect->MADC+USB ck en */
 +      e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, ctrl, R_CFG_BOOT);
 +      e |= protect_pm_master();
 +
 +      return e;
 +}
 +
 +/**
 + * twl4030_i2c_clear_isr - clear TWL4030 SIH ISR regs via read + write
 + * @mod_no: TWL4030 module number
 + * @reg: register index to clear
 + * @cor: value of the <module>_SIH_CTRL.COR bit (1 or 0)
 + *
 + * Either reads (cor == 1) or writes (cor == 0) to a TWL4030 interrupt
 + * status register to ensure that any prior interrupts are cleared.
 + * Returns the status from the I2C read operation.
 + */
 +static int __init twl4030_i2c_clear_isr(u8 mod_no, u8 reg, u8 cor)
 +{
 +      u8 tmp;
 +
 +      return (cor) ? twl4030_i2c_read_u8(mod_no, &tmp, reg) :
 +              twl4030_i2c_write_u8(mod_no, 0xff, reg);
 +}
 +
 +/**
 + * twl4030_read_cor_bit - are TWL module ISRs cleared by reads or writes?
 + * @mod_no: TWL4030 module number
 + * @reg: register index to clear
 + *
 + * Returns 1 if the TWL4030 SIH interrupt status registers (ISRs) for
 + * the specified TWL module are cleared by reads, or 0 if cleared by
 + * writes.
 + */
 +static int twl4030_read_cor_bit(u8 mod_no, u8 reg)
 +{
 +      u8 tmp = 0;
 +
 +      WARN_ON(twl4030_i2c_read_u8(mod_no, &tmp, reg) < 0);
 +
 +      tmp &= TWL4030_SIH_CTRL_COR_MASK;
 +      tmp >>= __ffs(TWL4030_SIH_CTRL_COR_MASK);
 +
 +      return tmp;
 +}
 +
 +/**
 + * twl4030_mask_clear_intrs - mask and clear all TWL4030 interrupts
 + * @t: pointer to twl4030_mod_iregs array
 + * @t_sz: ARRAY_SIZE(t) (starting at 1)
 + *
 + * Mask all TWL4030 interrupt mask registers (IMRs) and clear all
 + * interrupt status registers (ISRs).  No return value, but will WARN if
 + * any I2C operations fail.
 + */
 +static void __init twl4030_mask_clear_intrs(const struct twl4030_mod_iregs *t,
 +                                          const u8 t_sz)
 +{
 +      int i, j;
 +
 +      /*
 +       * N.B. - further efficiency is possible here.  Eight I2C
 +       * operations on BCI and GPIO modules are avoidable if I2C
 +       * burst read/write transactions were implemented.  Would
 +       * probably save about 1ms of boot time and a small amount of
 +       * power.
 +       */
 +      for (i = 0; i < t_sz; i++) {
 +              const struct twl4030_mod_iregs tmr = t[i];
 +              int cor;
 +
 +              /* Are ISRs cleared by reads or writes? */
 +              cor = twl4030_read_cor_bit(tmr.mod_no, tmr.sih_ctrl);
 +              WARN_ON(cor < 0);
 +
 +              for (j = 0; j < tmr.reg_cnt; j++) {
 +
 +                      /* Mask interrupts at the TWL4030 */
 +                      WARN_ON(twl4030_i2c_write_u8(tmr.mod_no, 0xff,
 +                                                   tmr.imrs[j]) < 0);
 +
 +                      /* Clear TWL4030 ISRs */
 +                      WARN_ON(twl4030_i2c_clear_isr(tmr.mod_no,
 +                                                    tmr.isrs[j], cor) < 0);
 +              }
 +      }
 +
 +      return;
 +}
 +
 +
 +static void twl_init_irq(void)
 +{
 +      int     i;
 +      int     res = 0;
 +      char    *msg = "Unable to register interrupt subsystem";
 +      unsigned int irq_num;
 +
 +      /*
 +       * Mask and clear all TWL4030 interrupts since initially we do
 +       * not have any TWL4030 module interrupt handlers present
 +       */
 +      twl4030_mask_clear_intrs(twl4030_mod_regs,
 +                               ARRAY_SIZE(twl4030_mod_regs));
 +
 +      /* install an irq handler for each of the PIH modules */
 +      for (i = TWL4030_IRQ_BASE; i < TWL4030_IRQ_END; i++) {
 +              set_irq_chip(i, &twl4030_irq_chip);
 +              set_irq_handler(i, do_twl4030_module_irq);
 +              set_irq_flags(i, IRQF_VALID);
 +      }
 +
 +      irq_num = (cpu_is_omap2430()) ? INT_24XX_SYS_NIRQ : INT_34XX_SYS_NIRQ;
 +
 +      /* install an irq handler to demultiplex the TWL4030 interrupt */
 +      set_irq_data(irq_num, start_twl4030_irq_thread(irq_num));
++      set_irq_type(irq_num, IRQ_TYPE_EDGE_FALLING);
 +      set_irq_chained_handler(irq_num, do_twl4030_irq);
 +
 +      res = power_companion_init();
 +      if (res < 0)
 +              pr_err("%s[%d][%d]\n", msg, res, __LINE__);
 +}
 +
 +static int __init twl4030_init(void)
 +{
 +      return i2c_add_driver(&twl4030_driver);
 +}
 +
 +static void __exit twl4030_exit(void)
 +{
 +      i2c_del_driver(&twl4030_driver);
 +      twl_irq_used = FREE;
 +}
 +
 +subsys_initcall(twl4030_init);
 +module_exit(twl4030_exit);
 +
 +MODULE_ALIAS("i2c:" DRIVER_NAME);
 +MODULE_AUTHOR("Texas Instruments, Inc.");
 +MODULE_DESCRIPTION("I2C Core interface for TWL4030");
 +MODULE_LICENSE("GPL");
index 58669f93f73dd28f7b64f78bd0559816d1016478,0000000000000000000000000000000000000000..a974a5fdc2e67a17f7efde09bb7e7b0b2c2779c3
mode 100644,000000..100644
--- /dev/null
@@@ -1,475 -1,0 +1,475 @@@
-       set_irq_type(kp->irq, IRQT_FALLING);
 +/*
 + * TSC2301 keypad driver
 + *
 + * Copyright (C) 2005-2006 Nokia Corporation
 + *
 + * Written by Jarkko Oikarinen
 + * Rewritten by Juha Yrjola <juha.yrjola@nokia.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.
 + *
 + * 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/module.h>
 +#include <linux/input.h>
 +#include <linux/interrupt.h>
 +#include <linux/irq.h>
 +#include <linux/delay.h>
 +#include <linux/spi/spi.h>
 +
 +#include <linux/spi/tsc2301.h>
 +
 +#define TSC2301_KEYBOARD_PRODUCT_ID      0x0051
 +#define TSC2301_KEYBOARD_PRODUCT_VERSION 0x0001
 +#define TSC2301_DEBOUNCE_TIME_2MS        0x0000
 +#define TSC2301_DEBOUNCE_TIME_10MS       0x0800
 +#define TSC2301_DEBOUNCE_TIME_20MS       0x1000
 +#define TSC2301_DEBOUNCE_TIME_50MS       0x1800
 +#define TSC2301_DEBOUNCE_TIME_60MS       0x2000
 +#define TSC2301_DEBOUNCE_TIME_80MS       0x2800
 +#define TSC2301_DEBOUNCE_TIME_100MS      0x3000
 +#define TSC2301_DEBOUNCE_TIME_120MS      0x3800
 +
 +#define TSC2301_DEBOUNCE_TIME         TSC2301_DEBOUNCE_TIME_20MS
 +
 +#define TSC2301_RELEASE_TIMEOUT               50
 +
 +struct tsc2301_kp {
 +      struct input_dev        *idev;
 +      char                    phys[32];
 +      spinlock_t              lock;
 +      struct mutex            mutex;
 +      struct timer_list       timer;
 +      u16                     keys_pressed;
 +      unsigned                pending:1;
 +      unsigned                user_disabled:1;
 +      unsigned                disable_depth;
 +
 +      struct spi_transfer     read_xfer[4];
 +      struct spi_message      read_msg;
 +
 +      u16                     data;
 +      u16                     mask;
 +
 +      int                     irq;
 +      s16                     keymap[16];
 +};
 +
 +static inline int tsc2301_kp_disabled(struct tsc2301 *tsc)
 +{
 +      return tsc->kp->disable_depth != 0;
 +}
 +
 +static void tsc2301_kp_send_key_events(struct tsc2301 *tsc,
 +                                     u16 prev_state,
 +                                     u16 new_state)
 +{
 +      struct tsc2301_kp *kp = tsc->kp;
 +      u16 common, released, pressed;
 +      int i;
 +
 +      common = prev_state & new_state;
 +      released = common ^ prev_state;
 +      pressed = common ^ new_state;
 +      if (!released && !pressed)
 +              return;
 +      for (i = 0; i < 16 && (released || pressed); i++) {
 +              if (released & 1) {
 +                      dev_dbg(&tsc->spi->dev, "key %d released\n", i);
 +                      input_report_key(kp->idev, kp->keymap[i], 0);
 +              }
 +              released >>= 1;
 +              if (pressed & 1) {
 +                      dev_dbg(&tsc->spi->dev, "key %d pressed\n", i);
 +                      input_report_key(kp->idev, kp->keymap[i], 1);
 +              }
 +              pressed >>= 1;
 +      }
 +      input_sync(kp->idev);
 +}
 +
 +static inline void _filter_out(struct tsc2301 *tsc, u16 prev_state,
 +                             u16 *new_state, int row1, int row2, u8 rect_pat)
 +{
 +      u16 mask;
 +
 +      mask = (rect_pat << (row1 * 4)) | (rect_pat << (row2 * 4));
 +      mask &= ~prev_state;
 +      *new_state &= ~mask;
 +      dev_dbg(&tsc->spi->dev, "filtering ghost keys %02x\n", mask);
 +}
 +
 +static void tsc2301_filter_ghost_keys(struct tsc2301 *tsc, u16 prev_state,
 +                                    u16 *new_state)
 +{
 +      int row1, row2;
 +      u16 key_map;
 +      u16 row1_map;
 +      static const u8 rect_pat[] = {
 +              0x3, 0x5, 0x9, 0x6, 0xa, 0xc, 0,
 +      };
 +
 +      key_map = *new_state;
 +      for (row1 = 0; row1 < 4; row1++) {
 +              row1_map = (key_map >> (row1 * 4)) & 0xf;
 +              if (!row1_map)
 +                      continue;
 +              for (row2 = row1 + 1; row2 < 4; row2++) {
 +                      u16 rect_map = (key_map >> (row2 * 4)) & 0xf;
 +                      const u8 *rp;
 +
 +                      rect_map &= row1_map;
 +                      if (!rect_map)
 +                              continue;
 +                      for (rp = rect_pat; *rp; rp++)
 +                              if ((rect_map & *rp) == *rp)
 +                                      _filter_out(tsc, prev_state, new_state,
 +                                                  row1, row2, *rp);
 +              }
 +      }
 +}
 +
 +static void tsc2301_kp_timer(unsigned long arg)
 +{
 +      struct tsc2301 *tsc = (void *) arg;
 +      struct tsc2301_kp *kp = tsc->kp;
 +      unsigned long flags;
 +
 +      tsc2301_kp_send_key_events(tsc, kp->keys_pressed, 0);
 +      spin_lock_irqsave(&kp->lock, flags);
 +      kp->keys_pressed = 0;
 +      spin_unlock_irqrestore(&kp->lock, flags);
 +}
 +
 +static void tsc2301_kp_rx(void *arg)
 +{
 +      struct tsc2301 *tsc = arg;
 +      struct tsc2301_kp *kp = tsc->kp;
 +      unsigned long flags;
 +      u16 kp_data;
 +
 +      kp_data = kp->data;
 +      dev_dbg(&tsc->spi->dev, "KP data %04x\n", kp_data);
 +
 +      tsc2301_filter_ghost_keys(tsc, kp->keys_pressed, &kp_data);
 +      tsc2301_kp_send_key_events(tsc, kp->keys_pressed, kp_data);
 +      spin_lock_irqsave(&kp->lock, flags);
 +      kp->keys_pressed = kp_data;
 +      kp->pending = 0;
 +      spin_unlock_irqrestore(&kp->lock, flags);
 +}
 +
 +static irqreturn_t tsc2301_kp_irq_handler(int irq, void *dev_id)
 +{
 +      struct tsc2301 *tsc = dev_id;
 +      struct tsc2301_kp *kp = tsc->kp;
 +      unsigned long flags;
 +      int r;
 +
 +      spin_lock_irqsave(&kp->lock, flags);
 +      if (tsc2301_kp_disabled(tsc)) {
 +              spin_unlock_irqrestore(&kp->lock, flags);
 +              return IRQ_HANDLED;
 +      }
 +      kp->pending = 1;
 +      spin_unlock_irqrestore(&kp->lock, flags);
 +      mod_timer(&kp->timer,
 +               jiffies + msecs_to_jiffies(TSC2301_RELEASE_TIMEOUT));
 +      r = spi_async(tsc->spi, &tsc->kp->read_msg);
 +      if (r)
 +              dev_err(&tsc->spi->dev, "kp: spi_async() failed");
 +      return IRQ_HANDLED;
 +}
 +
 +static void tsc2301_kp_start_scan(struct tsc2301 *tsc)
 +{
 +      tsc2301_write_reg(tsc, TSC2301_REG_KPMASK, tsc->kp->mask);
 +      tsc2301_write_reg(tsc, TSC2301_REG_KEY, TSC2301_DEBOUNCE_TIME);
 +}
 +
 +static void tsc2301_kp_stop_scan(struct tsc2301 *tsc)
 +{
 +      tsc2301_write_reg(tsc, TSC2301_REG_KEY, 1 << 14);
 +}
 +
 +/* Must be called with the mutex held */
 +static void tsc2301_kp_enable(struct tsc2301 *tsc)
 +{
 +      struct tsc2301_kp *kp = tsc->kp;
 +      unsigned long flags;
 +
 +      spin_lock_irqsave(&kp->lock, flags);
 +      BUG_ON(!tsc2301_kp_disabled(tsc));
 +      if (--kp->disable_depth != 0) {
 +              spin_unlock_irqrestore(&kp->lock, flags);
 +              return;
 +      }
 +      spin_unlock_irqrestore(&kp->lock, flags);
 +
-       set_irq_type(kp->irq, IRQT_NOEDGE);
++      set_irq_type(kp->irq, IRQ_TYPE_EDGE_FALLING);
 +      tsc2301_kp_start_scan(tsc);
 +      enable_irq(kp->irq);
 +}
 +
 +/* Must be called with the mutex held */
 +static int tsc2301_kp_disable(struct tsc2301 *tsc, int release_keys)
 +{
 +      struct tsc2301_kp *kp = tsc->kp;
 +      unsigned long flags;
 +
 +      spin_lock_irqsave(&kp->lock, flags);
 +      if (kp->disable_depth++ != 0) {
 +              spin_unlock_irqrestore(&kp->lock, flags);
 +              goto out;
 +      }
 +      disable_irq_nosync(kp->irq);
-       set_irq_type(kp->irq, IRQT_FALLING);
++      set_irq_type(kp->irq, IRQ_TYPE_NONE);
 +      spin_unlock_irqrestore(&kp->lock, flags);
 +
 +      while (kp->pending) {
 +              msleep(1);
 +      }
 +
 +      tsc2301_kp_stop_scan(tsc);
 +out:
 +      if (!release_keys)
 +              del_timer(&kp->timer); /* let timeout release keys */
 +
 +      return 0;
 +}
 +
 +/* The following workaround is needed for a HW bug triggered by the
 + * following:
 + * 1. keep any key pressed
 + * 2. disable keypad
 + * 3. release all keys
 + * 4. reenable keypad
 + * 5. disable touch screen controller
 + *
 + * After this the keypad scanner will get stuck in busy state and won't
 + * report any interrupts for further keypresses. One way to recover is to
 + * restart the keypad scanner whenever we enable / disable the
 + * touchscreen controller.
 + */
 +void tsc2301_kp_restart(struct tsc2301 *tsc)
 +{
 +      if (!tsc2301_kp_disabled(tsc)) {
 +              tsc2301_kp_start_scan(tsc);
 +      }
 +}
 +
 +static ssize_t tsc2301_kp_disable_show(struct device *dev,
 +                                     struct device_attribute *attr, char *buf)
 +{
 +      struct tsc2301          *tsc = dev_get_drvdata(dev);
 +
 +      return sprintf(buf, "%u\n", tsc2301_kp_disabled(tsc) ? 1 : 0);
 +}
 +
 +static ssize_t tsc2301_kp_disable_store(struct device *dev,
 +                                      struct device_attribute *attr,
 +                                      const char *buf, size_t count)
 +{
 +      struct tsc2301          *tsc = dev_get_drvdata(dev);
 +      struct tsc2301_kp       *kp = tsc->kp;
 +      char *endp;
 +      int i;
 +
 +      i = simple_strtoul(buf, &endp, 10);
 +      i = i ? 1 : 0;
 +
 +      mutex_lock(&kp->mutex);
 +      if (i == kp->user_disabled) {
 +              mutex_unlock(&kp->mutex);
 +              return count;
 +      }
 +      kp->user_disabled = i;
 +
 +      if (i)
 +              tsc2301_kp_disable(tsc, 1);
 +      else
 +              tsc2301_kp_enable(tsc);
 +      mutex_unlock(&kp->mutex);
 +
 +      return count;
 +}
 +
 +static DEVICE_ATTR(disable_kp, 0664, tsc2301_kp_disable_show,
 +                 tsc2301_kp_disable_store);
 +
 +static const u16 tsc2301_kp_read_data = 0x8000 | TSC2301_REG_KPDATA;
 +
 +static void tsc2301_kp_setup_spi_xfer(struct tsc2301 *tsc)
 +{
 +      struct tsc2301_kp *kp = tsc->kp;
 +      struct spi_message *m = &kp->read_msg;
 +      struct spi_transfer *x = &kp->read_xfer[0];
 +
 +      spi_message_init(&kp->read_msg);
 +
 +      x->tx_buf = &tsc2301_kp_read_data;
 +      x->len = 2;
 +      spi_message_add_tail(x, m);
 +      x++;
 +
 +      x->rx_buf = &kp->data;
 +      x->len = 2;
 +      spi_message_add_tail(x, m);
 +
 +      m->complete = tsc2301_kp_rx;
 +      m->context = tsc;
 +}
 +
 +#ifdef CONFIG_PM
 +int tsc2301_kp_suspend(struct tsc2301 *tsc)
 +{
 +      struct tsc2301_kp *kp = tsc->kp;
 +
 +      mutex_lock(&kp->mutex);
 +      tsc2301_kp_disable(tsc, 1);
 +      mutex_unlock(&kp->mutex);
 +      return 0;
 +}
 +
 +void tsc2301_kp_resume(struct tsc2301 *tsc)
 +{
 +      struct tsc2301_kp *kp = tsc->kp;
 +
 +      mutex_lock(&kp->mutex);
 +      tsc2301_kp_enable(tsc);
 +      mutex_unlock(&kp->mutex);
 +}
 +#endif
 +
 +int __devinit tsc2301_kp_init(struct tsc2301 *tsc,
 +                            struct tsc2301_platform_data *pdata)
 +{
 +      struct input_dev *idev;
 +      struct tsc2301_kp *kp;
 +      int r, i;
 +      u16 mask;
 +
 +      if (pdata->keyb_int < 0) {
 +              dev_err(&tsc->spi->dev, "need kbirq");
 +              return -EINVAL;
 +      }
 +
 +      kp = kzalloc(sizeof(*kp), GFP_KERNEL);
 +      if (kp == NULL)
 +              return -ENOMEM;
 +      tsc->kp = kp;
 +
 +      kp->irq = pdata->keyb_int;
 +      spin_lock_init(&kp->lock);
 +      mutex_init(&kp->mutex);
 +
 +      init_timer(&kp->timer);
 +      kp->timer.data = (unsigned long) tsc;
 +      kp->timer.function = tsc2301_kp_timer;
 +
 +      idev = input_allocate_device();
 +      if (idev == NULL) {
 +              r = -ENOMEM;
 +              goto err1;
 +      }
 +      if (pdata->keyb_name)
 +              idev->name = pdata->keyb_name;
 +      else
 +              idev->name = "TSC2301 keypad";
 +      snprintf(kp->phys, sizeof(kp->phys), "%s/input-kp", tsc->spi->dev.bus_id);
 +      idev->phys = kp->phys;
 +
 +      mask = 0;
 +      idev->evbit[0] = BIT(EV_KEY);
 +      for (i = 0; i < 16; i++) {
 +              if (pdata->keymap[i] > 0) {
 +                      set_bit(pdata->keymap[i], idev->keybit);
 +                      kp->keymap[i] = pdata->keymap[i];
 +              } else {
 +                      kp->keymap[i] = -1;
 +                      mask |= 1 << i;
 +              }
 +      }
 +
 +      if (pdata->kp_rep)
 +              set_bit(EV_REP, idev->evbit);
 +
 +      kp->idev = idev;
 +
 +      tsc2301_kp_setup_spi_xfer(tsc);
 +
 +      r = device_create_file(&tsc->spi->dev, &dev_attr_disable_kp);
 +      if (r < 0)
 +              goto err2;
 +
 +      tsc2301_kp_start_scan(tsc);
 +
 +      /* IRQ mode 0 is faulty, it can cause the KBIRQ to get stuck.
 +       * Mode 2 deasserts the IRQ at:
 +       * - HW or SW reset
 +       * - Setting SCS flag in REG_KEY register
 +       * - Releasing all keys
 +       * - Reading the REG_KPDATA
 +       */
 +      tsc2301_write_kbc(tsc, 2);
 +
 +      tsc2301_write_reg(tsc, TSC2301_REG_KPMASK, mask);
 +      kp->mask = mask;
 +
++      set_irq_type(kp->irq, IRQ_TYPE_EDGE_FALLING);
 +
 +      r = request_irq(kp->irq, tsc2301_kp_irq_handler, IRQF_SAMPLE_RANDOM,
 +                      "tsc2301-kp", tsc);
 +      if (r < 0) {
 +              dev_err(&tsc->spi->dev, "unable to get kbirq IRQ");
 +              goto err3;
 +      }
 +      set_irq_wake(kp->irq, 1);
 +
 +      /* We need to read the register once..? */
 +      tsc2301_read_reg(tsc, TSC2301_REG_KPDATA);
 +
 +      r = input_register_device(idev);
 +      if (r < 0) {
 +              dev_err(&tsc->spi->dev, "can't register keypad device\n");
 +              goto err4;
 +      }
 +
 +      return 0;
 +
 +err4:
 +      free_irq(kp->irq, tsc);
 +err3:
 +      tsc2301_kp_stop_scan(tsc);
 +      device_remove_file(&tsc->spi->dev, &dev_attr_disable_kp);
 +err2:
 +      input_free_device(kp->idev);
 +err1:
 +      kfree(kp);
 +      return r;
 +}
 +
 +void __devexit tsc2301_kp_exit(struct tsc2301 *tsc)
 +{
 +      struct tsc2301_kp *kp = tsc->kp;
 +
 +      tsc2301_kp_disable(tsc, 1);
 +      input_unregister_device(kp->idev);
 +      free_irq(kp->irq, tsc);
 +      device_remove_file(&tsc->spi->dev, &dev_attr_disable_kp);
 +
 +      kfree(kp);
 +}
index 8b5fd6423897ad032e3d0a0376909c9760645774,6e60a97a234c108540d68ca9ddedf22167b4318e..f32361fac8704988dfdf24a1e9e33c98b82e2155
@@@ -103,6 -103,18 +103,18 @@@ config TOUCHSCREEN_MTOUC
          To compile this driver as a module, choose M here: the
          module will be called mtouch.
  
+ config TOUCHSCREEN_INEXIO
+       tristate "iNexio serial touchscreens"
+       select SERIO
+       help
+         Say Y here if you have an iNexio serial touchscreen connected to
+         your system.
+         If unsure, say N.
+         To compile this driver as a module, choose M here: the
+         module will be called inexio.
  config TOUCHSCREEN_MK712
        tristate "ICS MicroClock MK712 touchscreen"
        help
@@@ -134,6 -146,18 +146,18 @@@ config TOUCHSCREEN_HP7X
          To compile this driver as a module, choose M here: the
          module will be called jornada720_ts.
  
+ config TOUCHSCREEN_HTCPEN
+       tristate "HTC Shift X9500 touchscreen"
+       depends on ISA
+       help
+         Say Y here if you have an HTC Shift UMPC also known as HTC X9500
+         Clio / Shangrila and want to support the built-in touchscreen.
+         If unsure, say N.
+         To compile this driver as a module, choose M here: the
+         module will be called htcpen.
  config TOUCHSCREEN_PENMOUNT
        tristate "Penmount serial touchscreen"
        select SERIO
          To compile this driver as a module, choose M here: the
          module will be called penmount.
  
+ config TOUCHSCREEN_MIGOR
+       tristate "Renesas MIGO-R touchscreen"
+       depends on SH_MIGOR && I2C
+       help
+         Say Y here to enable MIGO-R touchscreen support.
+         If unsure, say N.
+         To compile this driver as a module, choose M here: the
+         module will be called migor_ts.
  config TOUCHSCREEN_TOUCHRIGHT
        tristate "Touchright serial touchscreen"
        select SERIO
@@@ -170,46 -205,18 +205,58 @@@ config TOUCHSCREEN_TOUCHWI
          To compile this driver as a module, choose M here: the
          module will be called touchwin.
  
+ config TOUCHSCREEN_ATMEL_TSADCC
+       tristate "Atmel Touchscreen Interface"
+       depends on ARCH_AT91SAM9RL
+       help
+         Say Y here if you have a 4-wire touchscreen connected to the
+           ADC Controller on your Atmel SoC (such as the AT91SAM9RL).
+         If unsure, say N.
+         To compile this driver as a module, choose M here: the
+         module will be called atmel_tsadcc.
 +config TOUCHSCREEN_TSC2005
 +      tristate "TSC2005 touchscreen support"
 +      help
 +        Say Y here for if you are using the touchscreen features of TSC2301.
 +
 +config TOUCHSCREEN_TSC2102
 +      tristate "TSC 2102 based touchscreens"
 +      depends on SPI_MASTER
 +      select SPI_TSC2102
 +      help
 +        Say Y here if you have a touchscreen interface using the
 +        TI TSC 2102 controller, and your board-specific initialization
 +        code includes that in its table of SPI devices.  Also make
 +        sure the proper SPI controller is selected.
 +
 +        If unsure, say N (but it's safe to say "Y").
 +
 +        To compile this driver as a module, choose M here: the
 +        module will be called tsc2102_ts.
 +
 +config TOUCHSCREEN_TSC210X
 +      tristate "TI TSC210x based touchscreens"
 +      depends on SPI_MASTER
 +      select SPI_TSC210X
 +      help
 +        Say Y here if you have a touchscreen interface using a
 +        TI TSC210x controller, and your board-specific initialisation
 +        code includes that in its table of SPI devices.
 +
 +        If unsure, say N (but it's safe to say "Y").
 +
 +        To compile this driver as a module, choose M here: the
 +        module will be called tsc210x_ts.
 +
 +config TOUCHSCREEN_TSC2301
 +      tristate "TSC2301 touchscreen support"
 +      depends on SPI_TSC2301
 +      help
 +        Say Y here for if you are using the touchscreen features of TSC2301.
 +
  config TOUCHSCREEN_UCB1400
        tristate "Philips UCB1400 touchscreen"
        select AC97_BUS
@@@ -356,4 -363,15 +403,15 @@@ config TOUCHSCREEN_USB_GOTO
        bool "GoTop Super_Q2/GogoPen/PenPower tablet device support" if EMBEDDED
        depends on TOUCHSCREEN_USB_COMPOSITE
  
+ config TOUCHSCREEN_TOUCHIT213
+       tristate "Sahara TouchIT-213 touchscreen"
+       select SERIO
+       help
+         Say Y here if you have a Sahara TouchIT-213 Tablet PC.
+         If unsure, say N.
+         To compile this driver as a module, choose M here: the
+         module will be called touchit213.
  endif
index f8f08a735c509f0fe8208c2bc9dc112bdd1a5dcc,15cf2907948952df00b961ad2f0d97407b4a2faa..0c31dfa3ac9c984dd7281b628801c2bab364d512
@@@ -7,25 -7,25 +7,30 @@@
  wm97xx-ts-y := wm97xx-core.o
  
  obj-$(CONFIG_TOUCHSCREEN_ADS7846)     += ads7846.o
+ obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC)        += atmel_tsadcc.o
  obj-$(CONFIG_TOUCHSCREEN_BITSY)               += h3600_ts_input.o
  obj-$(CONFIG_TOUCHSCREEN_CORGI)               += corgi_ts.o
  obj-$(CONFIG_TOUCHSCREEN_GUNZE)               += gunze.o
  obj-$(CONFIG_TOUCHSCREEN_ELO)         += elo.o
  obj-$(CONFIG_TOUCHSCREEN_FUJITSU)     += fujitsu_ts.o
+ obj-$(CONFIG_TOUCHSCREEN_INEXIO)      += inexio.o
+ obj-$(CONFIG_TOUCHSCREEN_MIGOR)               += migor_ts.o
  obj-$(CONFIG_TOUCHSCREEN_MTOUCH)      += mtouch.o
  obj-$(CONFIG_TOUCHSCREEN_MK712)               += mk712.o
  obj-$(CONFIG_TOUCHSCREEN_HP600)               += hp680_ts_input.o
  obj-$(CONFIG_TOUCHSCREEN_HP7XX)               += jornada720_ts.o
+ obj-$(CONFIG_TOUCHSCREEN_HTCPEN)      += htcpen.o
  obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE)       += usbtouchscreen.o
  obj-$(CONFIG_TOUCHSCREEN_PENMOUNT)    += penmount.o
+ obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213)  += touchit213.o
  obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT)  += touchright.o
  obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN)    += touchwin.o
  obj-$(CONFIG_TOUCHSCREEN_UCB1400)     += ucb1400_ts.o
 +obj-$(CONFIG_TOUCHSCREEN_TSC2005)     += tsc2005.o
 +obj-$(CONFIG_TOUCHSCREEN_TSC2102)     += tsc2102_ts.o
 +obj-$(CONFIG_TOUCHSCREEN_OMAP)        += omap/
 +obj-$(CONFIG_TOUCHSCREEN_TSC210X)     += tsc210x_ts.o
 +obj-$(CONFIG_TOUCHSCREEN_TSC2301)     += tsc2301_ts.o
  obj-$(CONFIG_TOUCHSCREEN_WM97XX)      += wm97xx-ts.o
  wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705)        += wm9705.o
  wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712)        += wm9712.o
index 99f4ece22aa4da641988cf6abb8b5cc330f0dae1,ce6f48c695f553a703a9c9af3c739996bc2c971c..cc1db125a14a5d0d6f0e9cb568ee43ebab9bd328
@@@ -517,7 -517,9 +517,9 @@@ static void ads7846_rx(void *ads
        if (x == MAX_12BIT)
                x = 0;
  
-       if (likely(x && z1)) {
+       if (ts->model == 7843) {
+               Rt = ts->pressure_max / 2;
+       } else if (likely(x && z1)) {
                /* compute touch pressure resistance using equation #2 */
                Rt = z2;
                Rt -= z1;
                Rt *= ts->x_plate_ohms;
                Rt /= z1;
                Rt = (Rt + 2047) >> 12;
-       } else
+       } 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
@@@ -633,19 -633,17 +633,17 @@@ 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;
+       val = be16_to_cpup((__be16 *)t->rx_buf) >> 3;
  
        action = ts->filter(ts->filter_data, ts->msg_idx, &val);
        switch (action) {
                m = ts->last_msg;
                break;
        case ADS7846_FILTER_OK:
-               *rx_val = val;
+               *(u16 *)t->rx_buf = val;
                ts->tc.ignore = 0;
                m = &ts->msg[++ts->msg_idx];
                break;
@@@ -828,15 -826,6 +826,15 @@@ static int __devinit ads7846_probe(stru
                return -ENODEV;
        }
  
 +      /* enable voltage */
 +      if (pdata->vaux_control != NULL) {
 +              err = pdata->vaux_control(VAUX_ENABLE);
 +              if (err != 0) {
 +                      dev_dbg(&spi->dev, "TS vaux enable failed\n");
 +                      return err;
 +              }
 +      }
 +
        /* don't exceed max specified sample rate */
        if (spi->max_speed_hz > (125000 * SAMPLE_BITS)) {
                dev_dbg(&spi->dev, "f(sample) %d KHz?\n",
diff --combined drivers/leds/Kconfig
index 328e6adb509cf3de2405b6373b75aa9825c8df3c,9556262dda5aabba7b6474eee2b4e2a3b1a31906..6a2f44153c748ee22cf28ccba9e24d15579d00c2
@@@ -77,27 -77,6 +77,27 @@@ config LEDS_WRA
        help
          This option enables support for the PCEngines WRAP programmable LEDs.
  
 +config LEDS_OMAP_DEBUG
 +      boolean "LED Support for OMAP debug board LEDs"
 +      depends on LEDS_CLASS=y && ARCH_OMAP
 +      help
 +        Enables support for the LEDs on the debug board used with OMAP
 +        reference boards like H2/H3/H4 and Perseus2.  Up to six of these
 +        may be claimed by the original ARM debug LED API.
 +
 +config LEDS_OMAP
 +      tristate "LED Support for OMAP GPIO LEDs"
 +      depends on LEDS_CLASS && ARCH_OMAP
 +      help
 +        This option enables support for the LEDs on OMAP processors.
 +
 +config LEDS_OMAP_PWM
 +      tristate "LED Support for OMAP PWM-controlled LEDs"
 +      depends on LEDS_CLASS && ARCH_OMAP && OMAP_DM_TIMER
 +      help
 +        This options enables support for LEDs connected to GPIO lines
 +        controlled by a PWM timer on OMAP CPUs.
 +
  config LEDS_H1940
        tristate "LED Support for iPAQ H1940 device"
        depends on LEDS_CLASS && ARCH_H1940
@@@ -124,6 -103,14 +124,14 @@@ config LEDS_HP6X
          This option enables led support for the handheld
          HP Jornada 620/660/680/690.
  
+ config LEDS_PCA9532
+       tristate "LED driver for PCA9532 dimmer"
+       depends on LEDS_CLASS && I2C && INPUT && EXPERIMENTAL
+       help
+         This option enables support for NXP pca9532
+         led controller. It is generally only usefull
+         as a platform driver
  config LEDS_GPIO
        tristate "LED Support for GPIO connected LEDs"
        depends on LEDS_CLASS && GENERIC_GPIO
@@@ -168,6 -155,14 +176,14 @@@ config LEDS_CLEVO_MAI
          To compile this driver as a module, choose M here: the
          module will be called leds-clevo-mail.
  
+ config LEDS_PCA955X
+       tristate "LED Support for PCA955x I2C chips"
+       depends on LEDS_CLASS && I2C
+       help
+         This option enables support for LEDs connected to PCA955x
+         LED driver chips accessed via the I2C bus.  Supported
+         devices include PCA9550, PCA9551, PCA9552, and PCA9553.
  comment "LED Triggers"
  
  config LEDS_TRIGGERS
diff --combined drivers/leds/Makefile
index 5ee9ceba2fdb98eafc88b170a55568f30afcf474,ff7982b44565d7fe674b0846916a8acb2d221666..fd6316edf52d700a4e6195e6b99d56a9f4227b3f
@@@ -13,16 -13,16 +13,18 @@@ obj-$(CONFIG_LEDS_S3C24XX)         += leds-s3c
  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_OMAP)                       += leds-omap.o
 +obj-$(CONFIG_LEDS_OMAP_PWM)           += leds-omap-pwm.o
  obj-$(CONFIG_LEDS_H1940)              += leds-h1940.o
  obj-$(CONFIG_LEDS_COBALT_QUBE)                += leds-cobalt-qube.o
  obj-$(CONFIG_LEDS_COBALT_RAQ)         += leds-cobalt-raq.o
+ obj-$(CONFIG_LEDS_PCA9532)            += leds-pca9532.o
  obj-$(CONFIG_LEDS_GPIO)                       += leds-gpio.o
  obj-$(CONFIG_LEDS_CM_X270)              += leds-cm-x270.o
  obj-$(CONFIG_LEDS_CLEVO_MAIL)         += leds-clevo-mail.o
  obj-$(CONFIG_LEDS_HP6XX)              += leds-hp6xx.o
  obj-$(CONFIG_LEDS_FSG)                        += leds-fsg.o
+ obj-$(CONFIG_LEDS_PCA955X)            += leds-pca955x.o
  
  # LED Triggers
  obj-$(CONFIG_LEDS_TRIGGER_TIMER)      += ledtrig-timer.o
index a6d2e2f42d81b0e076b024f54cfbcac4188bd2ac,d4a6e56a71358842b58a87146fc2672e43ba418d..59522e9ccf3c78df0280f832ca33e9144fae4048
@@@ -24,21 -24,21 +24,21 @@@ config VIDEOBUF_VMALLO
        select VIDEOBUF_GEN
        tristate
  
+ config VIDEOBUF_DMA_CONTIG
+       depends on HAS_DMA
+       select VIDEOBUF_GEN
+       tristate
  config VIDEOBUF_DVB
        tristate
        select VIDEOBUF_GEN
-       select VIDEOBUF_DMA_SG
  
  config VIDEO_BTCX
        tristate
  
- config VIDEO_IR_I2C
-       tristate
  config VIDEO_IR
        tristate
        depends on INPUT
-       select VIDEO_IR_I2C if I2C
  
  config VIDEO_TVEEPROM
        tristate
@@@ -84,6 -84,19 +84,19 @@@ config VIDEO_HELPER_CHIPS_AUT
  
          In doubt, say Y.
  
+ config VIDEO_IR_I2C
+       tristate "I2C module for IR" if !VIDEO_HELPER_CHIPS_AUTO
+       depends on I2C && VIDEO_IR
+       default y
+       ---help---
+         Most boards have an IR chip directly connected via GPIO. However,
+         some video boards have the IR connected via I2C bus.
+         If your board doesn't have an I2C IR chip, you may disable this
+         option.
+         In doubt, say Y.
  #
  # Encoder / Decoder module configuration
  #
@@@ -282,14 -295,6 +295,14 @@@ config VIDEO_TCM825
          This is a driver for the Toshiba TCM825x VGA camera sensor.
          It is used for example in Nokia N800.
  
 +config VIDEO_OV9640
 +      tristate "OmniVision OV9640 sensor support"
 +      depends on I2C && VIDEO_V4L2
 +      ---help---
 +        This is a Video4Linux2 sensor-level driver for the OmniVision
 +        OV9640 camera.  It is currently working with the TI OMAP2
 +        camera controller.
 +
  config VIDEO_SAA7110
        tristate "Philips SAA7110 video decoder"
        depends on VIDEO_V4L1 && I2C
@@@ -482,17 -487,6 +495,6 @@@ config VIDEO_PM
          To compile this driver as a module, choose M here: the
          module will be called pms.
  
- config VIDEO_PLANB
-       tristate "PlanB Video-In on PowerMac"
-       depends on PPC_PMAC && VIDEO_V4L1 && BROKEN
-       help
-         PlanB is the V4L driver for the PowerMac 7x00/8x00 series video
-         input hardware. If you want to experiment with this, say Y.
-         Otherwise, or if you don't understand a word, say N. See
-         <http://www.cpu.lu/~mlan/linux/dev/planb.html> for more info.
-         Saying M will compile this driver as a module (planb).
  config VIDEO_BWQCAM
        tristate "Quickcam BW Video For Linux"
        depends on PARPORT && VIDEO_V4L1
@@@ -608,9 -602,6 +610,6 @@@ config VIDEO_STRADI
          driver for PCI.  There is a product page at
          <http://www.stradis.com/>.
  
- config VIDEO_ZORAN_ZR36060
-       tristate
  config VIDEO_ZORAN
        tristate "Zoran ZR36057/36067 Video For Linux"
        depends on PCI && I2C_ALGOBIT && VIDEO_V4L1 && VIRT_TO_BUS
          To compile this driver as a module, choose M here: the
          module will be called zr36067.
  
+ config VIDEO_ZORAN_DC30
+       tristate "Pinnacle/Miro DC30(+) support"
+       depends on VIDEO_ZORAN
+       select VIDEO_ADV7175 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_VPX3220 if VIDEO_HELPER_CHIPS_AUTO
+       help
+         Support for the Pinnacle/Miro DC30(+) MJPEG capture/playback
+         card. This also supports really old DC10 cards based on the
+         zr36050 MJPEG codec and zr36016 VFE.
+ config VIDEO_ZORAN_ZR36060
+       tristate "Zoran ZR36060"
+       depends on VIDEO_ZORAN
+       help
+         Say Y to support Zoran boards based on 36060 chips.
+         This includes Iomega Bus, Pinnacle DC10, Linux media Labs 33
+         and 33 R10 and AverMedia 6 boards.
  config VIDEO_ZORAN_BUZ
        tristate "Iomega Buz support"
-       depends on VIDEO_ZORAN
+       depends on VIDEO_ZORAN_ZR36060
        select VIDEO_SAA7111 if VIDEO_HELPER_CHIPS_AUTO
        select VIDEO_SAA7185 if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_ZORAN_ZR36060
        help
          Support for the Iomega Buz MJPEG capture/playback card.
  
  config VIDEO_ZORAN_DC10
        tristate "Pinnacle/Miro DC10(+) support"
-       depends on VIDEO_ZORAN
-       select VIDEO_SAA7110
+       depends on VIDEO_ZORAN_ZR36060
+       select VIDEO_SAA7110 if VIDEO_HELPER_CHIPS_AUTO
        select VIDEO_ADV7175 if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_ZORAN_ZR36060
        help
          Support for the Pinnacle/Miro DC10(+) MJPEG capture/playback
          card.
  
- config VIDEO_ZORAN_DC30
-       tristate "Pinnacle/Miro DC30(+) support"
-       depends on VIDEO_ZORAN
-       select VIDEO_ADV7175 if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_VPX3220 if VIDEO_HELPER_CHIPS_AUTO
-       help
-         Support for the Pinnacle/Miro DC30(+) MJPEG capture/playback
-         card. This also supports really old DC10 cards based on the
-         zr36050 MJPEG codec and zr36016 VFE.
  config VIDEO_ZORAN_LML33
        tristate "Linux Media Labs LML33 support"
-       depends on VIDEO_ZORAN
+       depends on VIDEO_ZORAN_ZR36060
        select VIDEO_BT819 if VIDEO_HELPER_CHIPS_AUTO
        select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_ZORAN_ZR36060
        help
          Support for the Linux Media Labs LML33 MJPEG capture/playback
          card.
  
  config VIDEO_ZORAN_LML33R10
        tristate "Linux Media Labs LML33R10 support"
-       depends on VIDEO_ZORAN
+       depends on VIDEO_ZORAN_ZR36060
        select VIDEO_SAA7114 if VIDEO_HELPER_CHIPS_AUTO
        select VIDEO_ADV7170 if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_ZORAN_ZR36060
        help
          support for the Linux Media Labs LML33R10 MJPEG capture/playback
          card.
  
  config VIDEO_ZORAN_AVS6EYES
        tristate "AverMedia 6 Eyes support (EXPERIMENTAL)"
-       depends on VIDEO_ZORAN && EXPERIMENTAL && VIDEO_V4L1
+       depends on VIDEO_ZORAN_ZR36060 && EXPERIMENTAL && VIDEO_V4L1
        select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO
        select VIDEO_KS0127 if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_ZORAN_ZR36060
        help
          Support for the AverMedia 6 Eyes video surveillance card.
  
@@@ -760,8 -754,6 +762,8 @@@ source "drivers/media/video/au0828/Kcon
  
  source "drivers/media/video/ivtv/Kconfig"
  
 +source drivers/media/video/omap/Kconfig
 +
  source "drivers/media/video/cx18/Kconfig"
  
  config VIDEO_M32R_AR
@@@ -792,15 -784,6 +794,15 @@@ config VIDEO_CAFE_CCI
          CMOS camera controller.  This is the controller found on first-
          generation OLPC systems.
  
 +config VIDEO_OMAP2
 +      tristate "OMAP 2 Camera support (EXPERIMENTAL)"
 +      select VIDEOBUF_GEN
 +      select VIDEOBUF_DMA_SG
 +      depends on VIDEO_V4L2 && ARCH_OMAP24XX
 +      ---help---
 +        Driver for an OMAP 2 camera controller.
 +
 +
  #
  # USB Multimedia device configuration
  #
@@@ -812,13 -795,9 +814,9 @@@ menuconfig V4L_USB_DRIVER
  
  if V4L_USB_DRIVERS && USB
  
- config USB_VIDEO_CLASS
-       tristate "USB Video Class (UVC)"
-       ---help---
-         Support for the USB Video Class (UVC).  Currently only video
-         input devices, such as webcams, are supported.
+ source "drivers/media/video/uvc/Kconfig"
  
-         For more information see: <http://linux-uvc.berlios.de/>
+ source "drivers/media/video/gspca/Kconfig"
  
  source "drivers/media/video/pvrusb2/Kconfig"
  
@@@ -924,12 -903,21 +922,21 @@@ config USB_STKWEBCA
          To compile this driver as a module, choose M here: the
          module will be called stkwebcam.
  
+ config USB_S2255
+       tristate "USB Sensoray 2255 video capture device"
+       depends on VIDEO_V4L2
+       select VIDEOBUF_VMALLOC
+       default n
+       help
+         Say Y here if you want support for the Sensoray 2255 USB device.
+         This driver can be compiled as a module, called s2255drv.
  endif # V4L_USB_DRIVERS
  
  config SOC_CAMERA
        tristate "SoC camera support"
        depends on VIDEO_V4L2 && HAS_DMA
-       select VIDEOBUF_DMA_SG
+       select VIDEOBUF_GEN
        help
          SoC Camera is a common API to several cameras, not connecting
          over a bus like PCI or USB. For example some i2c camera connected
@@@ -964,11 -952,26 +971,26 @@@ config MT9V022_PCA9536_SWITC
          Select this if your MT9V022 camera uses a PCA9536 I2C GPIO
          extender to switch between 8 and 10 bit datawidth modes
  
+ config SOC_CAMERA_PLATFORM
+       tristate "platform camera support"
+       depends on SOC_CAMERA
+       help
+         This is a generic SoC camera platform driver, useful for testing
  config VIDEO_PXA27x
        tristate "PXA27x Quick Capture Interface driver"
        depends on VIDEO_DEV && PXA27x
        select SOC_CAMERA
+       select VIDEOBUF_DMA_SG
        ---help---
          This is a v4l2 driver for the PXA27x Quick Capture Interface
  
+ config VIDEO_SH_MOBILE_CEU
+       tristate "SuperH Mobile CEU Interface driver"
+       depends on VIDEO_DEV
+       select SOC_CAMERA
+       select VIDEOBUF_DMA_CONTIG
+       ---help---
+         This is a v4l2 driver for the SuperH Mobile CEU Interface
  endif # VIDEO_CAPTURE_DRIVERS
index f07d6916227b5c7b01b045f92bf85e9ca93e7880,bbc6f8b82297e7a62dfc7d1e6ada130dff48d2d0..398753753f21bad8bd7cced8fbedbc9c770f7160
@@@ -10,6 -10,8 +10,8 @@@ msp3400-objs  :=      msp3400-driver.o msp340
  
  stkwebcam-objs        :=      stk-webcam.o stk-sensor.o
  
+ videodev-objs :=      v4l2-dev.o v4l2-ioctl.o
  obj-$(CONFIG_VIDEO_DEV) += videodev.o compat_ioctl32.o v4l2-int-device.o
  
  obj-$(CONFIG_VIDEO_V4L2_COMMON) += v4l2-common.o
@@@ -55,7 -57,6 +57,6 @@@ obj-$(CONFIG_VIDEO_ZORAN_DC30) += zr360
  obj-$(CONFIG_VIDEO_ZORAN_ZR36060) += zr36060.o
  
  obj-$(CONFIG_VIDEO_PMS) += pms.o
- obj-$(CONFIG_VIDEO_PLANB) += planb.o
  obj-$(CONFIG_VIDEO_VINO) += vino.o indycam.o
  obj-$(CONFIG_VIDEO_STRADIS) += stradis.o
  obj-$(CONFIG_VIDEO_CPIA) += cpia.o
@@@ -88,13 -89,13 +89,14 @@@ obj-$(CONFIG_VIDEO_TUNER) += tuner.
  
  obj-$(CONFIG_VIDEOBUF_GEN) += videobuf-core.o
  obj-$(CONFIG_VIDEOBUF_DMA_SG) += videobuf-dma-sg.o
+ obj-$(CONFIG_VIDEOBUF_DMA_CONTIG) += videobuf-dma-contig.o
  obj-$(CONFIG_VIDEOBUF_VMALLOC) += videobuf-vmalloc.o
  obj-$(CONFIG_VIDEOBUF_DVB) += videobuf-dvb.o
  obj-$(CONFIG_VIDEO_BTCX)  += btcx-risc.o
  obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o
  
  obj-$(CONFIG_VIDEO_M32R_AR_M64278) += arv.o
 +obj-$(CONFIG_VIDEO_OMAP_CAMERA) += omap/
  
  obj-$(CONFIG_VIDEO_CX25840) += cx25840/
  obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o
@@@ -104,9 -105,7 +106,9 @@@ obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.
  obj-$(CONFIG_VIDEO_CAFE_CCIC) += cafe_ccic.o
  obj-$(CONFIG_VIDEO_OV7670)    += ov7670.o
  
 +obj-$(CONFIG_VIDEO_OMAP2) += omap24xxcam.o omap24xxcam-dma.o
  obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o
 +obj-$(CONFIG_VIDEO_OV9640)    += ov9640.o
  
  obj-$(CONFIG_USB_DABUSB)        += dabusb.o
  obj-$(CONFIG_USB_OV511)         += ov511.o
@@@ -120,11 -119,13 +122,13 @@@ obj-$(CONFIG_USB_SN9C102)       += sn9c
  obj-$(CONFIG_USB_ET61X251)      += et61x251/
  obj-$(CONFIG_USB_PWC)           += pwc/
  obj-$(CONFIG_USB_ZC0301)        += zc0301/
+ obj-$(CONFIG_USB_GSPCA)         += gspca/
  
  obj-$(CONFIG_USB_IBMCAM)        += usbvideo/
  obj-$(CONFIG_USB_KONICAWC)      += usbvideo/
  obj-$(CONFIG_USB_VICAM)         += usbvideo/
  obj-$(CONFIG_USB_QUICKCAM_MESSENGER)  += usbvideo/
+ obj-$(CONFIG_USB_S2255)               += s2255drv.o
  
  obj-$(CONFIG_VIDEO_IVTV) += ivtv/
  obj-$(CONFIG_VIDEO_CX18) += cx18/
@@@ -133,9 -134,11 +137,11 @@@ obj-$(CONFIG_VIDEO_VIVI) += vivi.
  obj-$(CONFIG_VIDEO_CX23885) += cx23885/
  
  obj-$(CONFIG_VIDEO_PXA27x)    += pxa_camera.o
+ obj-$(CONFIG_VIDEO_SH_MOBILE_CEU)     += sh_mobile_ceu_camera.o
  obj-$(CONFIG_SOC_CAMERA)      += soc_camera.o
  obj-$(CONFIG_SOC_CAMERA_MT9M001)      += mt9m001.o
  obj-$(CONFIG_SOC_CAMERA_MT9V022)      += mt9v022.o
+ obj-$(CONFIG_SOC_CAMERA_PLATFORM)     += soc_camera_platform.o
  
  obj-$(CONFIG_VIDEO_AU0828) += au0828/
  
index dfd34796d0493345101b385e065c3e978d842a01,0000000000000000000000000000000000000000..6793869fcf58599cf15c62e533818b0e23ec9808
mode 100644,000000..100644
--- /dev/null
@@@ -1,1905 -1,0 +1,1905 @@@
-       .owner   = THIS_MODULE,
 +/*
 + * drivers/media/video/omap24xxcam.c
 + *
 + * OMAP 2 camera block driver.
 + *
 + * Copyright (C) 2004 MontaVista Software, Inc.
 + * Copyright (C) 2004 Texas Instruments.
 + * Copyright (C) 2007 Nokia Corporation.
 + *
 + * Contact: Sakari Ailus <sakari.ailus@nokia.com>
 + *
 + * Based on code from Andy Lowe <source@mvista.com>
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * version 2 as published by the Free Software Foundation.
 + *
 + * 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., 51 Franklin St, Fifth Floor, Boston, MA
 + * 02110-1301 USA
 + */
 +
 +#include <linux/delay.h>
 +#include <linux/kernel.h>
 +#include <linux/interrupt.h>
 +#include <linux/videodev2.h>
 +#include <linux/pci.h>                /* needed for videobufs */
 +#include <linux/version.h>
 +#include <linux/platform_device.h>
 +#include <linux/clk.h>
 +#include <linux/io.h>
 +
 +#include <media/v4l2-common.h>
++#include <media/v4l2-ioctl.h>
 +
 +#include "omap24xxcam.h"
 +
 +#define OMAP24XXCAM_VERSION KERNEL_VERSION(0, 0, 0)
 +
 +#define RESET_TIMEOUT_NS 10000
 +
 +static void omap24xxcam_reset(struct omap24xxcam_device *cam);
 +static int omap24xxcam_sensor_if_enable(struct omap24xxcam_device *cam);
 +static void omap24xxcam_device_unregister(struct v4l2_int_device *s);
 +static int omap24xxcam_remove(struct platform_device *pdev);
 +
 +/* module parameters */
 +static int video_nr = -1;     /* video device minor (-1 ==> auto assign) */
 +/*
 + * Maximum amount of memory to use for capture buffers.
 + * Default is 4800KB, enough to double-buffer SXGA.
 + */
 +static int capture_mem = 1280 * 960 * 2 * 2;
 +
 +static struct v4l2_int_device omap24xxcam;
 +
 +/*
 + *
 + * Clocks.
 + *
 + */
 +
 +static void omap24xxcam_clock_put(struct omap24xxcam_device *cam)
 +{
 +      if (cam->ick != NULL && !IS_ERR(cam->ick))
 +              clk_put(cam->ick);
 +      if (cam->fck != NULL && !IS_ERR(cam->fck))
 +              clk_put(cam->fck);
 +
 +      cam->ick = cam->fck = NULL;
 +}
 +
 +static int omap24xxcam_clock_get(struct omap24xxcam_device *cam)
 +{
 +      int rval = 0;
 +
 +      cam->fck = clk_get(cam->dev, "cam_fck");
 +      if (IS_ERR(cam->fck)) {
 +              dev_err(cam->dev, "can't get cam_fck");
 +              rval = PTR_ERR(cam->fck);
 +              omap24xxcam_clock_put(cam);
 +              return rval;
 +      }
 +
 +      cam->ick = clk_get(cam->dev, "cam_ick");
 +      if (IS_ERR(cam->ick)) {
 +              dev_err(cam->dev, "can't get cam_ick");
 +              rval = PTR_ERR(cam->ick);
 +              omap24xxcam_clock_put(cam);
 +      }
 +
 +      return rval;
 +}
 +
 +static void omap24xxcam_clock_on(struct omap24xxcam_device *cam)
 +{
 +      clk_enable(cam->fck);
 +      clk_enable(cam->ick);
 +}
 +
 +static void omap24xxcam_clock_off(struct omap24xxcam_device *cam)
 +{
 +      clk_disable(cam->fck);
 +      clk_disable(cam->ick);
 +}
 +
 +/*
 + *
 + * Camera core
 + *
 + */
 +
 +/*
 + * Set xclk.
 + *
 + * To disable xclk, use value zero.
 + */
 +static void omap24xxcam_core_xclk_set(const struct omap24xxcam_device *cam,
 +                                    u32 xclk)
 +{
 +      if (xclk) {
 +              u32 divisor = CAM_MCLK / xclk;
 +
 +              if (divisor == 1)
 +                      omap24xxcam_reg_out(cam->mmio_base + CC_REG_OFFSET,
 +                                          CC_CTRL_XCLK,
 +                                          CC_CTRL_XCLK_DIV_BYPASS);
 +              else
 +                      omap24xxcam_reg_out(cam->mmio_base + CC_REG_OFFSET,
 +                                          CC_CTRL_XCLK, divisor);
 +      } else
 +              omap24xxcam_reg_out(cam->mmio_base + CC_REG_OFFSET,
 +                                  CC_CTRL_XCLK, CC_CTRL_XCLK_DIV_STABLE_LOW);
 +}
 +
 +static void omap24xxcam_core_hwinit(const struct omap24xxcam_device *cam)
 +{
 +      /*
 +       * Setting the camera core AUTOIDLE bit causes problems with frame
 +       * synchronization, so we will clear the AUTOIDLE bit instead.
 +       */
 +      omap24xxcam_reg_out(cam->mmio_base + CC_REG_OFFSET, CC_SYSCONFIG,
 +                          CC_SYSCONFIG_AUTOIDLE);
 +
 +      /* program the camera interface DMA packet size */
 +      omap24xxcam_reg_out(cam->mmio_base + CC_REG_OFFSET, CC_CTRL_DMA,
 +                          CC_CTRL_DMA_EN | (DMA_THRESHOLD / 4 - 1));
 +
 +      /* enable camera core error interrupts */
 +      omap24xxcam_reg_out(cam->mmio_base + CC_REG_OFFSET, CC_IRQENABLE,
 +                          CC_IRQENABLE_FW_ERR_IRQ
 +                          | CC_IRQENABLE_FSC_ERR_IRQ
 +                          | CC_IRQENABLE_SSC_ERR_IRQ
 +                          | CC_IRQENABLE_FIFO_OF_IRQ);
 +}
 +
 +/*
 + * Enable the camera core.
 + *
 + * Data transfer to the camera DMA starts from next starting frame.
 + */
 +static void omap24xxcam_core_enable(const struct omap24xxcam_device *cam)
 +{
 +
 +      omap24xxcam_reg_out(cam->mmio_base + CC_REG_OFFSET, CC_CTRL,
 +                          cam->cc_ctrl);
 +}
 +
 +/*
 + * Disable camera core.
 + *
 + * The data transfer will be stopped immediately (CC_CTRL_CC_RST). The
 + * core internal state machines will be reset. Use
 + * CC_CTRL_CC_FRAME_TRIG instead if you want to transfer the current
 + * frame completely.
 + */
 +static void omap24xxcam_core_disable(const struct omap24xxcam_device *cam)
 +{
 +      omap24xxcam_reg_out(cam->mmio_base + CC_REG_OFFSET, CC_CTRL,
 +                          CC_CTRL_CC_RST);
 +}
 +
 +/* Interrupt service routine for camera core interrupts. */
 +static void omap24xxcam_core_isr(struct omap24xxcam_device *cam)
 +{
 +      u32 cc_irqstatus;
 +      const u32 cc_irqstatus_err =
 +              CC_IRQSTATUS_FW_ERR_IRQ
 +              | CC_IRQSTATUS_FSC_ERR_IRQ
 +              | CC_IRQSTATUS_SSC_ERR_IRQ
 +              | CC_IRQSTATUS_FIFO_UF_IRQ
 +              | CC_IRQSTATUS_FIFO_OF_IRQ;
 +
 +      cc_irqstatus = omap24xxcam_reg_in(cam->mmio_base + CC_REG_OFFSET,
 +                                        CC_IRQSTATUS);
 +      omap24xxcam_reg_out(cam->mmio_base + CC_REG_OFFSET, CC_IRQSTATUS,
 +                          cc_irqstatus);
 +
 +      if (cc_irqstatus & cc_irqstatus_err
 +          && !atomic_read(&cam->in_reset)) {
 +              dev_dbg(cam->dev, "resetting camera, cc_irqstatus 0x%x\n",
 +                      cc_irqstatus);
 +              omap24xxcam_reset(cam);
 +      }
 +}
 +
 +/*
 + *
 + * videobuf_buffer handling.
 + *
 + * Memory for mmapped videobuf_buffers is not allocated
 + * conventionally, but by several kmalloc allocations and then
 + * creating the scatterlist on our own. User-space buffers are handled
 + * normally.
 + *
 + */
 +
 +/*
 + * Free the memory-mapped buffer memory allocated for a
 + * videobuf_buffer and the associated scatterlist.
 + */
 +static void omap24xxcam_vbq_free_mmap_buffer(struct videobuf_buffer *vb)
 +{
 +      struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
 +      size_t alloc_size;
 +      struct page *page;
 +      int i;
 +
 +      if (dma->sglist == NULL)
 +              return;
 +
 +      i = dma->sglen;
 +      while (i) {
 +              i--;
 +              alloc_size = sg_dma_len(&dma->sglist[i]);
 +              page = sg_page(&dma->sglist[i]);
 +              do {
 +                      ClearPageReserved(page++);
 +              } while (alloc_size -= PAGE_SIZE);
 +              __free_pages(sg_page(&dma->sglist[i]),
 +                           get_order(sg_dma_len(&dma->sglist[i])));
 +      }
 +
 +      kfree(dma->sglist);
 +      dma->sglist = NULL;
 +}
 +
 +/* Release all memory related to the videobuf_queue. */
 +static void omap24xxcam_vbq_free_mmap_buffers(struct videobuf_queue *vbq)
 +{
 +      int i;
 +
 +      mutex_lock(&vbq->vb_lock);
 +
 +      for (i = 0; i < VIDEO_MAX_FRAME; i++) {
 +              if (NULL == vbq->bufs[i])
 +                      continue;
 +              if (V4L2_MEMORY_MMAP != vbq->bufs[i]->memory)
 +                      continue;
 +              vbq->ops->buf_release(vbq, vbq->bufs[i]);
 +              omap24xxcam_vbq_free_mmap_buffer(vbq->bufs[i]);
 +              kfree(vbq->bufs[i]);
 +              vbq->bufs[i] = NULL;
 +      }
 +
 +      mutex_unlock(&vbq->vb_lock);
 +
 +      videobuf_mmap_free(vbq);
 +}
 +
 +/*
 + * Allocate physically as contiguous as possible buffer for video
 + * frame and allocate and build DMA scatter-gather list for it.
 + */
 +static int omap24xxcam_vbq_alloc_mmap_buffer(struct videobuf_buffer *vb)
 +{
 +      unsigned int order;
 +      size_t alloc_size, size = vb->bsize; /* vb->bsize is page aligned */
 +      struct page *page;
 +      int max_pages, err = 0, i = 0;
 +      struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
 +
 +      /*
 +       * allocate maximum size scatter-gather list. Note this is
 +       * overhead. We may not use as many entries as we allocate
 +       */
 +      max_pages = vb->bsize >> PAGE_SHIFT;
 +      dma->sglist = kcalloc(max_pages, sizeof(*dma->sglist), GFP_KERNEL);
 +      if (dma->sglist == NULL) {
 +              err = -ENOMEM;
 +              goto out;
 +      }
 +
 +      while (size) {
 +              order = get_order(size);
 +              /*
 +               * do not over-allocate even if we would get larger
 +               * contiguous chunk that way
 +               */
 +              if ((PAGE_SIZE << order) > size)
 +                      order--;
 +
 +              /* try to allocate as many contiguous pages as possible */
 +              page = alloc_pages(GFP_KERNEL | GFP_DMA, order);
 +              /* if allocation fails, try to allocate smaller amount */
 +              while (page == NULL) {
 +                      order--;
 +                      page = alloc_pages(GFP_KERNEL | GFP_DMA, order);
 +                      if (page == NULL && !order) {
 +                              err = -ENOMEM;
 +                              goto out;
 +                      }
 +              }
 +              size -= (PAGE_SIZE << order);
 +
 +              /* append allocated chunk of pages into scatter-gather list */
 +              sg_set_page(&dma->sglist[i], page, PAGE_SIZE << order, 0);
 +              dma->sglen++;
 +              i++;
 +
 +              alloc_size = (PAGE_SIZE << order);
 +
 +              /* clear pages before giving them to user space */
 +              memset(page_address(page), 0, alloc_size);
 +
 +              /* mark allocated pages reserved */
 +              do {
 +                      SetPageReserved(page++);
 +              } while (alloc_size -= PAGE_SIZE);
 +      }
 +      /*
 +       * REVISIT: not fully correct to assign nr_pages == sglen but
 +       * video-buf is passing nr_pages for e.g. unmap_sg calls
 +       */
 +      dma->nr_pages = dma->sglen;
 +      dma->direction = PCI_DMA_FROMDEVICE;
 +
 +      return 0;
 +
 +out:
 +      omap24xxcam_vbq_free_mmap_buffer(vb);
 +      return err;
 +}
 +
 +static int omap24xxcam_vbq_alloc_mmap_buffers(struct videobuf_queue *vbq,
 +                                            unsigned int count)
 +{
 +      int i, err = 0;
 +      struct omap24xxcam_fh *fh =
 +              container_of(vbq, struct omap24xxcam_fh, vbq);
 +
 +      mutex_lock(&vbq->vb_lock);
 +
 +      for (i = 0; i < count; i++) {
 +              err = omap24xxcam_vbq_alloc_mmap_buffer(vbq->bufs[i]);
 +              if (err)
 +                      goto out;
 +              dev_dbg(fh->cam->dev, "sglen is %d for buffer %d\n",
 +                      videobuf_to_dma(vbq->bufs[i])->sglen, i);
 +      }
 +
 +      mutex_unlock(&vbq->vb_lock);
 +
 +      return 0;
 +out:
 +      while (i) {
 +              i--;
 +              omap24xxcam_vbq_free_mmap_buffer(vbq->bufs[i]);
 +      }
 +
 +      mutex_unlock(&vbq->vb_lock);
 +
 +      return err;
 +}
 +
 +/*
 + * This routine is called from interrupt context when a scatter-gather DMA
 + * transfer of a videobuf_buffer completes.
 + */
 +static void omap24xxcam_vbq_complete(struct omap24xxcam_sgdma *sgdma,
 +                                   u32 csr, void *arg)
 +{
 +      struct omap24xxcam_device *cam =
 +              container_of(sgdma, struct omap24xxcam_device, sgdma);
 +      struct omap24xxcam_fh *fh = cam->streaming->private_data;
 +      struct videobuf_buffer *vb = (struct videobuf_buffer *)arg;
 +      const u32 csr_error = CAMDMA_CSR_MISALIGNED_ERR
 +              | CAMDMA_CSR_SUPERVISOR_ERR | CAMDMA_CSR_SECURE_ERR
 +              | CAMDMA_CSR_TRANS_ERR | CAMDMA_CSR_DROP;
 +      unsigned long flags;
 +
 +      spin_lock_irqsave(&cam->core_enable_disable_lock, flags);
 +      if (--cam->sgdma_in_queue == 0)
 +              omap24xxcam_core_disable(cam);
 +      spin_unlock_irqrestore(&cam->core_enable_disable_lock, flags);
 +
 +      do_gettimeofday(&vb->ts);
 +      vb->field_count = atomic_add_return(2, &fh->field_count);
 +      if (csr & csr_error) {
 +              vb->state = VIDEOBUF_ERROR;
 +              if (!atomic_read(&fh->cam->in_reset)) {
 +                      dev_dbg(cam->dev, "resetting camera, csr 0x%x\n", csr);
 +                      omap24xxcam_reset(cam);
 +              }
 +      } else
 +              vb->state = VIDEOBUF_DONE;
 +      wake_up(&vb->done);
 +}
 +
 +static void omap24xxcam_vbq_release(struct videobuf_queue *vbq,
 +                                  struct videobuf_buffer *vb)
 +{
 +      struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
 +
 +      /* wait for buffer, especially to get out of the sgdma queue */
 +      videobuf_waiton(vb, 0, 0);
 +      if (vb->memory == V4L2_MEMORY_MMAP) {
 +              dma_unmap_sg(vbq->dev, dma->sglist, dma->sglen,
 +                           dma->direction);
 +              dma->direction = DMA_NONE;
 +      } else {
 +              videobuf_dma_unmap(vbq, videobuf_to_dma(vb));
 +              videobuf_dma_free(videobuf_to_dma(vb));
 +      }
 +
 +      vb->state = VIDEOBUF_NEEDS_INIT;
 +}
 +
 +/*
 + * Limit the number of available kernel image capture buffers based on the
 + * number requested, the currently selected image size, and the maximum
 + * amount of memory permitted for kernel capture buffers.
 + */
 +static int omap24xxcam_vbq_setup(struct videobuf_queue *vbq, unsigned int *cnt,
 +                               unsigned int *size)
 +{
 +      struct omap24xxcam_fh *fh = vbq->priv_data;
 +
 +      if (*cnt <= 0)
 +              *cnt = VIDEO_MAX_FRAME; /* supply a default number of buffers */
 +
 +      if (*cnt > VIDEO_MAX_FRAME)
 +              *cnt = VIDEO_MAX_FRAME;
 +
 +      *size = fh->pix.sizeimage;
 +
 +      /* accessing fh->cam->capture_mem is ok, it's constant */
 +      while (*size * *cnt > fh->cam->capture_mem)
 +              (*cnt)--;
 +
 +      return 0;
 +}
 +
 +static int omap24xxcam_dma_iolock(struct videobuf_queue *vbq,
 +                                struct videobuf_dmabuf *dma)
 +{
 +      int err = 0;
 +
 +      dma->direction = PCI_DMA_FROMDEVICE;
 +      if (!dma_map_sg(vbq->dev, dma->sglist, dma->sglen, dma->direction)) {
 +              kfree(dma->sglist);
 +              dma->sglist = NULL;
 +              dma->sglen = 0;
 +              err = -EIO;
 +      }
 +
 +      return err;
 +}
 +
 +static int omap24xxcam_vbq_prepare(struct videobuf_queue *vbq,
 +                                 struct videobuf_buffer *vb,
 +                                 enum v4l2_field field)
 +{
 +      struct omap24xxcam_fh *fh = vbq->priv_data;
 +      int err = 0;
 +
 +      /*
 +       * Accessing pix here is okay since it's constant while
 +       * streaming is on (and we only get called then).
 +       */
 +      if (vb->baddr) {
 +              /* This is a userspace buffer. */
 +              if (fh->pix.sizeimage > vb->bsize) {
 +                      /* The buffer isn't big enough. */
 +                      err = -EINVAL;
 +              } else
 +                      vb->size = fh->pix.sizeimage;
 +      } else {
 +              if (vb->state != VIDEOBUF_NEEDS_INIT) {
 +                      /*
 +                       * We have a kernel bounce buffer that has
 +                       * already been allocated.
 +                       */
 +                      if (fh->pix.sizeimage > vb->size) {
 +                              /*
 +                               * The image size has been changed to
 +                               * a larger size since this buffer was
 +                               * allocated, so we need to free and
 +                               * reallocate it.
 +                               */
 +                              omap24xxcam_vbq_release(vbq, vb);
 +                              vb->size = fh->pix.sizeimage;
 +                      }
 +              } else {
 +                      /* We need to allocate a new kernel bounce buffer. */
 +                      vb->size = fh->pix.sizeimage;
 +              }
 +      }
 +
 +      if (err)
 +              return err;
 +
 +      vb->width = fh->pix.width;
 +      vb->height = fh->pix.height;
 +      vb->field = field;
 +
 +      if (vb->state == VIDEOBUF_NEEDS_INIT) {
 +              if (vb->memory == V4L2_MEMORY_MMAP)
 +                      /*
 +                       * we have built the scatter-gather list by ourself so
 +                       * do the scatter-gather mapping as well
 +                       */
 +                      err = omap24xxcam_dma_iolock(vbq, videobuf_to_dma(vb));
 +              else
 +                      err = videobuf_iolock(vbq, vb, NULL);
 +      }
 +
 +      if (!err)
 +              vb->state = VIDEOBUF_PREPARED;
 +      else
 +              omap24xxcam_vbq_release(vbq, vb);
 +
 +      return err;
 +}
 +
 +static void omap24xxcam_vbq_queue(struct videobuf_queue *vbq,
 +                                struct videobuf_buffer *vb)
 +{
 +      struct omap24xxcam_fh *fh = vbq->priv_data;
 +      struct omap24xxcam_device *cam = fh->cam;
 +      enum videobuf_state state = vb->state;
 +      unsigned long flags;
 +      int err;
 +
 +      /*
 +       * FIXME: We're marking the buffer active since we have no
 +       * pretty way of marking it active exactly when the
 +       * scatter-gather transfer starts.
 +       */
 +      vb->state = VIDEOBUF_ACTIVE;
 +
 +      err = omap24xxcam_sgdma_queue(&fh->cam->sgdma,
 +                                    videobuf_to_dma(vb)->sglist,
 +                                    videobuf_to_dma(vb)->sglen, vb->size,
 +                                    omap24xxcam_vbq_complete, vb);
 +
 +      if (!err) {
 +              spin_lock_irqsave(&cam->core_enable_disable_lock, flags);
 +              if (++cam->sgdma_in_queue == 1
 +                  && !atomic_read(&cam->in_reset))
 +                      omap24xxcam_core_enable(cam);
 +              spin_unlock_irqrestore(&cam->core_enable_disable_lock, flags);
 +      } else {
 +              /*
 +               * Oops. We're not supposed to get any errors here.
 +               * The only way we could get an error is if we ran out
 +               * of scatter-gather DMA slots, but we are supposed to
 +               * have at least as many scatter-gather DMA slots as
 +               * video buffers so that can't happen.
 +               */
 +              dev_err(cam->dev, "failed to queue a video buffer for dma!\n");
 +              dev_err(cam->dev, "likely a bug in the driver!\n");
 +              vb->state = state;
 +      }
 +}
 +
 +static struct videobuf_queue_ops omap24xxcam_vbq_ops = {
 +      .buf_setup   = omap24xxcam_vbq_setup,
 +      .buf_prepare = omap24xxcam_vbq_prepare,
 +      .buf_queue   = omap24xxcam_vbq_queue,
 +      .buf_release = omap24xxcam_vbq_release,
 +};
 +
 +/*
 + *
 + * OMAP main camera system
 + *
 + */
 +
 +/*
 + * Reset camera block to power-on state.
 + */
 +static void omap24xxcam_poweron_reset(const struct omap24xxcam_device *cam)
 +{
 +      int max_loop = RESET_TIMEOUT_NS;
 +
 +      /* Reset whole camera subsystem */
 +      omap24xxcam_reg_out(cam->mmio_base,
 +                          CAM_SYSCONFIG,
 +                          CAM_SYSCONFIG_SOFTRESET);
 +
 +      /* Wait till it's finished */
 +      while (!(omap24xxcam_reg_in(cam->mmio_base, CAM_SYSSTATUS)
 +               & CAM_SYSSTATUS_RESETDONE)
 +             && --max_loop) {
 +              ndelay(1);
 +      }
 +
 +      if (!(omap24xxcam_reg_in(cam->mmio_base, CAM_SYSSTATUS)
 +            & CAM_SYSSTATUS_RESETDONE))
 +              dev_err(cam->dev, "camera soft reset timeout\n");
 +}
 +
 +/*
 + * (Re)initialise the camera block.
 + */
 +static void omap24xxcam_hwinit(const struct omap24xxcam_device *cam)
 +{
 +      omap24xxcam_poweron_reset(cam);
 +
 +      /* set the camera subsystem autoidle bit */
 +      omap24xxcam_reg_out(cam->mmio_base, CAM_SYSCONFIG,
 +                          CAM_SYSCONFIG_AUTOIDLE);
 +
 +      /* set the camera MMU autoidle bit */
 +      omap24xxcam_reg_out(cam->mmio_base,
 +                          CAMMMU_REG_OFFSET + CAMMMU_SYSCONFIG,
 +                          CAMMMU_SYSCONFIG_AUTOIDLE);
 +
 +      omap24xxcam_core_hwinit(cam);
 +
 +      omap24xxcam_dma_hwinit(&cam->sgdma.dma);
 +}
 +
 +/*
 + * Callback for dma transfer stalling.
 + */
 +static void omap24xxcam_stalled_dma_reset(unsigned long data)
 +{
 +      struct omap24xxcam_device *cam = (struct omap24xxcam_device *)data;
 +
 +      if (!atomic_read(&cam->in_reset)) {
 +              dev_dbg(cam->dev, "dma stalled, resetting camera\n");
 +              omap24xxcam_reset(cam);
 +      }
 +}
 +
 +/*
 + * Stop capture. Mark we're doing a reset, stop DMA transfers and
 + * core. (No new scatter-gather transfers will be queued whilst
 + * in_reset is non-zero.)
 + *
 + * If omap24xxcam_capture_stop is called from several places at
 + * once, only the first call will have an effect. Similarly, the last
 + * call omap24xxcam_streaming_cont will have effect.
 + *
 + * Serialisation is ensured by using cam->core_enable_disable_lock.
 + */
 +static void omap24xxcam_capture_stop(struct omap24xxcam_device *cam)
 +{
 +      unsigned long flags;
 +
 +      spin_lock_irqsave(&cam->core_enable_disable_lock, flags);
 +
 +      if (atomic_inc_return(&cam->in_reset) != 1) {
 +              spin_unlock_irqrestore(&cam->core_enable_disable_lock, flags);
 +              return;
 +      }
 +
 +      omap24xxcam_core_disable(cam);
 +
 +      spin_unlock_irqrestore(&cam->core_enable_disable_lock, flags);
 +
 +      omap24xxcam_sgdma_sync(&cam->sgdma);
 +}
 +
 +/*
 + * Reset and continue streaming.
 + *
 + * Note: Resetting the camera FIFO via the CC_RST bit in the CC_CTRL
 + * register is supposed to be sufficient to recover from a camera
 + * interface error, but it doesn't seem to be enough. If we only do
 + * that then subsequent image captures are out of sync by either one
 + * or two times DMA_THRESHOLD bytes. Resetting and re-initializing the
 + * entire camera subsystem prevents the problem with frame
 + * synchronization.
 + */
 +static void omap24xxcam_capture_cont(struct omap24xxcam_device *cam)
 +{
 +      unsigned long flags;
 +
 +      spin_lock_irqsave(&cam->core_enable_disable_lock, flags);
 +
 +      if (atomic_read(&cam->in_reset) != 1)
 +              goto out;
 +
 +      omap24xxcam_hwinit(cam);
 +
 +      omap24xxcam_sensor_if_enable(cam);
 +
 +      omap24xxcam_sgdma_process(&cam->sgdma);
 +
 +      if (cam->sgdma_in_queue)
 +              omap24xxcam_core_enable(cam);
 +
 +out:
 +      atomic_dec(&cam->in_reset);
 +      spin_unlock_irqrestore(&cam->core_enable_disable_lock, flags);
 +}
 +
 +static ssize_t
 +omap24xxcam_streaming_show(struct device *dev, struct device_attribute *attr,
 +              char *buf)
 +{
 +      struct omap24xxcam_device *cam = dev_get_drvdata(dev);
 +
 +      return sprintf(buf, "%s\n", cam->streaming ?  "active" : "inactive");
 +}
 +static DEVICE_ATTR(streaming, S_IRUGO, omap24xxcam_streaming_show, NULL);
 +
 +/*
 + * Stop capture and restart it. I.e. reset the camera during use.
 + */
 +static void omap24xxcam_reset(struct omap24xxcam_device *cam)
 +{
 +      omap24xxcam_capture_stop(cam);
 +      omap24xxcam_capture_cont(cam);
 +}
 +
 +/*
 + * The main interrupt handler.
 + */
 +static irqreturn_t omap24xxcam_isr(int irq, void *arg)
 +{
 +      struct omap24xxcam_device *cam = (struct omap24xxcam_device *)arg;
 +      u32 irqstatus;
 +      unsigned int irqhandled = 0;
 +
 +      irqstatus = omap24xxcam_reg_in(cam->mmio_base, CAM_IRQSTATUS);
 +
 +      if (irqstatus &
 +          (CAM_IRQSTATUS_DMA_IRQ2 | CAM_IRQSTATUS_DMA_IRQ1
 +           | CAM_IRQSTATUS_DMA_IRQ0)) {
 +              omap24xxcam_dma_isr(&cam->sgdma.dma);
 +              irqhandled = 1;
 +      }
 +      if (irqstatus & CAM_IRQSTATUS_CC_IRQ) {
 +              omap24xxcam_core_isr(cam);
 +              irqhandled = 1;
 +      }
 +      if (irqstatus & CAM_IRQSTATUS_MMU_IRQ)
 +              dev_err(cam->dev, "unhandled camera MMU interrupt!\n");
 +
 +      return IRQ_RETVAL(irqhandled);
 +}
 +
 +/*
 + *
 + * Sensor handling.
 + *
 + */
 +
 +/*
 + * Enable the external sensor interface. Try to negotiate interface
 + * parameters with the sensor and start using the new ones. The calls
 + * to sensor_if_enable and sensor_if_disable need not to be balanced.
 + */
 +static int omap24xxcam_sensor_if_enable(struct omap24xxcam_device *cam)
 +{
 +      int rval;
 +      struct v4l2_ifparm p;
 +
 +      rval = vidioc_int_g_ifparm(cam->sdev, &p);
 +      if (rval) {
 +              dev_err(cam->dev, "vidioc_int_g_ifparm failed with %d\n", rval);
 +              return rval;
 +      }
 +
 +      cam->if_type = p.if_type;
 +
 +      cam->cc_ctrl = CC_CTRL_CC_EN;
 +
 +      switch (p.if_type) {
 +      case V4L2_IF_TYPE_BT656:
 +              if (p.u.bt656.frame_start_on_rising_vs)
 +                      cam->cc_ctrl |= CC_CTRL_NOBT_SYNCHRO;
 +              if (p.u.bt656.bt_sync_correct)
 +                      cam->cc_ctrl |= CC_CTRL_BT_CORRECT;
 +              if (p.u.bt656.swap)
 +                      cam->cc_ctrl |= CC_CTRL_PAR_ORDERCAM;
 +              if (p.u.bt656.latch_clk_inv)
 +                      cam->cc_ctrl |= CC_CTRL_PAR_CLK_POL;
 +              if (p.u.bt656.nobt_hs_inv)
 +                      cam->cc_ctrl |= CC_CTRL_NOBT_HS_POL;
 +              if (p.u.bt656.nobt_vs_inv)
 +                      cam->cc_ctrl |= CC_CTRL_NOBT_VS_POL;
 +
 +              switch (p.u.bt656.mode) {
 +              case V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT:
 +                      cam->cc_ctrl |= CC_CTRL_PAR_MODE_NOBT8;
 +                      break;
 +              case V4L2_IF_TYPE_BT656_MODE_NOBT_10BIT:
 +                      cam->cc_ctrl |= CC_CTRL_PAR_MODE_NOBT10;
 +                      break;
 +              case V4L2_IF_TYPE_BT656_MODE_NOBT_12BIT:
 +                      cam->cc_ctrl |= CC_CTRL_PAR_MODE_NOBT12;
 +                      break;
 +              case V4L2_IF_TYPE_BT656_MODE_BT_8BIT:
 +                      cam->cc_ctrl |= CC_CTRL_PAR_MODE_BT8;
 +                      break;
 +              case V4L2_IF_TYPE_BT656_MODE_BT_10BIT:
 +                      cam->cc_ctrl |= CC_CTRL_PAR_MODE_BT10;
 +                      break;
 +              default:
 +                      dev_err(cam->dev,
 +                              "bt656 interface mode %d not supported\n",
 +                              p.u.bt656.mode);
 +                      return -EINVAL;
 +              }
 +              /*
 +               * The clock rate that the sensor wants has changed.
 +               * We have to adjust the xclk from OMAP 2 side to
 +               * match the sensor's wish as closely as possible.
 +               */
 +              if (p.u.bt656.clock_curr != cam->if_u.bt656.xclk) {
 +                      u32 xclk = p.u.bt656.clock_curr;
 +                      u32 divisor;
 +
 +                      if (xclk == 0)
 +                              return -EINVAL;
 +
 +                      if (xclk > CAM_MCLK)
 +                              xclk = CAM_MCLK;
 +
 +                      divisor = CAM_MCLK / xclk;
 +                      if (divisor * xclk < CAM_MCLK)
 +                              divisor++;
 +                      if (CAM_MCLK / divisor < p.u.bt656.clock_min
 +                          && divisor > 1)
 +                              divisor--;
 +                      if (divisor > 30)
 +                              divisor = 30;
 +
 +                      xclk = CAM_MCLK / divisor;
 +
 +                      if (xclk < p.u.bt656.clock_min
 +                          || xclk > p.u.bt656.clock_max)
 +                              return -EINVAL;
 +
 +                      cam->if_u.bt656.xclk = xclk;
 +              }
 +              omap24xxcam_core_xclk_set(cam, cam->if_u.bt656.xclk);
 +              break;
 +      default:
 +              /* FIXME: how about other interfaces? */
 +              dev_err(cam->dev, "interface type %d not supported\n",
 +                      p.if_type);
 +              return -EINVAL;
 +      }
 +
 +      return 0;
 +}
 +
 +static void omap24xxcam_sensor_if_disable(const struct omap24xxcam_device *cam)
 +{
 +      switch (cam->if_type) {
 +      case V4L2_IF_TYPE_BT656:
 +              omap24xxcam_core_xclk_set(cam, 0);
 +              break;
 +      }
 +}
 +
 +/*
 + * Initialise the sensor hardware.
 + */
 +static int omap24xxcam_sensor_init(struct omap24xxcam_device *cam)
 +{
 +      int err = 0;
 +      struct v4l2_int_device *sdev = cam->sdev;
 +
 +      omap24xxcam_clock_on(cam);
 +      err = omap24xxcam_sensor_if_enable(cam);
 +      if (err) {
 +              dev_err(cam->dev, "sensor interface could not be enabled at "
 +                      "initialisation, %d\n", err);
 +              cam->sdev = NULL;
 +              goto out;
 +      }
 +
 +      /* power up sensor during sensor initialization */
 +      vidioc_int_s_power(sdev, 1);
 +
 +      err = vidioc_int_dev_init(sdev);
 +      if (err) {
 +              dev_err(cam->dev, "cannot initialize sensor, error %d\n", err);
 +              /* Sensor init failed --- it's nonexistent to us! */
 +              cam->sdev = NULL;
 +              goto out;
 +      }
 +
 +      dev_info(cam->dev, "sensor is %s\n", sdev->name);
 +
 +out:
 +      omap24xxcam_sensor_if_disable(cam);
 +      omap24xxcam_clock_off(cam);
 +
 +      vidioc_int_s_power(sdev, 0);
 +
 +      return err;
 +}
 +
 +static void omap24xxcam_sensor_exit(struct omap24xxcam_device *cam)
 +{
 +      if (cam->sdev)
 +              vidioc_int_dev_exit(cam->sdev);
 +}
 +
 +static void omap24xxcam_sensor_disable(struct omap24xxcam_device *cam)
 +{
 +      omap24xxcam_sensor_if_disable(cam);
 +      omap24xxcam_clock_off(cam);
 +      vidioc_int_s_power(cam->sdev, 0);
 +}
 +
 +/*
 + * Power-up and configure camera sensor. It's ready for capturing now.
 + */
 +static int omap24xxcam_sensor_enable(struct omap24xxcam_device *cam)
 +{
 +      int rval;
 +
 +      omap24xxcam_clock_on(cam);
 +
 +      omap24xxcam_sensor_if_enable(cam);
 +
 +      rval = vidioc_int_s_power(cam->sdev, 1);
 +      if (rval)
 +              goto out;
 +
 +      rval = vidioc_int_init(cam->sdev);
 +      if (rval)
 +              goto out;
 +
 +      return 0;
 +
 +out:
 +      omap24xxcam_sensor_disable(cam);
 +
 +      return rval;
 +}
 +
 +static void omap24xxcam_sensor_reset_work(struct work_struct *work)
 +{
 +      struct omap24xxcam_device *cam =
 +              container_of(work, struct omap24xxcam_device,
 +                           sensor_reset_work);
 +
 +      if (atomic_read(&cam->reset_disable))
 +              return;
 +
 +      omap24xxcam_capture_stop(cam);
 +
 +      if (vidioc_int_reset(cam->sdev) == 0) {
 +              vidioc_int_init(cam->sdev);
 +      } else {
 +              /* Can't reset it by vidioc_int_reset. */
 +              omap24xxcam_sensor_disable(cam);
 +              omap24xxcam_sensor_enable(cam);
 +      }
 +
 +      omap24xxcam_capture_cont(cam);
 +}
 +
 +/*
 + *
 + * IOCTL interface.
 + *
 + */
 +
 +static int vidioc_querycap(struct file *file, void *fh,
 +                         struct v4l2_capability *cap)
 +{
 +      struct omap24xxcam_fh *ofh = fh;
 +      struct omap24xxcam_device *cam = ofh->cam;
 +
 +      strlcpy(cap->driver, CAM_NAME, sizeof(cap->driver));
 +      strlcpy(cap->card, cam->vfd->name, sizeof(cap->card));
 +      cap->version = OMAP24XXCAM_VERSION;
 +      cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
 +
 +      return 0;
 +}
 +
 +static int vidioc_enum_fmt_cap(struct file *file, void *fh,
 +                             struct v4l2_fmtdesc *f)
 +{
 +      struct omap24xxcam_fh *ofh = fh;
 +      struct omap24xxcam_device *cam = ofh->cam;
 +      int rval;
 +
 +      rval = vidioc_int_enum_fmt_cap(cam->sdev, f);
 +
 +      return rval;
 +}
 +
 +static int vidioc_g_fmt_cap(struct file *file, void *fh,
 +                          struct v4l2_format *f)
 +{
 +      struct omap24xxcam_fh *ofh = fh;
 +      struct omap24xxcam_device *cam = ofh->cam;
 +      int rval;
 +
 +      mutex_lock(&cam->mutex);
 +      rval = vidioc_int_g_fmt_cap(cam->sdev, f);
 +      mutex_unlock(&cam->mutex);
 +
 +      return rval;
 +}
 +
 +static int vidioc_s_fmt_cap(struct file *file, void *fh,
 +                          struct v4l2_format *f)
 +{
 +      struct omap24xxcam_fh *ofh = fh;
 +      struct omap24xxcam_device *cam = ofh->cam;
 +      int rval;
 +
 +      mutex_lock(&cam->mutex);
 +      if (cam->streaming) {
 +              rval = -EBUSY;
 +              goto out;
 +      }
 +
 +      rval = vidioc_int_s_fmt_cap(cam->sdev, f);
 +
 +out:
 +      mutex_unlock(&cam->mutex);
 +
 +      if (!rval) {
 +              mutex_lock(&ofh->vbq.vb_lock);
 +              ofh->pix = f->fmt.pix;
 +              mutex_unlock(&ofh->vbq.vb_lock);
 +      }
 +
 +      memset(f, 0, sizeof(*f));
 +      vidioc_g_fmt_cap(file, fh, f);
 +
 +      return rval;
 +}
 +
 +static int vidioc_try_fmt_cap(struct file *file, void *fh,
 +                            struct v4l2_format *f)
 +{
 +      struct omap24xxcam_fh *ofh = fh;
 +      struct omap24xxcam_device *cam = ofh->cam;
 +      int rval;
 +
 +      mutex_lock(&cam->mutex);
 +      rval = vidioc_int_try_fmt_cap(cam->sdev, f);
 +      mutex_unlock(&cam->mutex);
 +
 +      return rval;
 +}
 +
 +static int vidioc_reqbufs(struct file *file, void *fh,
 +                        struct v4l2_requestbuffers *b)
 +{
 +      struct omap24xxcam_fh *ofh = fh;
 +      struct omap24xxcam_device *cam = ofh->cam;
 +      int rval;
 +
 +      mutex_lock(&cam->mutex);
 +      if (cam->streaming) {
 +              mutex_unlock(&cam->mutex);
 +              return -EBUSY;
 +      }
 +
 +      omap24xxcam_vbq_free_mmap_buffers(&ofh->vbq);
 +      mutex_unlock(&cam->mutex);
 +
 +      rval = videobuf_reqbufs(&ofh->vbq, b);
 +
 +      /*
 +       * Either videobuf_reqbufs failed or the buffers are not
 +       * memory-mapped (which would need special attention).
 +       */
 +      if (rval < 0 || b->memory != V4L2_MEMORY_MMAP)
 +              goto out;
 +
 +      rval = omap24xxcam_vbq_alloc_mmap_buffers(&ofh->vbq, rval);
 +      if (rval)
 +              omap24xxcam_vbq_free_mmap_buffers(&ofh->vbq);
 +
 +out:
 +      return rval;
 +}
 +
 +static int vidioc_querybuf(struct file *file, void *fh,
 +                         struct v4l2_buffer *b)
 +{
 +      struct omap24xxcam_fh *ofh = fh;
 +
 +      return videobuf_querybuf(&ofh->vbq, b);
 +}
 +
 +static int vidioc_qbuf(struct file *file, void *fh, struct v4l2_buffer *b)
 +{
 +      struct omap24xxcam_fh *ofh = fh;
 +
 +      return videobuf_qbuf(&ofh->vbq, b);
 +}
 +
 +static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
 +{
 +      struct omap24xxcam_fh *ofh = fh;
 +      struct omap24xxcam_device *cam = ofh->cam;
 +      struct videobuf_buffer *vb;
 +      int rval;
 +
 +videobuf_dqbuf_again:
 +      rval = videobuf_dqbuf(&ofh->vbq, b, file->f_flags & O_NONBLOCK);
 +      if (rval)
 +              goto out;
 +
 +      vb = ofh->vbq.bufs[b->index];
 +
 +      mutex_lock(&cam->mutex);
 +      /* _needs_reset returns -EIO if reset is required. */
 +      rval = vidioc_int_g_needs_reset(cam->sdev, (void *)vb->baddr);
 +      mutex_unlock(&cam->mutex);
 +      if (rval == -EIO)
 +              schedule_work(&cam->sensor_reset_work);
 +      else
 +              rval = 0;
 +
 +out:
 +      /*
 +       * This is a hack. We don't want to show -EIO to the user
 +       * space. Requeue the buffer and try again if we're not doing
 +       * this in non-blocking mode.
 +       */
 +      if (rval == -EIO) {
 +              videobuf_qbuf(&ofh->vbq, b);
 +              if (!(file->f_flags & O_NONBLOCK))
 +                      goto videobuf_dqbuf_again;
 +              /*
 +               * We don't have a videobuf_buffer now --- maybe next
 +               * time...
 +               */
 +              rval = -EAGAIN;
 +      }
 +
 +      return rval;
 +}
 +
 +static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
 +{
 +      struct omap24xxcam_fh *ofh = fh;
 +      struct omap24xxcam_device *cam = ofh->cam;
 +      int rval;
 +
 +      mutex_lock(&cam->mutex);
 +      if (cam->streaming) {
 +              rval = -EBUSY;
 +              goto out;
 +      }
 +
 +      rval = omap24xxcam_sensor_if_enable(cam);
 +      if (rval) {
 +              dev_dbg(cam->dev, "vidioc_int_g_ifparm failed\n");
 +              goto out;
 +      }
 +
 +      rval = videobuf_streamon(&ofh->vbq);
 +      if (!rval) {
 +              cam->streaming = file;
 +              sysfs_notify(&cam->dev->kobj, NULL, "streaming");
 +      }
 +
 +out:
 +      mutex_unlock(&cam->mutex);
 +
 +      return rval;
 +}
 +
 +static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i)
 +{
 +      struct omap24xxcam_fh *ofh = fh;
 +      struct omap24xxcam_device *cam = ofh->cam;
 +      struct videobuf_queue *q = &ofh->vbq;
 +      int rval;
 +
 +      atomic_inc(&cam->reset_disable);
 +
 +      flush_scheduled_work();
 +
 +      rval = videobuf_streamoff(q);
 +      if (!rval) {
 +              mutex_lock(&cam->mutex);
 +              cam->streaming = NULL;
 +              mutex_unlock(&cam->mutex);
 +              sysfs_notify(&cam->dev->kobj, NULL, "streaming");
 +      }
 +
 +      atomic_dec(&cam->reset_disable);
 +
 +      return rval;
 +}
 +
 +static int vidioc_enum_input(struct file *file, void *fh,
 +                           struct v4l2_input *inp)
 +{
 +      if (inp->index > 0)
 +              return -EINVAL;
 +
 +      strlcpy(inp->name, "camera", sizeof(inp->name));
 +      inp->type = V4L2_INPUT_TYPE_CAMERA;
 +
 +      return 0;
 +}
 +
 +static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
 +{
 +      *i = 0;
 +
 +      return 0;
 +}
 +
 +static int vidioc_s_input(struct file *file, void *fh, unsigned int i)
 +{
 +      if (i > 0)
 +              return -EINVAL;
 +
 +      return 0;
 +}
 +
 +static int vidioc_queryctrl(struct file *file, void *fh,
 +                          struct v4l2_queryctrl *a)
 +{
 +      struct omap24xxcam_fh *ofh = fh;
 +      struct omap24xxcam_device *cam = ofh->cam;
 +      int rval;
 +
 +      rval = vidioc_int_queryctrl(cam->sdev, a);
 +
 +      return rval;
 +}
 +
 +static int vidioc_g_ctrl(struct file *file, void *fh,
 +                       struct v4l2_control *a)
 +{
 +      struct omap24xxcam_fh *ofh = fh;
 +      struct omap24xxcam_device *cam = ofh->cam;
 +      int rval;
 +
 +      mutex_lock(&cam->mutex);
 +      rval = vidioc_int_g_ctrl(cam->sdev, a);
 +      mutex_unlock(&cam->mutex);
 +
 +      return rval;
 +}
 +
 +static int vidioc_s_ctrl(struct file *file, void *fh,
 +                       struct v4l2_control *a)
 +{
 +      struct omap24xxcam_fh *ofh = fh;
 +      struct omap24xxcam_device *cam = ofh->cam;
 +      int rval;
 +
 +      mutex_lock(&cam->mutex);
 +      rval = vidioc_int_s_ctrl(cam->sdev, a);
 +      mutex_unlock(&cam->mutex);
 +
 +      return rval;
 +}
 +
 +static int vidioc_g_parm(struct file *file, void *fh,
 +                       struct v4l2_streamparm *a) {
 +      struct omap24xxcam_fh *ofh = fh;
 +      struct omap24xxcam_device *cam = ofh->cam;
 +      int rval;
 +
 +      if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 +              return -EINVAL;
 +
 +      mutex_lock(&cam->mutex);
 +      rval = vidioc_int_g_parm(cam->sdev, a);
 +      mutex_unlock(&cam->mutex);
 +
 +      return rval;
 +}
 +
 +static int vidioc_s_parm(struct file *file, void *fh,
 +                       struct v4l2_streamparm *a)
 +{
 +      struct omap24xxcam_fh *ofh = fh;
 +      struct omap24xxcam_device *cam = ofh->cam;
 +      struct v4l2_streamparm old_streamparm;
 +      int rval;
 +
 +      if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 +              return -EINVAL;
 +
 +      mutex_lock(&cam->mutex);
 +      if (cam->streaming) {
 +              rval = -EBUSY;
 +              goto out;
 +      }
 +
 +      old_streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 +      rval = vidioc_int_g_parm(cam->sdev, &old_streamparm);
 +      if (rval)
 +              goto out;
 +
 +      rval = vidioc_int_s_parm(cam->sdev, a);
 +      if (rval)
 +              goto out;
 +
 +      rval = omap24xxcam_sensor_if_enable(cam);
 +      /*
 +       * Revert to old streaming parameters if enabling sensor
 +       * interface with the new ones failed.
 +       */
 +      if (rval)
 +              vidioc_int_s_parm(cam->sdev, &old_streamparm);
 +
 +out:
 +      mutex_unlock(&cam->mutex);
 +
 +      return rval;
 +}
 +
 +/*
 + *
 + * File operations.
 + *
 + */
 +
 +static unsigned int omap24xxcam_poll(struct file *file,
 +                                   struct poll_table_struct *wait)
 +{
 +      struct omap24xxcam_fh *fh = file->private_data;
 +      struct omap24xxcam_device *cam = fh->cam;
 +      struct videobuf_buffer *vb;
 +
 +      mutex_lock(&cam->mutex);
 +      if (cam->streaming != file) {
 +              mutex_unlock(&cam->mutex);
 +              return POLLERR;
 +      }
 +      mutex_unlock(&cam->mutex);
 +
 +      mutex_lock(&fh->vbq.vb_lock);
 +      if (list_empty(&fh->vbq.stream)) {
 +              mutex_unlock(&fh->vbq.vb_lock);
 +              return POLLERR;
 +      }
 +      vb = list_entry(fh->vbq.stream.next, struct videobuf_buffer, stream);
 +      mutex_unlock(&fh->vbq.vb_lock);
 +
 +      poll_wait(file, &vb->done, wait);
 +
 +      if (vb->state == VIDEOBUF_DONE || vb->state == VIDEOBUF_ERROR)
 +              return POLLIN | POLLRDNORM;
 +
 +      return 0;
 +}
 +
 +static int omap24xxcam_mmap_buffers(struct file *file,
 +                                  struct vm_area_struct *vma)
 +{
 +      struct omap24xxcam_fh *fh = file->private_data;
 +      struct omap24xxcam_device *cam = fh->cam;
 +      struct videobuf_queue *vbq = &fh->vbq;
 +      unsigned int first, last, size, i, j;
 +      int err = 0;
 +
 +      mutex_lock(&cam->mutex);
 +      if (cam->streaming) {
 +              mutex_unlock(&cam->mutex);
 +              return -EBUSY;
 +      }
 +      mutex_unlock(&cam->mutex);
 +      mutex_lock(&vbq->vb_lock);
 +
 +      /* look for first buffer to map */
 +      for (first = 0; first < VIDEO_MAX_FRAME; first++) {
 +              if (NULL == vbq->bufs[first])
 +                      continue;
 +              if (V4L2_MEMORY_MMAP != vbq->bufs[first]->memory)
 +                      continue;
 +              if (vbq->bufs[first]->boff == (vma->vm_pgoff << PAGE_SHIFT))
 +                      break;
 +      }
 +
 +      /* look for last buffer to map */
 +      for (size = 0, last = first; last < VIDEO_MAX_FRAME; last++) {
 +              if (NULL == vbq->bufs[last])
 +                      continue;
 +              if (V4L2_MEMORY_MMAP != vbq->bufs[last]->memory)
 +                      continue;
 +              size += vbq->bufs[last]->bsize;
 +              if (size == (vma->vm_end - vma->vm_start))
 +                      break;
 +      }
 +
 +      size = 0;
 +      for (i = first; i <= last; i++) {
 +              struct videobuf_dmabuf *dma = videobuf_to_dma(vbq->bufs[i]);
 +
 +              for (j = 0; j < dma->sglen; j++) {
 +                      err = remap_pfn_range(
 +                              vma, vma->vm_start + size,
 +                              page_to_pfn(sg_page(&dma->sglist[j])),
 +                              sg_dma_len(&dma->sglist[j]), vma->vm_page_prot);
 +                      if (err)
 +                              goto out;
 +                      size += sg_dma_len(&dma->sglist[j]);
 +              }
 +      }
 +
 +out:
 +      mutex_unlock(&vbq->vb_lock);
 +
 +      return err;
 +}
 +
 +static int omap24xxcam_mmap(struct file *file, struct vm_area_struct *vma)
 +{
 +      struct omap24xxcam_fh *fh = file->private_data;
 +      int rval;
 +
 +      /* let the video-buf mapper check arguments and set-up structures */
 +      rval = videobuf_mmap_mapper(&fh->vbq, vma);
 +      if (rval)
 +              return rval;
 +
 +      vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 +
 +      /* do mapping to our allocated buffers */
 +      rval = omap24xxcam_mmap_buffers(file, vma);
 +      /*
 +       * In case of error, free vma->vm_private_data allocated by
 +       * videobuf_mmap_mapper.
 +       */
 +      if (rval)
 +              kfree(vma->vm_private_data);
 +
 +      return rval;
 +}
 +
 +static int omap24xxcam_open(struct inode *inode, struct file *file)
 +{
 +      int minor = iminor(inode);
 +      struct omap24xxcam_device *cam = omap24xxcam.priv;
 +      struct omap24xxcam_fh *fh;
 +      struct v4l2_format format;
 +
 +      if (!cam || !cam->vfd || (cam->vfd->minor != minor))
 +              return -ENODEV;
 +
 +      fh = kzalloc(sizeof(*fh), GFP_KERNEL);
 +      if (fh == NULL)
 +              return -ENOMEM;
 +
 +      mutex_lock(&cam->mutex);
 +      if (cam->sdev == NULL || !try_module_get(cam->sdev->module)) {
 +              mutex_unlock(&cam->mutex);
 +              goto out_try_module_get;
 +      }
 +
 +      if (atomic_inc_return(&cam->users) == 1) {
 +              omap24xxcam_hwinit(cam);
 +              if (omap24xxcam_sensor_enable(cam)) {
 +                      mutex_unlock(&cam->mutex);
 +                      goto out_omap24xxcam_sensor_enable;
 +              }
 +      }
 +      mutex_unlock(&cam->mutex);
 +
 +      fh->cam = cam;
 +      mutex_lock(&cam->mutex);
 +      vidioc_int_g_fmt_cap(cam->sdev, &format);
 +      mutex_unlock(&cam->mutex);
 +      /* FIXME: how about fh->pix when there are more users? */
 +      fh->pix = format.fmt.pix;
 +
 +      file->private_data = fh;
 +
 +      spin_lock_init(&fh->vbq_lock);
 +
 +      videobuf_queue_sg_init(&fh->vbq, &omap24xxcam_vbq_ops, NULL,
 +                              &fh->vbq_lock, V4L2_BUF_TYPE_VIDEO_CAPTURE,
 +                              V4L2_FIELD_NONE,
 +                              sizeof(struct videobuf_buffer), fh);
 +
 +      return 0;
 +
 +out_omap24xxcam_sensor_enable:
 +      omap24xxcam_poweron_reset(cam);
 +      module_put(cam->sdev->module);
 +
 +out_try_module_get:
 +      kfree(fh);
 +
 +      return -ENODEV;
 +}
 +
 +static int omap24xxcam_release(struct inode *inode, struct file *file)
 +{
 +      struct omap24xxcam_fh *fh = file->private_data;
 +      struct omap24xxcam_device *cam = fh->cam;
 +
 +      atomic_inc(&cam->reset_disable);
 +
 +      flush_scheduled_work();
 +
 +      /* stop streaming capture */
 +      videobuf_streamoff(&fh->vbq);
 +
 +      mutex_lock(&cam->mutex);
 +      if (cam->streaming == file) {
 +              cam->streaming = NULL;
 +              mutex_unlock(&cam->mutex);
 +              sysfs_notify(&cam->dev->kobj, NULL, "streaming");
 +      } else {
 +              mutex_unlock(&cam->mutex);
 +      }
 +
 +      atomic_dec(&cam->reset_disable);
 +
 +      omap24xxcam_vbq_free_mmap_buffers(&fh->vbq);
 +
 +      /*
 +       * Make sure the reset work we might have scheduled is not
 +       * pending! It may be run *only* if we have users. (And it may
 +       * not be scheduled anymore since streaming is already
 +       * disabled.)
 +       */
 +      flush_scheduled_work();
 +
 +      mutex_lock(&cam->mutex);
 +      if (atomic_dec_return(&cam->users) == 0) {
 +              omap24xxcam_sensor_disable(cam);
 +              omap24xxcam_poweron_reset(cam);
 +      }
 +      mutex_unlock(&cam->mutex);
 +
 +      file->private_data = NULL;
 +
 +      module_put(cam->sdev->module);
 +      kfree(fh);
 +
 +      return 0;
 +}
 +
 +static struct file_operations omap24xxcam_fops = {
 +      .llseek  = no_llseek,
 +      .ioctl   = video_ioctl2,
 +      .poll    = omap24xxcam_poll,
 +      .mmap    = omap24xxcam_mmap,
 +      .open    = omap24xxcam_open,
 +      .release = omap24xxcam_release,
 +};
 +
 +/*
 + *
 + * Power management.
 + *
 + */
 +
 +#ifdef CONFIG_PM
 +static int omap24xxcam_suspend(struct platform_device *pdev, pm_message_t state)
 +{
 +      struct omap24xxcam_device *cam = platform_get_drvdata(pdev);
 +
 +      if (atomic_read(&cam->users) == 0)
 +              return 0;
 +
 +      if (!atomic_read(&cam->reset_disable))
 +              omap24xxcam_capture_stop(cam);
 +
 +      omap24xxcam_sensor_disable(cam);
 +      omap24xxcam_poweron_reset(cam);
 +
 +      return 0;
 +}
 +
 +static int omap24xxcam_resume(struct platform_device *pdev)
 +{
 +      struct omap24xxcam_device *cam = platform_get_drvdata(pdev);
 +
 +      if (atomic_read(&cam->users) == 0)
 +              return 0;
 +
 +      omap24xxcam_hwinit(cam);
 +      omap24xxcam_sensor_enable(cam);
 +
 +      if (!atomic_read(&cam->reset_disable))
 +              omap24xxcam_capture_cont(cam);
 +
 +      return 0;
 +}
 +#endif /* CONFIG_PM */
 +
 +/*
 + *
 + * Camera device (i.e. /dev/video).
 + *
 + */
 +
 +static int omap24xxcam_device_register(struct v4l2_int_device *s)
 +{
 +      struct omap24xxcam_device *cam = s->u.slave->master->priv;
 +      struct video_device *vfd;
 +      int rval;
 +
 +      /* We already have a slave. */
 +      if (cam->sdev)
 +              return -EBUSY;
 +
 +      cam->sdev = s;
 +
 +      if (device_create_file(cam->dev, &dev_attr_streaming) != 0) {
 +              dev_err(cam->dev, "could not register sysfs entry\n");
 +              rval = -EBUSY;
 +              goto err;
 +      }
 +
 +      /* initialize the video_device struct */
 +      vfd = cam->vfd = video_device_alloc();
 +      if (!vfd) {
 +              dev_err(cam->dev, "could not allocate video device struct\n");
 +              rval = -ENOMEM;
 +              goto err;
 +      }
 +      vfd->release = video_device_release;
 +
 +      vfd->dev = cam->dev;
 +
 +      strlcpy(vfd->name, CAM_NAME, sizeof(vfd->name));
 +      vfd->type                = VID_TYPE_CAPTURE | VID_TYPE_CHROMAKEY;
 +      vfd->fops                = &omap24xxcam_fops;
 +      vfd->priv                = cam;
 +      vfd->minor               = -1;
 +
 +      vfd->vidioc_querycap     = vidioc_querycap;
 +      vfd->vidioc_enum_fmt_cap = vidioc_enum_fmt_cap;
 +      vfd->vidioc_g_fmt_cap    = vidioc_g_fmt_cap;
 +      vfd->vidioc_s_fmt_cap    = vidioc_s_fmt_cap;
 +      vfd->vidioc_try_fmt_cap  = vidioc_try_fmt_cap;
 +      vfd->vidioc_reqbufs      = vidioc_reqbufs;
 +      vfd->vidioc_querybuf     = vidioc_querybuf;
 +      vfd->vidioc_qbuf         = vidioc_qbuf;
 +      vfd->vidioc_dqbuf        = vidioc_dqbuf;
 +      vfd->vidioc_streamon     = vidioc_streamon;
 +      vfd->vidioc_streamoff    = vidioc_streamoff;
 +      vfd->vidioc_enum_input   = vidioc_enum_input;
 +      vfd->vidioc_g_input      = vidioc_g_input;
 +      vfd->vidioc_s_input      = vidioc_s_input;
 +      vfd->vidioc_queryctrl    = vidioc_queryctrl;
 +      vfd->vidioc_g_ctrl       = vidioc_g_ctrl;
 +      vfd->vidioc_s_ctrl       = vidioc_s_ctrl;
 +      vfd->vidioc_g_parm       = vidioc_g_parm;
 +      vfd->vidioc_s_parm       = vidioc_s_parm;
 +
 +      omap24xxcam_hwinit(cam);
 +
 +      rval = omap24xxcam_sensor_init(cam);
 +      if (rval)
 +              goto err;
 +
 +      if (video_register_device(vfd, VFL_TYPE_GRABBER, video_nr) < 0) {
 +              dev_err(cam->dev, "could not register V4L device\n");
 +              vfd->minor = -1;
 +              rval = -EBUSY;
 +              goto err;
 +      }
 +
 +      omap24xxcam_poweron_reset(cam);
 +
 +      dev_info(cam->dev, "registered device video%d\n", vfd->minor);
 +
 +      return 0;
 +
 +err:
 +      omap24xxcam_device_unregister(s);
 +
 +      return rval;
 +}
 +
 +static void omap24xxcam_device_unregister(struct v4l2_int_device *s)
 +{
 +      struct omap24xxcam_device *cam = s->u.slave->master->priv;
 +
 +      omap24xxcam_sensor_exit(cam);
 +
 +      if (cam->vfd) {
 +              if (cam->vfd->minor == -1) {
 +                      /*
 +                       * The device was never registered, so release the
 +                       * video_device struct directly.
 +                       */
 +                      video_device_release(cam->vfd);
 +              } else {
 +                      /*
 +                       * The unregister function will release the
 +                       * video_device struct as well as
 +                       * unregistering it.
 +                       */
 +                      video_unregister_device(cam->vfd);
 +              }
 +              cam->vfd = NULL;
 +      }
 +
 +      device_remove_file(cam->dev, &dev_attr_streaming);
 +
 +      cam->sdev = NULL;
 +}
 +
 +static struct v4l2_int_master omap24xxcam_master = {
 +      .attach = omap24xxcam_device_register,
 +      .detach = omap24xxcam_device_unregister,
 +};
 +
 +static struct v4l2_int_device omap24xxcam = {
 +      .module = THIS_MODULE,
 +      .name   = CAM_NAME,
 +      .type   = v4l2_int_type_master,
 +      .u      = {
 +              .master = &omap24xxcam_master
 +      },
 +};
 +
 +/*
 + *
 + * Driver initialisation and deinitialisation.
 + *
 + */
 +
 +static int __init omap24xxcam_probe(struct platform_device *pdev)
 +{
 +      struct omap24xxcam_device *cam;
 +      struct resource *mem;
 +      int irq;
 +
 +      cam = kzalloc(sizeof(*cam), GFP_KERNEL);
 +      if (!cam) {
 +              dev_err(&pdev->dev, "could not allocate memory\n");
 +              goto err;
 +      }
 +
 +      platform_set_drvdata(pdev, cam);
 +
 +      cam->dev = &pdev->dev;
 +
 +      /*
 +       * Impose a lower limit on the amount of memory allocated for
 +       * capture. We require at least enough memory to double-buffer
 +       * QVGA (300KB).
 +       */
 +      if (capture_mem < 320 * 240 * 2 * 2)
 +              capture_mem = 320 * 240 * 2 * 2;
 +      cam->capture_mem = capture_mem;
 +
 +      /* request the mem region for the camera registers */
 +      mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 +      if (!mem) {
 +              dev_err(cam->dev, "no mem resource?\n");
 +              goto err;
 +      }
 +      if (!request_mem_region(mem->start, (mem->end - mem->start) + 1,
 +                              pdev->name)) {
 +              dev_err(cam->dev,
 +                      "cannot reserve camera register I/O region\n");
 +              goto err;
 +      }
 +      cam->mmio_base_phys = mem->start;
 +      cam->mmio_size = (mem->end - mem->start) + 1;
 +
 +      /* map the region */
 +      cam->mmio_base = (unsigned long)
 +              ioremap_nocache(cam->mmio_base_phys, cam->mmio_size);
 +      if (!cam->mmio_base) {
 +              dev_err(cam->dev, "cannot map camera register I/O region\n");
 +              goto err;
 +      }
 +
 +      irq = platform_get_irq(pdev, 0);
 +      if (irq <= 0) {
 +              dev_err(cam->dev, "no irq for camera?\n");
 +              goto err;
 +      }
 +
 +      /* install the interrupt service routine */
 +      if (request_irq(irq, omap24xxcam_isr, 0, CAM_NAME, cam)) {
 +              dev_err(cam->dev,
 +                      "could not install interrupt service routine\n");
 +              goto err;
 +      }
 +      cam->irq = irq;
 +
 +      if (omap24xxcam_clock_get(cam))
 +              goto err;
 +
 +      INIT_WORK(&cam->sensor_reset_work, omap24xxcam_sensor_reset_work);
 +
 +      mutex_init(&cam->mutex);
 +      spin_lock_init(&cam->core_enable_disable_lock);
 +
 +      omap24xxcam_sgdma_init(&cam->sgdma,
 +                             cam->mmio_base + CAMDMA_REG_OFFSET,
 +                             omap24xxcam_stalled_dma_reset,
 +                             (unsigned long)cam);
 +
 +      omap24xxcam.priv = cam;
 +
 +      if (v4l2_int_device_register(&omap24xxcam))
 +              goto err;
 +
 +      return 0;
 +
 +err:
 +      omap24xxcam_remove(pdev);
 +      return -ENODEV;
 +}
 +
 +static int omap24xxcam_remove(struct platform_device *pdev)
 +{
 +      struct omap24xxcam_device *cam = platform_get_drvdata(pdev);
 +
 +      if (!cam)
 +              return 0;
 +
 +      if (omap24xxcam.priv != NULL)
 +              v4l2_int_device_unregister(&omap24xxcam);
 +      omap24xxcam.priv = NULL;
 +
 +      omap24xxcam_clock_put(cam);
 +
 +      if (cam->irq) {
 +              free_irq(cam->irq, cam);
 +              cam->irq = 0;
 +      }
 +
 +      if (cam->mmio_base) {
 +              iounmap((void *)cam->mmio_base);
 +              cam->mmio_base = 0;
 +      }
 +
 +      if (cam->mmio_base_phys) {
 +              release_mem_region(cam->mmio_base_phys, cam->mmio_size);
 +              cam->mmio_base_phys = 0;
 +      }
 +
 +      kfree(cam);
 +
 +      return 0;
 +}
 +
 +static struct platform_driver omap24xxcam_driver = {
 +      .probe   = omap24xxcam_probe,
 +      .remove  = omap24xxcam_remove,
 +#ifdef CONFIG_PM
 +      .suspend = omap24xxcam_suspend,
 +      .resume  = omap24xxcam_resume,
 +#endif
 +      .driver  = {
 +              .name = CAM_NAME,
 +      },
 +};
 +
 +/*
 + *
 + * Module initialisation and deinitialisation
 + *
 + */
 +
 +static int __init omap24xxcam_init(void)
 +{
 +      return platform_driver_register(&omap24xxcam_driver);
 +}
 +
 +static void __exit omap24xxcam_cleanup(void)
 +{
 +      platform_driver_unregister(&omap24xxcam_driver);
 +}
 +
 +MODULE_AUTHOR("Sakari Ailus <sakari.ailus@nokia.com>");
 +MODULE_DESCRIPTION("OMAP24xx Video for Linux camera driver");
 +MODULE_LICENSE("GPL");
 +module_param(video_nr, int, 0);
 +MODULE_PARM_DESC(video_nr,
 +               "Minor number for video device (-1 ==> auto assign)");
 +module_param(capture_mem, int, 0);
 +MODULE_PARM_DESC(capture_mem, "Maximum amount of memory for capture "
 +               "buffers (default 4800kiB)");
 +
 +module_init(omap24xxcam_init);
 +module_exit(omap24xxcam_cleanup);
diff --combined drivers/misc/Kconfig
index 4885d2dc6f58ebf3c3615bd525f9c2459a9f667d,82af385460e4711643e79914cbe16ca1bff7e88e..e895bf7282c67b91b0508b8327ec47f6f402b24a
@@@ -77,11 -77,13 +77,13 @@@ config IBM_AS
          for your IBM server.
  
  config PHANTOM
-       tristate "Sensable PHANToM"
+       tristate "Sensable PHANToM (PCI)"
        depends on PCI
        help
          Say Y here if you want to build a driver for Sensable PHANToM device.
  
+         This driver is only for PCI PHANToMs.
          If you choose to build module, its name will be phantom. If unsure,
          say N here.
  
@@@ -179,17 -181,29 +181,29 @@@ config FUJITSU_LAPTO
          tristate "Fujitsu Laptop Extras"
          depends on X86
          depends on ACPI
+       depends on INPUT
          depends on BACKLIGHT_CLASS_DEVICE
          ---help---
          This is a driver for laptops built by Fujitsu:
  
            * P2xxx/P5xxx/S6xxx/S7xxx series Lifebooks
            * Possibly other Fujitsu laptop models
+           * Tested with S6410 and S7020
  
-         It adds support for LCD brightness control.
+         It adds support for LCD brightness control and some hotkeys.
  
          If you have a Fujitsu laptop, say Y or M here.
  
+ config FUJITSU_LAPTOP_DEBUG
+       bool "Verbose debug mode for Fujitsu Laptop Extras"
+       depends on FUJITSU_LAPTOP
+       default n
+       ---help---
+         Enables extra debug output from the fujitsu extras driver, at the
+         expense of a slight increase in driver size.
+         If you are not sure, say N here.
  config TC1100_WMI
        tristate "HP Compaq TC1100 Tablet WMI Extras (EXPERIMENTAL)"
        depends on X86 && !X86_64
          This is a driver for the WMI extensions (wireless and bluetooth power
          control) of the HP Compaq TC1100 tablet.
  
+ config HP_WMI
+        tristate "HP WMI extras"
+        depends on ACPI_WMI
+        depends on INPUT
+        depends on RFKILL
+        help
+          Say Y here if you want to support WMI-based hotkeys on HP laptops and
+        to read data from WMI such as docking or ambient light sensor state.
+          To compile this driver as a module, choose M here: the module will
+          be called hp-wmi.
  config MSI_LAPTOP
          tristate "MSI Laptop Extras"
          depends on X86
  
          If you have an MSI S270 laptop, say Y or M here.
  
+ config COMPAL_LAPTOP
+       tristate "Compal Laptop Extras"
+       depends on X86
+       depends on ACPI_EC
+       depends on BACKLIGHT_CLASS_DEVICE
+       ---help---
+         This is a driver for laptops built by Compal:
+         Compal FL90/IFL90
+         Compal FL91/IFL91
+         Compal FL92/JFL92
+         Compal FT00/IFT00
+         It adds support for Bluetooth, WLAN and LCD brightness control.
+         If you have an Compal FL9x/IFL9x/FT00 laptop, say Y or M here.
  config SONY_LAPTOP
        tristate "Sony Laptop Extras"
        depends on X86 && ACPI
@@@ -250,6 -293,8 +293,8 @@@ config THINKPAD_ACP
        select INPUT
        select NEW_LEDS
        select LEDS_CLASS
+       select NET
+       select RFKILL
        ---help---
          This is a driver for the IBM and Lenovo ThinkPad laptops. It adds
          support for Fn-Fx key combinations, Bluetooth control, video
@@@ -315,7 -360,7 +360,7 @@@ config THINKPAD_ACPI_VIDE
          If you are not sure, say Y here.
  
  config THINKPAD_ACPI_HOTKEY_POLL
-       bool "Suport NVRAM polling for hot keys"
+       bool "Support NVRAM polling for hot keys"
        depends on THINKPAD_ACPI
        default y
        ---help---
@@@ -364,24 -409,11 +409,24 @@@ config EEEPC_LAPTO
        depends on BACKLIGHT_CLASS_DEVICE
        depends on HWMON
        depends on EXPERIMENTAL
 +
        ---help---
          This driver supports the Fn-Fx keys on Eee PC laptops.
          It also adds the ability to switch camera/wlan on/off.
  
 -        If you have an Eee PC laptop, say Y or M here.
 +config OMAP_STI
 +      bool "Serial Trace Interface support"
 +      depends on ARCH_OMAP16XX || ARCH_OMAP24XX || ARCH_OMAP34XX
 +      default n
 +      help
 +        Serial Trace Interface. The protocols suported for OMAP1/2/3 are
 +        STI/CSTI/XTIv2 correspondingly.
 +
 +config OMAP_STI_CONSOLE
 +      bool "STI console support"
 +      depends on OMAP_STI
 +      help
 +        This enables a console driver by way of STI/XTI.
  
  config ENCLOSURE_SERVICES
        tristate "Enclosure Services"
  
  config SGI_XP
        tristate "Support communication between SGI SSIs"
-       depends on IA64_GENERIC || IA64_SGI_SN2
+       depends on NET
+       depends on IA64_GENERIC || IA64_SGI_SN2 || IA64_SGI_UV || (X86_64 && SMP)
        select IA64_UNCACHED_ALLOCATOR if IA64_GENERIC || IA64_SGI_SN2
        select GENERIC_ALLOCATOR if IA64_GENERIC || IA64_SGI_SN2
+       select SGI_GRU if IA64_GENERIC || IA64_SGI_UV || (X86_64 && SMP)
        ---help---
          An SGI machine can be divided into multiple Single System
          Images which act independently of each other and have
          this feature will allow for direct communication between SSIs
          based on a network adapter and DMA messaging.
  
+ config HP_ILO
+       tristate "Channel interface driver for HP iLO/iLO2 processor"
+       depends on PCI
+       default n
+       help
+         The channel interface driver allows applications to communicate
+         with iLO/iLO2 management processors present on HP ProLiant
+         servers.  Upon loading, the driver creates /dev/hpilo/dXccbN files,
+         which can be used to gather data from the management processor,
+         via read and write system calls.
+         To compile this driver as a module, choose M here: the
+         module will be called hpilo.
+ config SGI_GRU
+       tristate "SGI GRU driver"
+       depends on (X86_64 || IA64_SGI_UV || IA64_GENERIC) && SMP
+       default n
+       select MMU_NOTIFIER
+       ---help---
+       The GRU is a hardware resource located in the system chipset. The GRU
+       contains memory that can be mmapped into the user address space. This memory is
+       used to communicate with the GRU to perform functions such as load/store,
+       scatter/gather, bcopy, AMOs, etc.  The GRU is directly accessed by user
+       instructions using user virtual addresses. GRU instructions (ex., bcopy) use
+       user virtual addresses for operands.
+       If you are not running on a SGI UV system, say N.
+ config SGI_GRU_DEBUG
+       bool  "SGI GRU driver debug"
+       depends on SGI_GRU
+       default n
+       ---help---
+       This option enables addition debugging code for the SGI GRU driver. If
+       you are unsure, say N.
  endif # MISC_DEVICES
diff --combined drivers/misc/Makefile
index 2649528f06d5f5b6c2e0cc957792ea6187bdd31c,c6c13f60b4520124f7ce918069f37cdbda6e7806..b6167e79df77eb633938898b0ad3ab3ea0a8c439
@@@ -5,14 -5,15 +5,16 @@@ obj- := misc.o        # Dummy rule to force bu
  
  obj-$(CONFIG_IBM_ASM)         += ibmasm/
  obj-$(CONFIG_HDPU_FEATURES)   += hdpuftrs/
- obj-$(CONFIG_MSI_LAPTOP)     += msi-laptop.o
- obj-$(CONFIG_ACER_WMI)     += acer-wmi.o
 +obj-$(CONFIG_OMAP_STI)                += sti/
  obj-$(CONFIG_ASUS_LAPTOP)     += asus-laptop.o
  obj-$(CONFIG_EEEPC_LAPTOP)    += eeepc-laptop.o
+ obj-$(CONFIG_MSI_LAPTOP)      += msi-laptop.o
+ obj-$(CONFIG_COMPAL_LAPTOP)   += compal-laptop.o
+ obj-$(CONFIG_ACER_WMI)                += acer-wmi.o
  obj-$(CONFIG_ATMEL_PWM)               += atmel_pwm.o
  obj-$(CONFIG_ATMEL_SSC)               += atmel-ssc.o
  obj-$(CONFIG_ATMEL_TCLIB)     += atmel_tclib.o
+ obj-$(CONFIG_HP_WMI)          += hp-wmi.o
  obj-$(CONFIG_TC1100_WMI)      += tc1100-wmi.o
  obj-$(CONFIG_LKDTM)           += lkdtm.o
  obj-$(CONFIG_TIFM_CORE)               += tifm_core.o
@@@ -27,3 -28,5 +29,5 @@@ obj-$(CONFIG_INTEL_MENLOW)    += intel_men
  obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o
  obj-$(CONFIG_KGDB_TESTS)      += kgdbts.o
  obj-$(CONFIG_SGI_XP)          += sgi-xp/
+ obj-$(CONFIG_SGI_GRU)         += sgi-gru/
+ obj-$(CONFIG_HP_ILO)          += hpilo.o
diff --combined drivers/mmc/host/Kconfig
index 39a2d92ccbbb599d79475257cf7f00f0c68aa340,dc6f2579f85cd81f31e4b1316d2b7d7ba69a127a..76eebaa69b9294a200617e42a1b2078d4712e119
@@@ -26,18 -26,31 +26,31 @@@ config MMC_PX
  
  config MMC_SDHCI
        tristate "Secure Digital Host Controller Interface support"
-       depends on PCI
+       depends on HAS_DMA
        help
-         This select the generic Secure Digital Host Controller Interface.
+         This selects the generic Secure Digital Host Controller Interface.
          It is used by manufacturers such as Texas Instruments(R), Ricoh(R)
          and Toshiba(R). Most controllers found in laptops are of this type.
+         If you have a controller with this interface, say Y or M here. You
+         also need to enable an appropriate bus interface.
+         If unsure, say N.
+ config MMC_SDHCI_PCI
+       tristate "SDHCI support on PCI bus"
+       depends on MMC_SDHCI && PCI
+       help
+         This selects the PCI Secure Digital Host Controller Interface.
+         Most controllers found today are PCI devices.
          If you have a controller with this interface, say Y or M here.
  
          If unsure, say N.
  
  config MMC_RICOH_MMC
        tristate "Ricoh MMC Controller Disabler  (EXPERIMENTAL)"
-       depends on PCI && EXPERIMENTAL && MMC_SDHCI
+       depends on MMC_SDHCI_PCI
        help
          This selects the disabler for the Ricoh MMC Controller. This
          proprietary controller is unnecessary because the SDHCI driver
  
  config MMC_OMAP
        tristate "TI OMAP Multimedia Card Interface support"
 -      depends on ARCH_OMAP
 +      depends on ARCH_OMAP1 || (ARCH_OMAP2 && ARCH_OMAP2420)
        select TPS65010 if MACH_OMAP_H2
 +      select OMAP_GPIO_SWITCH if MACH_NOKIA_N800
        help
          This selects the TI OMAP Multimedia card Interface.
          If you have an OMAP board with a Multimedia Card slot,
          say Y or M here.
  
          If unsure, say N.
 +
 +config MMC_OMAP_HS
 +      tristate "TI OMAP High Speed Multimedia Card Interface support"
 +      depends on (ARCH_OMAP2 && ARCH_OMAP2430) || ARCH_OMAP3
 +      select TWL4030_CORE if MACH_OMAP_2430SDP || MACH_OMAP_3430SDP
 +      help
 +        This selects the TI OMAP High Speed Multimedia card Interface.
 +        If you have an OMAP2(2430) or OMAP3 board 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"
@@@ -103,6 -104,16 +116,16 @@@ config MMC_AT9
  
          If unsure, say N.
  
+ config MMC_ATMELMCI
+       tristate "Atmel Multimedia Card Interface support"
+       depends on AVR32
+       help
+         This selects the Atmel Multimedia Card Interface driver. If
+         you have an AT32 (AVR32) platform with a Multimedia Card
+         slot, say Y or M here.
+         If unsure, say N.
  config MMC_IMX
        tristate "Motorola i.MX Multimedia Card Interface support"
        depends on ARCH_IMX
@@@ -142,3 -153,24 +165,24 @@@ config MMC_SP
  
          If unsure, or if your system has no SPI master driver, say N.
  
+ config MMC_S3C
+       tristate "Samsung S3C SD/MMC Card Interface support"
+       depends on ARCH_S3C2410 && MMC
+       help
+         This selects a driver for the MCI interface found in
+           Samsung's S3C2410, S3C2412, S3C2440, S3C2442 CPUs.
+         If you have a board based on one of those and a MMC/SD
+         slot, say Y or M here.
+         If unsure, say N.
+ config MMC_SDRICOH_CS
+       tristate "MMC/SD driver for Ricoh Bay1Controllers (EXPERIMENTAL)"
+       depends on EXPERIMENTAL && MMC && PCI && PCMCIA
+       help
+         Say Y here if your Notebook reports a Ricoh Bay1Controller PCMCIA
+         card whenever you insert a MMC or SD card into the card slot.
+         To compile this driver as a module, choose M here: the
+         module will be called sdricoh_cs.
index d4d72f56ab78faa84c5c6e45dcb1e0c642948005,db52eebfb50ee77e04705e9bb1aca3ab0c29b7ea..6a10b43583b208b200b5b2befb4ca89dcb661ef4
@@@ -10,12 -10,15 +10,16 @@@ obj-$(CONFIG_MMC_ARMMMCI)  += mmci.
  obj-$(CONFIG_MMC_PXA)         += pxamci.o
  obj-$(CONFIG_MMC_IMX)         += imxmmc.o
  obj-$(CONFIG_MMC_SDHCI)               += sdhci.o
+ obj-$(CONFIG_MMC_SDHCI_PCI)   += sdhci-pci.o
  obj-$(CONFIG_MMC_RICOH_MMC)   += ricoh_mmc.o
  obj-$(CONFIG_MMC_WBSD)                += wbsd.o
  obj-$(CONFIG_MMC_AU1X)                += au1xmmc.o
  obj-$(CONFIG_MMC_OMAP)                += omap.o
 +obj-$(CONFIG_MMC_OMAP_HS)     += omap_hsmmc.o
  obj-$(CONFIG_MMC_AT91)                += at91_mci.o
+ obj-$(CONFIG_MMC_ATMELMCI)    += atmel-mci.o
  obj-$(CONFIG_MMC_TIFM_SD)     += tifm_sd.o
  obj-$(CONFIG_MMC_SPI)         += mmc_spi.o
+ obj-$(CONFIG_MMC_S3C)         += s3cmci.o
+ obj-$(CONFIG_MMC_SDRICOH_CS)  += sdricoh_cs.o
  
index e103e19d5b2d13fa5331532c109c402046ce8169,71bc07f149b7910f964a5bc9b4c678a149cfbdf9..69f471b94b1eeec4f6a4aec7ba25a865826005d7
@@@ -1,6 -1,4 +1,4 @@@
  /*
-  * $Id: cmdlinepart.c,v 1.19 2005/11/07 11:14:19 gleixner Exp $
-  *
   * Read flash partition table from command line
   *
   * Copyright 2002 SYSGO Real-Time Solutions GmbH
@@@ -308,7 -306,7 +306,7 @@@ static int parse_cmdline_partitions(str
        unsigned long offset;
        int i;
        struct cmdline_mtd_partition *part;
-       char *mtd_id = master->name;
+       const char *mtd_id = master->name;
  
        /* parse command line */
        if (!cmdline_parsed)
   *
   * This function needs to be visible for bootloaders.
   */
 -static int mtdpart_setup(char *s)
 +int mtdpart_setup(char *s)
  {
        cmdline = s;
        return 1;
diff --combined drivers/mtd/nand/Kconfig
index 2b1021bd3c651b69855159d30bbada5791bbfbe3,02f9cc30d77b70b5f89c01f5e6194999da4b1ceb..565715c68740e725378aff6454c807a89519cd91
@@@ -1,5 -1,4 +1,4 @@@
  # drivers/mtd/nand/Kconfig
- # $Id: Kconfig,v 1.35 2005/11/07 11:14:30 gleixner Exp $
  
  menuconfig MTD_NAND
        tristate "NAND Device Support"
@@@ -69,25 -68,6 +68,25 @@@ config MTD_NAND_AMS_DELT
        help
          Support for NAND flash on Amstrad E3 (Delta).
  
 +config MTD_NAND_OMAP2
 +      tristate "NAND Flash device on OMAP2 and OMAP3"
 +      depends on ARM && MTD_NAND && (ARCH_OMAP2 || ARCH_OMAP3)
 +      help
 +          Support for NAND flash on Texas Instruments OMAP2 and OMAP3 platforms.
 +
 +config MTD_NAND_OMAP
 +      tristate "NAND Flash device on OMAP H3/H2/P2 boards"
 +      depends on ARM && ARCH_OMAP1 && MTD_NAND && (MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_PERSEUS2)
 +      help
 +        Support for NAND flash on Texas Instruments H3/H2/P2 platforms.
 +
 +config MTD_NAND_OMAP_HW
 +      bool "OMAP HW NAND Flash controller support"
 +        depends on ARM && ARCH_OMAP16XX && MTD_NAND
 +
 +      help
 +        Driver for TI OMAP16xx hardware NAND flash controller.
 +
  config MTD_NAND_TOTO
        tristate "NAND Flash device on TOTO board"
        depends on ARCH_OMAP && BROKEN
@@@ -124,11 -104,24 +123,24 @@@ config MTD_NAND_BF5X
  
  config MTD_NAND_BF5XX_HWECC
        bool "BF5XX NAND Hardware ECC"
+       default y
        depends on MTD_NAND_BF5XX
        help
          Enable the use of the BF5XX's internal ECC generator when
          using NAND.
  
+ config MTD_NAND_BF5XX_BOOTROM_ECC
+       bool "Use Blackfin BootROM ECC Layout"
+       default n
+       depends on MTD_NAND_BF5XX_HWECC
+       help
+         If you wish to modify NAND pages and allow the Blackfin on-chip
+         BootROM to boot from them, say Y here.  This is only necessary
+         if you are booting U-Boot out of NAND and you wish to update
+         U-Boot from Linux' userspace.  Otherwise, you should say N here.
+         If unsure, say N.
  config MTD_NAND_RTC_FROM4
        tristate "Renesas Flash ROM 4-slot interface board (FROM_BOARD4)"
        depends on SH_SOLUTION_ENGINE
@@@ -291,22 -284,23 +303,23 @@@ config MTD_NAND_CS553
  
          If you say "m", the module will be called "cs553x_nand.ko".
  
- config MTD_NAND_AT91
-       bool "Support for NAND Flash / SmartMedia on AT91"
-       depends on ARCH_AT91
+ config MTD_NAND_ATMEL
+       tristate "Support for NAND Flash / SmartMedia on AT91 and AVR32"
+       depends on ARCH_AT91 || AVR32
        help
          Enables support for NAND Flash / Smart Media Card interface
-         on Atmel AT91 processors.
+         on Atmel AT91 and AVR32 processors.
  choice
-       prompt "ECC management for NAND Flash / SmartMedia on AT91"
-       depends on MTD_NAND_AT91
+       prompt "ECC management for NAND Flash / SmartMedia on AT91 / AVR32"
+       depends on MTD_NAND_ATMEL
  
- config MTD_NAND_AT91_ECC_HW
+ config MTD_NAND_ATMEL_ECC_HW
        bool "Hardware ECC"
-       depends on ARCH_AT91SAM9263 || ARCH_AT91SAM9260
+       depends on ARCH_AT91SAM9263 || ARCH_AT91SAM9260 || AVR32
        help
-         Uses hardware ECC provided by the at91sam9260/at91sam9263 chip
-         instead of software ECC.
+         Use hardware ECC instead of software ECC when the chip
+         supports it.
          The hardware ECC controller is capable of single bit error
          correction and 2-bit random detection per page.
  
  
          If unsure, say Y
  
- config MTD_NAND_AT91_ECC_SOFT
+ config MTD_NAND_ATMEL_ECC_SOFT
        bool "Software ECC"
        help
-         Uses software ECC.
+         Use software ECC.
  
          NB : hardware and software ECC schemes are incompatible.
          If you switch from one to another, you'll have to erase your
          mtd partition.
  
- config MTD_NAND_AT91_ECC_NONE
+ config MTD_NAND_ATMEL_ECC_NONE
        bool "No ECC (testing only, DANGEROUS)"
        depends on DEBUG_KERNEL
        help
index c8be0dad517efe99316cf31ab010bdf22386dd02,d772581de573cf4281e64cf11598e234ca2dd6e7..521cf078c6f43ccab665ba33be39d081ee6fbab7
@@@ -1,7 -1,6 +1,6 @@@
  #
  # linux/drivers/nand/Makefile
  #
- # $Id: Makefile.common,v 1.15 2004/11/26 12:28:22 dedekind Exp $
  
  obj-$(CONFIG_MTD_NAND)                        += nand.o nand_ecc.o
  obj-$(CONFIG_MTD_NAND_IDS)            += nand_ids.o
@@@ -24,10 -23,7 +23,10 @@@ obj-$(CONFIG_MTD_NAND_TS7250)               += ts725
  obj-$(CONFIG_MTD_NAND_NANDSIM)                += nandsim.o
  obj-$(CONFIG_MTD_NAND_CS553X)         += cs553x_nand.o
  obj-$(CONFIG_MTD_NAND_NDFC)           += ndfc.o
- obj-$(CONFIG_MTD_NAND_AT91)           += at91_nand.o
+ obj-$(CONFIG_MTD_NAND_ATMEL)          += atmel_nand.o
 +obj-$(CONFIG_MTD_NAND_OMAP)           += omap-nand-flash.o
 +obj-$(CONFIG_MTD_NAND_OMAP2)          += omap2.o
 +obj-$(CONFIG_MTD_NAND_OMAP_HW)                += omap-hw.o
  obj-$(CONFIG_MTD_NAND_CM_X270)                += cmx270_nand.o
  obj-$(CONFIG_MTD_NAND_BASLER_EXCITE)  += excite_nandflash.o
  obj-$(CONFIG_MTD_NAND_PXA3xx)         += pxa3xx_nand.o
index 43060bee5009356b6184b1de51f71c1be6fe4b38,0000000000000000000000000000000000000000..f279d896eedfac76a875e24c56d5053fa851d93d
mode 100644,000000..100644
--- /dev/null
@@@ -1,777 -1,0 +1,777 @@@
-       if (dma_mapping_error(dma_dst)) {
 +/*
 + *  linux/drivers/mtd/onenand/omap2.c
 + *
 + *  OneNAND driver for OMAP2 / OMAP3
 + *
 + *  Copyright (C) 2005-2006 Nokia Corporation
 + *
 + *  Author: Jarkko Lavinen <jarkko.lavinen@nokia.com> and Juha Yrjola
 + *  IRQ and DMA support written by Timo Teras
 + *
 + * This program is free software; you can redistribute it and/or modify it
 + * under the terms of the GNU General Public License version 2 as published by
 + * the Free Software Foundation.
 + *
 + * This program is 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; see the file COPYING. If not, write to the Free Software
 + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 + *
 + */
 +
 +#include <linux/device.h>
 +#include <linux/module.h>
 +#include <linux/init.h>
 +#include <linux/mtd/mtd.h>
 +#include <linux/mtd/onenand.h>
 +#include <linux/mtd/partitions.h>
 +#include <linux/platform_device.h>
 +#include <linux/interrupt.h>
 +#include <linux/delay.h>
 +
 +#include <asm/io.h>
 +#include <asm/mach/flash.h>
 +#include <asm/arch/gpmc.h>
 +#include <asm/arch/onenand.h>
 +#include <asm/arch/gpio.h>
 +#include <asm/arch/gpmc.h>
 +#include <asm/arch/pm.h>
 +
 +#include <linux/dma-mapping.h>
 +#include <asm/dma-mapping.h>
 +#include <asm/arch/dma.h>
 +
 +#include <asm/arch/board.h>
 +
 +#define DRIVER_NAME "omap2-onenand"
 +
 +#define ONENAND_IO_SIZE               SZ_128K
 +#define ONENAND_BUFRAM_SIZE   (1024 * 5)
 +
 +struct omap2_onenand {
 +      struct platform_device *pdev;
 +      int gpmc_cs;
 +      unsigned long phys_base;
 +      int gpio_irq;
 +      struct mtd_info mtd;
 +      struct mtd_partition *parts;
 +      struct onenand_chip onenand;
 +      struct completion irq_done;
 +      struct completion dma_done;
 +      int dma_channel;
 +      int freq;
 +      int (*setup)(void __iomem *base, int freq);
 +};
 +
 +static void omap2_onenand_dma_cb(int lch, u16 ch_status, void *data)
 +{
 +      struct omap2_onenand *c = data;
 +
 +      complete(&c->dma_done);
 +}
 +
 +static irqreturn_t omap2_onenand_interrupt(int irq, void *dev_id)
 +{
 +      struct omap2_onenand *c = dev_id;
 +
 +      complete(&c->irq_done);
 +
 +      return IRQ_HANDLED;
 +}
 +
 +static inline unsigned short read_reg(struct omap2_onenand *c, int reg)
 +{
 +      return readw(c->onenand.base + reg);
 +}
 +
 +static inline void write_reg(struct omap2_onenand *c, unsigned short value,
 +                           int reg)
 +{
 +      writew(value, c->onenand.base + reg);
 +}
 +
 +static void wait_err(char *msg, int state, unsigned int ctrl, unsigned int intr)
 +{
 +      printk(KERN_ERR "onenand_wait: %s! state %d ctrl 0x%04x intr 0x%04x\n",
 +             msg, state, ctrl, intr);
 +}
 +
 +static void wait_warn(char *msg, int state, unsigned int ctrl,
 +                    unsigned int intr)
 +{
 +      printk(KERN_WARNING "onenand_wait: %s! state %d ctrl 0x%04x "
 +             "intr 0x%04x\n", msg, state, ctrl, intr);
 +}
 +
 +static int omap2_onenand_wait(struct mtd_info *mtd, int state)
 +{
 +      struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
 +      unsigned int intr = 0;
 +      unsigned int ctrl;
 +      unsigned long timeout;
 +      u32 syscfg;
 +
 +      if (state == FL_RESETING) {
 +              int i;
 +
 +              for (i = 0; i < 20; i++) {
 +                      udelay(1);
 +                      intr = read_reg(c, ONENAND_REG_INTERRUPT);
 +                      if (intr & ONENAND_INT_MASTER)
 +                              break;
 +              }
 +              ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS);
 +              if (ctrl & ONENAND_CTRL_ERROR) {
 +                      wait_err("controller error", state, ctrl, intr);
 +                      return -EIO;
 +              }
 +              if (!(intr & ONENAND_INT_RESET)) {
 +                      wait_err("timeout", state, ctrl, intr);
 +                      return -EIO;
 +              }
 +              return 0;
 +      }
 +
 +      if (state != FL_READING) {
 +              int result;
 +
 +              /* Turn interrupts on */
 +              syscfg = read_reg(c, ONENAND_REG_SYS_CFG1);
 +              syscfg |= ONENAND_SYS_CFG1_IOBE;
 +              write_reg(c, syscfg, ONENAND_REG_SYS_CFG1);
 +
 +              INIT_COMPLETION(c->irq_done);
 +              if (c->gpio_irq) {
 +                      result = omap_get_gpio_datain(c->gpio_irq);
 +                      if (result == -1) {
 +                              ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS);
 +                              intr = read_reg(c, ONENAND_REG_INTERRUPT);
 +                              wait_err("gpio error", state, ctrl, intr);
 +                              return -EIO;
 +                      }
 +              } else
 +                      result = 0;
 +              if (result == 0) {
 +                      int retry_cnt = 0;
 +retry:
 +                      result = wait_for_completion_timeout(&c->irq_done,
 +                                                  msecs_to_jiffies(20));
 +                      if (result == 0) {
 +                              /* Timeout after 20ms */
 +                              ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS);
 +                              if (ctrl & ONENAND_CTRL_ONGO) {
 +                                      /*
 +                                       * The operation seems to be still going
 +                                       * so give it some more time.
 +                                       */
 +                                      retry_cnt += 1;
 +                                      if (retry_cnt < 3)
 +                                              goto retry;
 +                                      intr = read_reg(c,
 +                                                      ONENAND_REG_INTERRUPT);
 +                                      wait_err("timeout", state, ctrl, intr);
 +                                      return -EIO;
 +                              }
 +                              intr = read_reg(c, ONENAND_REG_INTERRUPT);
 +                              if ((intr & ONENAND_INT_MASTER) == 0)
 +                                      wait_warn("timeout", state, ctrl, intr);
 +                      }
 +              }
 +      } else {
 +              /* Turn interrupts off */
 +              syscfg = read_reg(c, ONENAND_REG_SYS_CFG1);
 +              syscfg &= ~ONENAND_SYS_CFG1_IOBE;
 +              write_reg(c, syscfg, ONENAND_REG_SYS_CFG1);
 +
 +              timeout = jiffies + msecs_to_jiffies(20);
 +              while (time_before(jiffies, timeout)) {
 +                      intr = read_reg(c, ONENAND_REG_INTERRUPT);
 +                      if (intr & ONENAND_INT_MASTER)
 +                              break;
 +              }
 +      }
 +
 +      intr = read_reg(c, ONENAND_REG_INTERRUPT);
 +      ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS);
 +
 +      if (intr & ONENAND_INT_READ) {
 +              int ecc = read_reg(c, ONENAND_REG_ECC_STATUS);
 +
 +              if (ecc) {
 +                      unsigned int addr1, addr8;
 +
 +                      addr1 = read_reg(c, ONENAND_REG_START_ADDRESS1);
 +                      addr8 = read_reg(c, ONENAND_REG_START_ADDRESS8);
 +                      if (ecc & ONENAND_ECC_2BIT_ALL) {
 +                              printk(KERN_ERR "onenand_wait: ECC error = "
 +                                     "0x%04x, addr1 %#x, addr8 %#x\n",
 +                                     ecc, addr1, addr8);
 +                              mtd->ecc_stats.failed++;
 +                              return -EBADMSG;
 +                      } else if (ecc & ONENAND_ECC_1BIT_ALL) {
 +                              printk(KERN_NOTICE "onenand_wait: correctable "
 +                                     "ECC error = 0x%04x, addr1 %#x, "
 +                                     "addr8 %#x\n", ecc, addr1, addr8);
 +                              mtd->ecc_stats.corrected++;
 +                      }
 +              }
 +      } else if (state == FL_READING) {
 +              wait_err("timeout", state, ctrl, intr);
 +              return -EIO;
 +      }
 +
 +      if (ctrl & ONENAND_CTRL_ERROR) {
 +              wait_err("controller error", state, ctrl, intr);
 +              if (ctrl & ONENAND_CTRL_LOCK)
 +                      printk(KERN_ERR "onenand_wait: "
 +                                      "Device is write protected!!!\n");
 +              return -EIO;
 +      }
 +
 +      if (ctrl & 0xFE9F)
 +              wait_warn("unexpected controller status", state, ctrl, intr);
 +
 +      return 0;
 +}
 +
 +static inline int omap2_onenand_bufferram_offset(struct mtd_info *mtd, int area)
 +{
 +      struct onenand_chip *this = mtd->priv;
 +
 +      if (ONENAND_CURRENT_BUFFERRAM(this)) {
 +              if (area == ONENAND_DATARAM)
 +                      return mtd->writesize;
 +              if (area == ONENAND_SPARERAM)
 +                      return mtd->oobsize;
 +      }
 +
 +      return 0;
 +}
 +
 +#if defined(CONFIG_ARCH_OMAP3) || defined(MULTI_OMAP2)
 +
 +static int omap3_onenand_read_bufferram(struct mtd_info *mtd, int area,
 +                                      unsigned char *buffer, int offset,
 +                                      size_t count)
 +{
 +      struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
 +      struct onenand_chip *this = mtd->priv;
 +      dma_addr_t dma_src, dma_dst;
 +      int bram_offset;
 +      unsigned long timeout;
 +      void *buf = (void *)buffer;
 +      size_t xtra;
 +      volatile unsigned *done;
 +
 +      bram_offset = omap2_onenand_bufferram_offset(mtd, area) + area + offset;
 +      if (bram_offset & 3 || (size_t)buf & 3 || count < 384)
 +              goto out_copy;
 +
 +      if (buf >= high_memory) {
 +              struct page *p1;
 +
 +              if (((size_t)buf & PAGE_MASK) !=
 +                  ((size_t)(buf + count - 1) & PAGE_MASK))
 +                      goto out_copy;
 +              p1 = vmalloc_to_page(buf);
 +              if (!p1)
 +                      goto out_copy;
 +              buf = page_address(p1) + ((size_t)buf & ~PAGE_MASK);
 +      }
 +
 +      xtra = count & 3;
 +      if (xtra) {
 +              count -= xtra;
 +              memcpy(buf + count, this->base + bram_offset + count, xtra);
 +      }
 +
 +      dma_src = c->phys_base + bram_offset;
 +      dma_dst = dma_map_single(&c->pdev->dev, buf, count, DMA_FROM_DEVICE);
-       if (dma_mapping_error(dma_dst)) {
++      if (dma_mapping_error(&c->pdev->dev, dma_dst)) {
 +              dev_err(&c->pdev->dev,
 +                      "Couldn't DMA map a %d byte buffer\n",
 +                      count);
 +              goto out_copy;
 +      }
 +
 +      omap_set_dma_transfer_params(c->dma_channel, OMAP_DMA_DATA_TYPE_S32,
 +                                   count >> 2, 1, 0, 0, 0);
 +      omap_set_dma_src_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
 +                              dma_src, 0, 0);
 +      omap_set_dma_dest_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
 +                               dma_dst, 0, 0);
 +
 +      INIT_COMPLETION(c->dma_done);
 +      omap_start_dma(c->dma_channel);
 +
 +      timeout = jiffies + msecs_to_jiffies(20);
 +      done = &c->dma_done.done;
 +      while (time_before(jiffies, timeout))
 +              if (*done)
 +                      break;
 +
 +      dma_unmap_single(&c->pdev->dev, dma_dst, count, DMA_FROM_DEVICE);
 +
 +      if (!*done) {
 +              dev_err(&c->pdev->dev, "timeout waiting for DMA\n");
 +              goto out_copy;
 +      }
 +
 +      return 0;
 +
 +out_copy:
 +      memcpy(buf, this->base + bram_offset, count);
 +      return 0;
 +}
 +
 +static int omap3_onenand_write_bufferram(struct mtd_info *mtd, int area,
 +                                       const unsigned char *buffer,
 +                                       int offset, size_t count)
 +{
 +      struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
 +      struct onenand_chip *this = mtd->priv;
 +      dma_addr_t dma_src, dma_dst;
 +      int bram_offset;
 +      unsigned long timeout;
 +      void *buf = (void *)buffer;
 +      volatile unsigned *done;
 +
 +      bram_offset = omap2_onenand_bufferram_offset(mtd, area) + area + offset;
 +      if (bram_offset & 3 || (size_t)buf & 3 || count < 384)
 +              goto out_copy;
 +
 +      /* panic_write() may be in an interrupt context */
 +      if (in_interrupt())
 +              goto out_copy;
 +
 +      if (buf >= high_memory) {
 +              struct page *p1;
 +
 +              if (((size_t)buf & PAGE_MASK) !=
 +                  ((size_t)(buf + count - 1) & PAGE_MASK))
 +                      goto out_copy;
 +              p1 = vmalloc_to_page(buf);
 +              if (!p1)
 +                      goto out_copy;
 +              buf = page_address(p1) + ((size_t)buf & ~PAGE_MASK);
 +      }
 +
 +      dma_src = dma_map_single(&c->pdev->dev, buf, count, DMA_TO_DEVICE);
 +      dma_dst = c->phys_base + bram_offset;
-       if (dma_mapping_error(dma_dst)) {
++      if (dma_mapping_error(&c->pdev->dev, dma_dst)) {
 +              dev_err(&c->pdev->dev,
 +                      "Couldn't DMA map a %d byte buffer\n",
 +                      count);
 +              return -1;
 +      }
 +
 +      omap_set_dma_transfer_params(c->dma_channel, OMAP_DMA_DATA_TYPE_S32,
 +                                   count >> 2, 1, 0, 0, 0);
 +      omap_set_dma_src_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
 +                              dma_src, 0, 0);
 +      omap_set_dma_dest_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
 +                               dma_dst, 0, 0);
 +
 +      INIT_COMPLETION(c->dma_done);
 +      omap_start_dma(c->dma_channel);
 +
 +      timeout = jiffies + msecs_to_jiffies(20);
 +      done = &c->dma_done.done;
 +      while (time_before(jiffies, timeout))
 +              if (*done)
 +                      break;
 +
 +      dma_unmap_single(&c->pdev->dev, dma_dst, count, DMA_TO_DEVICE);
 +
 +      if (!*done) {
 +              dev_err(&c->pdev->dev, "timeout waiting for DMA\n");
 +              goto out_copy;
 +      }
 +
 +      return 0;
 +
 +out_copy:
 +      memcpy(this->base + bram_offset, buf, count);
 +      return 0;
 +}
 +
 +#else
 +
 +int omap3_onenand_read_bufferram(struct mtd_info *mtd, int area,
 +                               unsigned char *buffer, int offset,
 +                               size_t count);
 +
 +int omap3_onenand_write_bufferram(struct mtd_info *mtd, int area,
 +                                const unsigned char *buffer,
 +                                int offset, size_t count);
 +
 +#endif
 +
 +#if defined(CONFIG_ARCH_OMAP2) || defined(MULTI_OMAP2)
 +
 +static int omap2_onenand_read_bufferram(struct mtd_info *mtd, int area,
 +                                      unsigned char *buffer, int offset,
 +                                      size_t count)
 +{
 +      struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
 +      struct onenand_chip *this = mtd->priv;
 +      dma_addr_t dma_src, dma_dst;
 +      int bram_offset;
 +
 +      bram_offset = omap2_onenand_bufferram_offset(mtd, area) + area + offset;
 +      /* DMA is not used.  Revisit PM requirements before enabling it. */
 +      if (1 || (c->dma_channel < 0) ||
 +          ((void *) buffer >= (void *) high_memory) || (bram_offset & 3) ||
 +          (((unsigned int) buffer) & 3) || (count < 1024) || (count & 3)) {
 +              memcpy(buffer, (__force void *)(this->base + bram_offset),
 +                     count);
 +              return 0;
 +      }
 +
 +      dma_src = c->phys_base + bram_offset;
 +      dma_dst = dma_map_single(&c->pdev->dev, buffer, count,
 +                               DMA_FROM_DEVICE);
-       if (dma_mapping_error(dma_dst)) {
++      if (dma_mapping_error(&c->pdev->dev, dma_dst)) {
 +              dev_err(&c->pdev->dev,
 +                      "Couldn't DMA map a %d byte buffer\n",
 +                      count);
 +              return -1;
 +      }
 +
 +      omap_set_dma_transfer_params(c->dma_channel, OMAP_DMA_DATA_TYPE_S32,
 +                                   count / 4, 1, 0, 0, 0);
 +      omap_set_dma_src_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
 +                              dma_src, 0, 0);
 +      omap_set_dma_dest_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
 +                               dma_dst, 0, 0);
 +
 +      INIT_COMPLETION(c->dma_done);
 +      omap_start_dma(c->dma_channel);
 +      wait_for_completion(&c->dma_done);
 +
 +      dma_unmap_single(&c->pdev->dev, dma_dst, count, DMA_FROM_DEVICE);
 +
 +      return 0;
 +}
 +
 +static int omap2_onenand_write_bufferram(struct mtd_info *mtd, int area,
 +                                       const unsigned char *buffer,
 +                                       int offset, size_t count)
 +{
 +      struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
 +      struct onenand_chip *this = mtd->priv;
 +      dma_addr_t dma_src, dma_dst;
 +      int bram_offset;
 +
 +      bram_offset = omap2_onenand_bufferram_offset(mtd, area) + area + offset;
 +      /* DMA is not used.  Revisit PM requirements before enabling it. */
 +      if (1 || (c->dma_channel < 0) ||
 +          ((void *) buffer >= (void *) high_memory) || (bram_offset & 3) ||
 +          (((unsigned int) buffer) & 3) || (count < 1024) || (count & 3)) {
 +              memcpy((__force void *)(this->base + bram_offset), buffer,
 +                     count);
 +              return 0;
 +      }
 +
 +      dma_src = dma_map_single(&c->pdev->dev, (void *) buffer, count,
 +                               DMA_TO_DEVICE);
 +      dma_dst = c->phys_base + bram_offset;
++      if (dma_mapping_error(&c->pdev->dev, dma_dst)) {
 +              dev_err(&c->pdev->dev,
 +                      "Couldn't DMA map a %d byte buffer\n",
 +                      count);
 +              return -1;
 +      }
 +
 +      omap_set_dma_transfer_params(c->dma_channel, OMAP_DMA_DATA_TYPE_S16,
 +                                   count / 2, 1, 0, 0, 0);
 +      omap_set_dma_src_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
 +                              dma_src, 0, 0);
 +      omap_set_dma_dest_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
 +                               dma_dst, 0, 0);
 +
 +      INIT_COMPLETION(c->dma_done);
 +      omap_start_dma(c->dma_channel);
 +      wait_for_completion(&c->dma_done);
 +
 +      dma_unmap_single(&c->pdev->dev, dma_dst, count, DMA_TO_DEVICE);
 +
 +      return 0;
 +}
 +
 +#else
 +
 +int omap2_onenand_read_bufferram(struct mtd_info *mtd, int area,
 +                               unsigned char *buffer, int offset,
 +                               size_t count);
 +
 +int omap2_onenand_write_bufferram(struct mtd_info *mtd, int area,
 +                                const unsigned char *buffer,
 +                                int offset, size_t count);
 +
 +#endif
 +
 +static struct platform_driver omap2_onenand_driver;
 +
 +static int __adjust_timing(struct device *dev, void *data)
 +{
 +      int ret = 0;
 +      struct omap2_onenand *c;
 +
 +      c = dev_get_drvdata(dev);
 +
 +      BUG_ON(c->setup == NULL);
 +
 +      /* DMA is not in use so this is all that is needed */
 +      /* Revisit for OMAP3! */
 +      ret = c->setup(c->onenand.base, c->freq);
 +
 +      return ret;
 +}
 +
 +int omap2_onenand_rephase(void)
 +{
 +      return driver_for_each_device(&omap2_onenand_driver.driver, NULL,
 +                                    NULL, __adjust_timing);
 +}
 +
 +static void __devexit omap2_onenand_shutdown(struct platform_device *pdev)
 +{
 +      struct omap2_onenand *c = dev_get_drvdata(&pdev->dev);
 +
 +      /* With certain content in the buffer RAM, the OMAP boot ROM code
 +       * can recognize the flash chip incorrectly. Zero it out before
 +       * soft reset.
 +       */
 +      memset((__force void *)c->onenand.base, 0, ONENAND_BUFRAM_SIZE);
 +}
 +
 +static int __devinit omap2_onenand_probe(struct platform_device *pdev)
 +{
 +      struct omap_onenand_platform_data *pdata;
 +      struct omap2_onenand *c;
 +      int r;
 +
 +      pdata = pdev->dev.platform_data;
 +      if (pdata == NULL) {
 +              dev_err(&pdev->dev, "platform data missing\n");
 +              return -ENODEV;
 +      }
 +
 +      c = kzalloc(sizeof(struct omap2_onenand), GFP_KERNEL);
 +      if (!c)
 +              return -ENOMEM;
 +
 +      init_completion(&c->irq_done);
 +      init_completion(&c->dma_done);
 +      c->gpmc_cs = pdata->cs;
 +      c->gpio_irq = pdata->gpio_irq;
 +      c->dma_channel = pdata->dma_channel;
 +      if (c->dma_channel < 0) {
 +              /* if -1, don't use DMA */
 +              c->gpio_irq = 0;
 +      }
 +
 +      r = gpmc_cs_request(c->gpmc_cs, ONENAND_IO_SIZE, &c->phys_base);
 +      if (r < 0) {
 +              dev_err(&pdev->dev, "Cannot request GPMC CS\n");
 +              goto err_kfree;
 +      }
 +
 +      if (request_mem_region(c->phys_base, ONENAND_IO_SIZE,
 +                             pdev->dev.driver->name) == NULL) {
 +              dev_err(&pdev->dev, "Cannot reserve memory region at 0x%08lx, "
 +                      "size: 0x%x\n", c->phys_base, ONENAND_IO_SIZE);
 +              r = -EBUSY;
 +              goto err_free_cs;
 +      }
 +      c->onenand.base = ioremap(c->phys_base, ONENAND_IO_SIZE);
 +      if (c->onenand.base == NULL) {
 +              r = -ENOMEM;
 +              goto err_release_mem_region;
 +      }
 +
 +      if (pdata->onenand_setup != NULL) {
 +              r = pdata->onenand_setup(c->onenand.base, c->freq);
 +              if (r < 0) {
 +                      dev_err(&pdev->dev, "Onenand platform setup failed: "
 +                              "%d\n", r);
 +                      goto err_iounmap;
 +              }
 +              c->setup = pdata->onenand_setup;
 +      }
 +
 +      if (c->gpio_irq) {
 +              if ((r = omap_request_gpio(c->gpio_irq)) < 0) {
 +                      dev_err(&pdev->dev,  "Failed to request GPIO%d for "
 +                              "OneNAND\n", c->gpio_irq);
 +                      goto err_iounmap;
 +      }
 +      omap_set_gpio_direction(c->gpio_irq, 1);
 +
 +      if ((r = request_irq(OMAP_GPIO_IRQ(c->gpio_irq),
 +                           omap2_onenand_interrupt, IRQF_TRIGGER_RISING,
 +                           pdev->dev.driver->name, c)) < 0)
 +              goto err_release_gpio;
 +      }
 +
 +      if (c->dma_channel >= 0) {
 +              r = omap_request_dma(0, pdev->dev.driver->name,
 +                                   omap2_onenand_dma_cb, (void *) c,
 +                                   &c->dma_channel);
 +              if (r == 0) {
 +                      omap_set_dma_write_mode(c->dma_channel,
 +                                              OMAP_DMA_WRITE_NON_POSTED);
 +                      omap_set_dma_src_data_pack(c->dma_channel, 1);
 +                      omap_set_dma_src_burst_mode(c->dma_channel,
 +                                                  OMAP_DMA_DATA_BURST_8);
 +                      omap_set_dma_dest_data_pack(c->dma_channel, 1);
 +                      omap_set_dma_dest_burst_mode(c->dma_channel,
 +                                                   OMAP_DMA_DATA_BURST_8);
 +              } else {
 +                      dev_info(&pdev->dev,
 +                               "failed to allocate DMA for OneNAND, "
 +                               "using PIO instead\n");
 +                      c->dma_channel = -1;
 +              }
 +      }
 +
 +      dev_info(&pdev->dev, "initializing on CS%d, phys base 0x%08lx, virtual "
 +               "base %p\n", c->gpmc_cs, c->phys_base,
 +               c->onenand.base);
 +
 +      c->pdev = pdev;
 +      c->mtd.name = pdev->dev.bus_id;
 +      c->mtd.priv = &c->onenand;
 +      c->mtd.owner = THIS_MODULE;
 +
 +      if (c->dma_channel >= 0) {
 +              struct onenand_chip *this = &c->onenand;
 +
 +              this->wait = omap2_onenand_wait;
 +              if (cpu_is_omap34xx()) {
 +                      this->read_bufferram = omap3_onenand_read_bufferram;
 +                      this->write_bufferram = omap3_onenand_write_bufferram;
 +              } else {
 +                      this->read_bufferram = omap2_onenand_read_bufferram;
 +                      this->write_bufferram = omap2_onenand_write_bufferram;
 +              }
 +      }
 +
 +      if ((r = onenand_scan(&c->mtd, 1)) < 0)
 +              goto err_release_dma;
 +
 +      switch ((c->onenand.version_id >> 4) & 0xf) {
 +      case 0:
 +              c->freq = 40;
 +              break;
 +      case 1:
 +              c->freq = 54;
 +              break;
 +      case 2:
 +              c->freq = 66;
 +              break;
 +      case 3:
 +              c->freq = 83;
 +              break;
 +      }
 +
 +#ifdef CONFIG_MTD_PARTITIONS
 +      if (pdata->parts != NULL)
 +              r = add_mtd_partitions(&c->mtd, pdata->parts,
 +                                     pdata->nr_parts);
 +      else
 +#endif
 +              r = add_mtd_device(&c->mtd);
 +      if (r < 0)
 +              goto err_release_onenand;
 +
 +      platform_set_drvdata(pdev, c);
 +
 +      return 0;
 +
 +err_release_onenand:
 +      onenand_release(&c->mtd);
 +err_release_dma:
 +      if (c->dma_channel != -1)
 +              omap_free_dma(c->dma_channel);
 +      if (c->gpio_irq)
 +              free_irq(OMAP_GPIO_IRQ(c->gpio_irq), c);
 +err_release_gpio:
 +      if (c->gpio_irq)
 +              omap_free_gpio(c->gpio_irq);
 +err_iounmap:
 +      iounmap(c->onenand.base);
 +err_release_mem_region:
 +      release_mem_region(c->phys_base, ONENAND_IO_SIZE);
 +err_free_cs:
 +      gpmc_cs_free(c->gpmc_cs);
 +err_kfree:
 +      kfree(c);
 +
 +      return r;
 +}
 +
 +static int __devexit omap2_onenand_remove(struct platform_device *pdev)
 +{
 +      struct omap2_onenand *c = dev_get_drvdata(&pdev->dev);
 +
 +      BUG_ON(c == NULL);
 +
 +#ifdef CONFIG_MTD_PARTITIONS
 +      if (c->parts)
 +              del_mtd_partitions(&c->mtd);
 +      else
 +              del_mtd_device(&c->mtd);
 +#else
 +      del_mtd_device(&c->mtd);
 +#endif
 +
 +      onenand_release(&c->mtd);
 +      if (c->dma_channel != -1)
 +              omap_free_dma(c->dma_channel);
 +      omap2_onenand_shutdown(pdev);
 +      platform_set_drvdata(pdev, NULL);
 +      if (c->gpio_irq) {
 +              free_irq(OMAP_GPIO_IRQ(c->gpio_irq), c);
 +              omap_free_gpio(c->gpio_irq);
 +      }
 +      iounmap(c->onenand.base);
 +      release_mem_region(c->phys_base, ONENAND_IO_SIZE);
 +      kfree(c);
 +
 +      return 0;
 +}
 +
 +static struct platform_driver omap2_onenand_driver = {
 +      .probe          = omap2_onenand_probe,
 +      .remove         = omap2_onenand_remove,
 +      .shutdown       = omap2_onenand_shutdown,
 +      .driver         = {
 +              .name   = DRIVER_NAME,
 +              .owner  = THIS_MODULE,
 +      },
 +};
 +
 +static int __init omap2_onenand_init(void)
 +{
 +      printk(KERN_INFO "OneNAND driver initializing\n");
 +      return platform_driver_register(&omap2_onenand_driver);
 +}
 +
 +static void __exit omap2_onenand_exit(void)
 +{
 +      platform_driver_unregister(&omap2_onenand_driver);
 +}
 +
 +module_init(omap2_onenand_init);
 +module_exit(omap2_onenand_exit);
 +
 +MODULE_ALIAS(DRIVER_NAME);
 +MODULE_LICENSE("GPL");
 +MODULE_AUTHOR("Jarkko Lavinen <jarkko.lavinen@nokia.com>");
 +MODULE_DESCRIPTION("Glue layer for OneNAND flash on OMAP2 / OMAP3");
diff --combined drivers/net/Kconfig
index ecda0b6eafd4649fa38d8c0b949dbc37cb037738,8a03875ec8779505ca6846f38501eb812c3766c6..fef138b4a6361bbdcffa1ee9f82d03be6794916a
@@@ -26,14 -26,6 +26,6 @@@ menuconfig NETDEVICE
  # that for each of the symbols.
  if NETDEVICES
  
- config NETDEVICES_MULTIQUEUE
-       bool "Netdevice multiple hardware queue support"
-       ---help---
-         Say Y here if you want to allow the network stack to use multiple
-         hardware TX queues on an ethernet device.
-         Most people will say N here.
  config IFB
        tristate "Intermediate Functional Block support"
        depends on NET_CLS_ACT
@@@ -217,7 -209,7 +209,7 @@@ config MI
  
  config MACB
        tristate "Atmel MACB support"
-       depends on AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263 || ARCH_AT91CAP9
+       depends on AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263 || ARCH_AT91SAM9G20 || ARCH_AT91CAP9
        select PHYLIB
        help
          The Atmel MACB ethernet interface is found on many AT32 and AT91
@@@ -333,15 -325,6 +325,6 @@@ config APN
          To compile this driver as a module, choose M here: the module
          will be called apne.
  
- config APOLLO_ELPLUS
-       tristate "Apollo 3c505 support"
-       depends on APOLLO
-       help
-         Say Y or M here if your Apollo has a 3Com 3c505 ISA Ethernet card.
-         If you don't have one made for Apollos, you can use one from a PC,
-         except that your Apollo won't be able to boot from it (because the
-         code in the ROM will be for a PC).
  config MAC8390
        bool "Macintosh NS 8390 based ethernet cards"
        depends on MAC
@@@ -524,6 -507,18 +507,18 @@@ config STNI
  
          If unsure, say N.
  
+ config SH_ETH
+       tristate "Renesas SuperH Ethernet support"
+       depends on SUPERH && \
+               (CPU_SUBTYPE_SH7710 || CPU_SUBTYPE_SH7712 || CPU_SUBTYPE_SH7763)
+       select CRC32
+       select MII
+       select MDIO_BITBANG
+       select PHYLIB
+       help
+         Renesas SuperH Ethernet device driver.
+         This driver support SH7710, SH7712 and SH7763.
  config SUNLANCE
        tristate "Sun LANCE support"
        depends on SBUS
@@@ -926,6 -921,23 +921,23 @@@ config DM900
          To compile this driver as a module, choose M here.  The module
          will be called dm9000.
  
+ config DM9000_DEBUGLEVEL
+       int "DM9000 maximum debug level"
+       depends on DM9000
+       default 4
+       help
+         The maximum level of debugging code compiled into the DM9000
+         driver.
+ config DM9000_FORCE_SIMPLE_PHY_POLL
+       bool "Force simple NSR based PHY polling"
+       depends on DM9000
+       ---help---
+         This configuration forces the DM9000 to use the NSR's LinkStatus
+         bit to determine if the link is up or down instead of the more
+         costly MII PHY reads. Note, this will not work if the chip is
+         operating with an external PHY.
  config ENC28J60
        tristate "ENC28J60 support"
        depends on EXPERIMENTAL && SPI && NET_ETHERNET
@@@ -943,19 -955,11 +955,11 @@@ config ENC28J60_WRITEVERIF
          Enable the verify after the buffer write useful for debugging purpose.
          If unsure, say N.
  
- config DM9000_DEBUGLEVEL
-       int "DM9000 maximum debug level"
-       depends on DM9000
-       default 4
-       help
-         The maximum level of debugging code compiled into the DM9000
-         driver.
  config SMC911X
        tristate "SMSC LAN911[5678] support"
        select CRC32
        select MII
-       depends on ARCH_PXA || SH_MAGIC_PANEL_R2 || ARCH_OMAP24XX || ARCH_OMAP34XX 
 -      depends on ARCH_PXA || SUPERH
++      depends on ARCH_PXA || SUPERH || SH_MAGIC_PANEL_R2 || ARCH_OMAP24XX || ARCH_OMAP34XX
        help
          This is a driver for SMSC's LAN911x series of Ethernet chipsets
          including the new LAN9115, LAN9116, LAN9117, and LAN9118.
@@@ -1243,7 -1247,6 +1247,6 @@@ config IBMVET
          To compile this driver as a module, choose M here. The module will
          be called ibmveth.
  
- source "drivers/net/ibm_emac/Kconfig"
  source "drivers/net/ibm_newemac/Kconfig"
  
  config NET_PCI
@@@ -1286,20 -1289,6 +1289,6 @@@ config AMD8111_ET
          To compile this driver as a module, choose M here. The module
          will be called amd8111e.
  
- config AMD8111E_NAPI
-       bool "Use RX polling (NAPI)"
-       depends on AMD8111_ETH
-       help
-         NAPI is a new driver API designed to reduce CPU and interrupt load
-         when the driver is receiving lots of packets from the card. It is
-         still somewhat experimental and thus not yet enabled by default.
-         If your estimated Rx load is 10kpps or more, or if the card will be
-         deployed on potentially unfriendly networks (e.g. in a firewall),
-         then say Y here.
-         If in doubt, say N.
  config ADAPTEC_STARFIRE
        tristate "Adaptec Starfire/DuraLAN support"
        depends on NET_PCI && PCI
          To compile this driver as a module, choose M here: the module
          will be called starfire.  This is recommended.
  
- config ADAPTEC_STARFIRE_NAPI
-       bool "Use Rx Polling (NAPI) (EXPERIMENTAL)"
-       depends on ADAPTEC_STARFIRE && EXPERIMENTAL
-       help
-         NAPI is a new driver API designed to reduce CPU and interrupt load
-         when the driver is receiving lots of packets from the card. It is
-         still somewhat experimental and thus not yet enabled by default.
-         If your estimated Rx load is 10kpps or more, or if the card will be
-         deployed on potentially unfriendly networks (e.g. in a firewall),
-         then say Y here.
-         If in doubt, say N.
  config AC3200
        tristate "Ansel Communications EISA 3200 support (EXPERIMENTAL)"
        depends on NET_PCI && (ISA || EISA) && EXPERIMENTAL
@@@ -1670,7 -1645,7 +1645,7 @@@ config SUNDANCE_MMI
  
  config TLAN
        tristate "TI ThunderLAN support"
-       depends on NET_PCI && (PCI || EISA) && !64BIT
+       depends on NET_PCI && (PCI || EISA)
        ---help---
          If you have a PCI Ethernet network card based on the ThunderLAN chip
          which is supported by this driver, say Y and read the
@@@ -1710,26 -1685,6 +1685,6 @@@ config VIA_RHINE_MMI
  
          If unsure, say Y.
  
- config VIA_RHINE_NAPI
-       bool "Use Rx Polling (NAPI)"
-       depends on VIA_RHINE
-       help
-         NAPI is a new driver API designed to reduce CPU and interrupt load
-         when the driver is receiving lots of packets from the card.
-         If your estimated Rx load is 10kpps or more, or if the card will be
-         deployed on potentially unfriendly networks (e.g. in a firewall),
-         then say Y here.
- config LAN_SAA9730
-       bool "Philips SAA9730 Ethernet support"
-       depends on NET_PCI && PCI && MIPS_ATLAS
-       help
-         The SAA9730 is a combined multimedia and peripheral controller used
-         in thin clients, Internet access terminals, and diskless
-         workstations.
-         See <http://www.semiconductors.philips.com/pip/SAA9730_flyer_1>.
  config SC92031
        tristate "Silan SC92031 PCI Fast Ethernet Adapter driver (EXPERIMENTAL)"
        depends on NET_PCI && PCI && EXPERIMENTAL
@@@ -1884,7 -1839,6 +1839,6 @@@ config NE_H830
          Say Y here if you want to use the NE2000 compatible
          controller on the Renesas H8/300 processor.
  
- source "drivers/net/fec_8xx/Kconfig"
  source "drivers/net/fs_enet/Kconfig"
  
  endif # NET_ETHERNET
@@@ -1972,20 -1926,6 +1926,6 @@@ config E100
          To compile this driver as a module, choose M here. The module
          will be called e1000.
  
- config E1000_NAPI
-       bool "Use Rx Polling (NAPI)"
-       depends on E1000
-       help
-         NAPI is a new driver API designed to reduce CPU and interrupt load
-         when the driver is receiving lots of packets from the card. It is
-         still somewhat experimental and thus not yet enabled by default.
-         If your estimated Rx load is 10kpps or more, or if the card will be
-         deployed on potentially unfriendly networks (e.g. in a firewall),
-         then say Y here.
-         If in doubt, say N.
  config E1000_DISABLE_PACKET_SPLIT
        bool "Disable Packet Split for PCI express adapters"
        depends on E1000
@@@ -2014,9 -1954,6 +1954,6 @@@ config E1000
          To compile this driver as a module, choose M here. The module
          will be called e1000e.
  
- config E1000E_ENABLED
-       def_bool E1000E != n
  config IP1000
        tristate "IP1000 Gigabit Ethernet support"
        depends on PCI && EXPERIMENTAL
@@@ -2048,6 -1985,15 +1985,15 @@@ config IG
           To compile this driver as a module, choose M here. The module
           will be called igb.
  
+ config IGB_LRO 
+       bool "Use software LRO"
+       depends on IGB && INET
+       select INET_LRO
+       ---help---
+         Say Y here if you want to use large receive offload. 
+         If in doubt, say N.
  source "drivers/net/ixp2000/Kconfig"
  
  config MYRI_SBUS
@@@ -2105,27 -2051,13 +2051,13 @@@ config R816
          To compile this driver as a module, choose M here: the module
          will be called r8169.  This is recommended.
  
- config R8169_NAPI
-       bool "Use Rx Polling (NAPI) (EXPERIMENTAL)"
-       depends on R8169 && EXPERIMENTAL
-       help
-         NAPI is a new driver API designed to reduce CPU and interrupt load
-         when the driver is receiving lots of packets from the card. It is
-         still somewhat experimental and thus not yet enabled by default.
-         If your estimated Rx load is 10kpps or more, or if the card will be
-         deployed on potentially unfriendly networks (e.g. in a firewall),
-         then say Y here.
-         If in doubt, say N.
  config R8169_VLAN
        bool "VLAN support"
        depends on R8169 && VLAN_8021Q
        ---help---
          Say Y here for the r8169 driver to support the functions required
          by the kernel 802.1Q code.
-         
          If in doubt, say Y.
  
  config SB1250_MAC
@@@ -2228,6 -2160,7 +2160,7 @@@ config VIA_VELOCIT
  config TIGON3
        tristate "Broadcom Tigon3 support"
        depends on PCI
+       select PHYLIB
        help
          This driver supports Broadcom Tigon3 based gigabit Ethernet cards.
  
@@@ -2283,6 -2216,19 +2216,19 @@@ config GELIC_WIRELES
          the driver automatically distinguishes the models, you can
          safely enable this option even if you have a wireless-less model.
  
+ config GELIC_WIRELESS_OLD_PSK_INTERFACE
+        bool "PS3 Wireless private PSK interface (OBSOLETE)"
+        depends on GELIC_WIRELESS
+        help
+           This option retains the obsolete private interface to pass
+           the PSK from user space programs to the driver.  The PSK
+           stands for 'Pre Shared Key' and is used for WPA[2]-PSK
+           (WPA-Personal) environment.
+           If WPA[2]-PSK is used and you need to use old programs that
+           support only this old interface, say Y.  Otherwise N.
+           If unsure, say N.
  config GIANFAR
        tristate "Gianfar Ethernet"
        depends on FSL_SOC
          This driver supports the Gigabit TSEC on the MPC83xx, MPC85xx,
          and MPC86xx family of chips, and the FEC on the 8540.
  
- config GFAR_NAPI
-       bool "Use Rx Polling (NAPI)"
-       depends on GIANFAR
  config UCC_GETH
        tristate "Freescale QE Gigabit Ethernet"
        depends on QUICC_ENGINE
          This driver supports the Gigabit Ethernet mode of the QUICC Engine,
          which is available on some Freescale SOCs.
  
- config UGETH_NAPI
-       bool "Use Rx Polling (NAPI)"
-       depends on UCC_GETH
  config UGETH_MAGIC_PACKET
        bool "Magic Packet detection support"
        depends on UCC_GETH
@@@ -2352,6 -2290,17 +2290,17 @@@ config ATL
          To compile this driver as a module, choose M here.  The module
          will be called atl1.
  
+ config ATL1E
+       tristate "Atheros L1E Gigabit Ethernet support (EXPERIMENTAL)"
+       depends on PCI && EXPERIMENTAL
+       select CRC32
+       select MII
+       help
+         This driver supports the Atheros L1E gigabit ethernet adapter.
+         To compile this driver as a module, choose M here.  The module
+         will be called atl1e.
  endif # NETDEV_1000
  
  #
@@@ -2397,18 -2346,11 +2346,11 @@@ config CHELSIO_T1_1
            Enables support for Chelsio's gigabit Ethernet PCI cards.  If you
            are using only 10G cards say 'N' here.
  
- config CHELSIO_T1_NAPI
-       bool "Use Rx Polling (NAPI)"
-       depends on CHELSIO_T1
-       default y
-       help
-         NAPI is a driver API designed to reduce CPU and interrupt load
-         when the driver is receiving lots of packets from the card.
  config CHELSIO_T3
        tristate "Chelsio Communications T3 10Gb Ethernet support"
-       depends on PCI
+       depends on PCI && INET
        select FW_LOADER
+       select INET_LRO
        help
          This driver supports Chelsio T3-based gigabit and 10Gb Ethernet
          adapters.
@@@ -2436,7 -2378,8 +2378,8 @@@ config EHE
  
  config IXGBE
        tristate "Intel(R) 10GbE PCI Express adapters support"
-       depends on PCI
+       depends on PCI && INET
+       select INET_LRO
        ---help---
          This driver supports Intel(R) 10GbE PCI Express family of
          adapters.  For more information on how to identify your adapter, go
@@@ -2474,20 -2417,6 +2417,6 @@@ config IXG
          To compile this driver as a module, choose M here. The module
          will be called ixgb.
  
- config IXGB_NAPI
-       bool "Use Rx Polling (NAPI) (EXPERIMENTAL)"
-       depends on IXGB && EXPERIMENTAL
-       help
-         NAPI is a new driver API designed to reduce CPU and interrupt load
-         when the driver is receiving lots of packets from the card. It is
-         still somewhat experimental and thus not yet enabled by default.
-         If your estimated Rx load is 10kpps or more, or if the card will be
-         deployed on potentially unfriendly networks (e.g. in a firewall),
-         then say Y here.
-         If in doubt, say N.
  config S2IO
        tristate "S2IO 10Gbe XFrame NIC"
        depends on PCI
          More specific information on configuring the driver is in 
          <file:Documentation/networking/s2io.txt>.
  
- config S2IO_NAPI
-       bool "Use Rx Polling (NAPI) (EXPERIMENTAL)"
-       depends on S2IO && EXPERIMENTAL
-       help
-         NAPI is a new driver API designed to reduce CPU and interrupt load
-         when the driver is receiving lots of packets from the card. It is
-         still somewhat experimental and thus not yet enabled by default.
-         If your estimated Rx load is 10kpps or more, or if the card will be
-         deployed on potentially unfriendly networks (e.g. in a firewall),
-         then say Y here.
-         If in doubt, say N.
  config MYRI10GE
        tristate "Myricom Myri-10G Ethernet support"
        depends on PCI && INET
@@@ -2574,6 -2489,7 +2489,7 @@@ config BNX2
        tristate "Broadcom NetXtremeII 10Gb support"
        depends on PCI
        select ZLIB_INFLATE
+       select LIBCRC32C
        help
          This driver supports Broadcom NetXtremeII 10 gigabit Ethernet cards.
          To compile this driver as a module, choose M here: the module
diff --combined drivers/net/smc911x.h
index 0f406a0d111fa3db7c478666336dd5e897129688,76c17c28fab4b271006f51163f6029784149c311..07e7af89fa0bec81cb642b2a910e541d13e1e462
@@@ -29,6 -29,7 +29,7 @@@
  #ifndef _SMC911X_H_
  #define _SMC911X_H_
  
+ #include <linux/smc911x.h>
  /*
   * Use the DMA feature on PXA chips
   */
    #define SMC_USE_32BIT               1
    #define SMC_IRQ_SENSE               IRQF_TRIGGER_FALLING
  #elif defined(CONFIG_SH_MAGIC_PANEL_R2)
-   #define SMC_USE_SH_DMA      0
    #define SMC_USE_16BIT               0
    #define SMC_USE_32BIT               1
    #define SMC_IRQ_SENSE               IRQF_TRIGGER_LOW
 +#elif defined(CONFIG_ARCH_OMAP34XX)
 +  #define SMC_USE_16BIT               0
 +  #define SMC_USE_32BIT               1
 +  #define SMC_IRQ_SENSE               IRQF_TRIGGER_LOW
 +  #define SMC_MEM_RESERVED    1
 +#elif defined(CONFIG_ARCH_OMAP24XX)
 +  #define SMC_USE_16BIT               0
 +  #define SMC_USE_32BIT               1
 +  #define SMC_IRQ_SENSE               IRQF_TRIGGER_LOW
 +  #define SMC_MEM_RESERVED    1
+ #else
+ /*
+  * Default configuration
+  */
+ #define SMC_DYNAMIC_BUS_CONFIG
  #endif
  
+ /* store this information for the driver.. */
+ struct smc911x_local {
+       /*
+        * If I have to wait until the DMA is finished and ready to reload a
+        * packet, I will store the skbuff here. Then, the DMA will send it
+        * out and free it.
+        */
+       struct sk_buff *pending_tx_skb;
+       /* version/revision of the SMC911x chip */
+       u16 version;
+       u16 revision;
+       /* FIFO sizes */
+       int tx_fifo_kb;
+       int tx_fifo_size;
+       int rx_fifo_size;
+       int afc_cfg;
+       /* Contains the current active receive/phy mode */
+       int ctl_rfduplx;
+       int ctl_rspeed;
+       u32 msg_enable;
+       u32 phy_type;
+       struct mii_if_info mii;
+       /* work queue */
+       struct work_struct phy_configure;
+       int tx_throttle;
+       spinlock_t lock;
+       struct net_device *netdev;
+ #ifdef SMC_USE_DMA
+       /* DMA needs the physical address of the chip */
+       u_long physaddr;
+       int rxdma;
+       int txdma;
+       int rxdma_active;
+       int txdma_active;
+       struct sk_buff *current_rx_skb;
+       struct sk_buff *current_tx_skb;
+       struct device *dev;
+ #endif
+       void __iomem *base;
+ #ifdef SMC_DYNAMIC_BUS_CONFIG
+       struct smc911x_platdata cfg;
+ #endif
+ };
  
  /*
   * Define the bus width specific IO macros
   */
  
+ #ifdef SMC_DYNAMIC_BUS_CONFIG
+ static inline unsigned int SMC_inl(struct smc911x_local *lp, int reg)
+ {
+       void __iomem *ioaddr = lp->base + reg;
+       if (lp->cfg.flags & SMC911X_USE_32BIT)
+               return readl(ioaddr);
+       if (lp->cfg.flags & SMC911X_USE_16BIT)
+               return readw(ioaddr) | (readw(ioaddr + 2) << 16);
+       BUG();
+ }
+ static inline void SMC_outl(unsigned int value, struct smc911x_local *lp,
+                           int reg)
+ {
+       void __iomem *ioaddr = lp->base + reg;
+       if (lp->cfg.flags & SMC911X_USE_32BIT) {
+               writel(value, ioaddr);
+               return;
+       }
+       if (lp->cfg.flags & SMC911X_USE_16BIT) {
+               writew(value & 0xffff, ioaddr);
+               writew(value >> 16, ioaddr + 2);
+               return;
+       }
+       BUG();
+ }
+ static inline void SMC_insl(struct smc911x_local *lp, int reg,
+                             void *addr, unsigned int count)
+ {
+       void __iomem *ioaddr = lp->base + reg;
+       if (lp->cfg.flags & SMC911X_USE_32BIT) {
+               readsl(ioaddr, addr, count);
+               return;
+       }
+       if (lp->cfg.flags & SMC911X_USE_16BIT) {
+               readsw(ioaddr, addr, count * 2);
+               return;
+       }
+       BUG();
+ }
+ static inline void SMC_outsl(struct smc911x_local *lp, int reg,
+                            void *addr, unsigned int count)
+ {
+       void __iomem *ioaddr = lp->base + reg;
+       if (lp->cfg.flags & SMC911X_USE_32BIT) {
+               writesl(ioaddr, addr, count);
+               return;
+       }
+       if (lp->cfg.flags & SMC911X_USE_16BIT) {
+               writesw(ioaddr, addr, count * 2);
+               return;
+       }
+       BUG();
+ }
+ #else
  #if   SMC_USE_16BIT
- #define SMC_inb(a, r)                  readb((a) + (r))
- #define SMC_inw(a, r)                  readw((a) + (r))
- #define SMC_inl(a, r)                  ((SMC_inw(a, r) & 0xFFFF)+(SMC_inw(a+2, r)<<16))
- #define SMC_outb(v, a, r)              writeb(v, (a) + (r))
- #define SMC_outw(v, a, r)              writew(v, (a) + (r))
- #define SMC_outl(v, a, r)                      \
+ #define SMC_inl(lp, r)                 ((readw((lp)->base + (r)) & 0xFFFF) + (readw((lp)->base + (r) + 2) << 16))
+ #define SMC_outl(v, lp, r)                     \
        do{                                      \
-                writel(v & 0xFFFF, (a) + (r));  \
-                writel(v >> 16, (a) + (r) + 2); \
+                writew(v & 0xFFFF, (lp)->base + (r));   \
+                writew(v >> 16, (lp)->base + (r) + 2); \
         } while (0)
- #define SMC_insl(a, r, p, l)   readsw((short*)((a) + (r)), p, l*2)
- #define SMC_outsl(a, r, p, l)  writesw((short*)((a) + (r)), p, l*2)
+ #define SMC_insl(lp, r, p, l)  readsw((short*)((lp)->base + (r)), p, l*2)
+ #define SMC_outsl(lp, r, p, l)         writesw((short*)((lp)->base + (r)), p, l*2)
  
  #elif SMC_USE_32BIT
- #define SMC_inb(a, r)          readb((a) + (r))
- #define SMC_inw(a, r)          readw((a) + (r))
- #define SMC_inl(a, r)          readl((a) + (r))
- #define SMC_outb(v, a, r)      writeb(v, (a) + (r))
- #define SMC_outl(v, a, r)      writel(v, (a) + (r))
- #define SMC_insl(a, r, p, l)   readsl((int*)((a) + (r)), p, l)
- #define SMC_outsl(a, r, p, l)  writesl((int*)((a) + (r)), p, l)
+ #define SMC_inl(lp, r)                 readl((lp)->base + (r))
+ #define SMC_outl(v, lp, r)     writel(v, (lp)->base + (r))
+ #define SMC_insl(lp, r, p, l)  readsl((int*)((lp)->base + (r)), p, l)
+ #define SMC_outsl(lp, r, p, l)         writesl((int*)((lp)->base + (r)), p, l)
  
  #endif /* SMC_USE_16BIT */
+ #endif /* SMC_DYNAMIC_BUS_CONFIG */
  
  
  #ifdef SMC_USE_PXA_DMA
@@@ -120,22 -229,22 +239,22 @@@ static int rx_dmalen, tx_dmalen
  
  #ifdef SMC_insl
  #undef SMC_insl
- #define SMC_insl(a, r, p, l) \
-       smc_pxa_dma_insl(lp->dev, a, lp->physaddr, r, lp->rxdma, p, l)
+ #define SMC_insl(lp, r, p, l) \
+       smc_pxa_dma_insl(lp, lp->physaddr, r, lp->rxdma, p, l)
  
  static inline void
- smc_pxa_dma_insl(struct device *dev, u_long ioaddr, u_long physaddr,
+ smc_pxa_dma_insl(struct smc911x_local *lp, u_long physaddr,
                int reg, int dma, u_char *buf, int len)
  {
        /* 64 bit alignment is required for memory to memory DMA */
        if ((long)buf & 4) {
-               *((u32 *)buf) = SMC_inl(ioaddr, reg);
+               *((u32 *)buf) = SMC_inl(lp, reg);
                buf += 4;
                len--;
        }
  
        len *= 4;
-       rx_dmabuf = dma_map_single(dev, buf, len, DMA_FROM_DEVICE);
+       rx_dmabuf = dma_map_single(lp->dev, buf, len, DMA_FROM_DEVICE);
        rx_dmalen = len;
        DCSR(dma) = DCSR_NODESC;
        DTADR(dma) = rx_dmabuf;
  }
  #endif
  
- #ifdef SMC_insw
- #undef SMC_insw
- #define SMC_insw(a, r, p, l) \
-       smc_pxa_dma_insw(lp->dev, a, lp->physaddr, r, lp->rxdma, p, l)
- static inline void
- smc_pxa_dma_insw(struct device *dev, u_long ioaddr, u_long physaddr,
-               int reg, int dma, u_char *buf, int len)
- {
-       /* 64 bit alignment is required for memory to memory DMA */
-       while ((long)buf & 6) {
-               *((u16 *)buf) = SMC_inw(ioaddr, reg);
-               buf += 2;
-               len--;
-       }
-       len *= 2;
-       rx_dmabuf = dma_map_single(dev, buf, len, DMA_FROM_DEVICE);
-       rx_dmalen = len;
-       DCSR(dma) = DCSR_NODESC;
-       DTADR(dma) = rx_dmabuf;
-       DSADR(dma) = physaddr + reg;
-       DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 |
-               DCMD_WIDTH2 | DCMD_ENDIRQEN | (DCMD_LENGTH & rx_dmalen));
-       DCSR(dma) = DCSR_NODESC | DCSR_RUN;
- }
- #endif
  #ifdef SMC_outsl
  #undef SMC_outsl
- #define SMC_outsl(a, r, p, l) \
-        smc_pxa_dma_outsl(lp->dev, a, lp->physaddr, r, lp->txdma, p, l)
+ #define SMC_outsl(lp, r, p, l) \
+        smc_pxa_dma_outsl(lp, lp->physaddr, r, lp->txdma, p, l)
  
  static inline void
- smc_pxa_dma_outsl(struct device *dev, u_long ioaddr, u_long physaddr,
+ smc_pxa_dma_outsl(struct smc911x_local *lp, u_long physaddr,
                int reg, int dma, u_char *buf, int len)
  {
        /* 64 bit alignment is required for memory to memory DMA */
        if ((long)buf & 4) {
-               SMC_outl(*((u32 *)buf), ioaddr, reg);
+               SMC_outl(*((u32 *)buf), lp, reg);
                buf += 4;
                len--;
        }
  
        len *= 4;
-       tx_dmabuf = dma_map_single(dev, buf, len, DMA_TO_DEVICE);
+       tx_dmabuf = dma_map_single(lp->dev, buf, len, DMA_TO_DEVICE);
        tx_dmalen = len;
        DCSR(dma) = DCSR_NODESC;
        DSADR(dma) = tx_dmabuf;
        DCSR(dma) = DCSR_NODESC | DCSR_RUN;
  }
  #endif
- #ifdef SMC_outsw
- #undef SMC_outsw
- #define SMC_outsw(a, r, p, l) \
-       smc_pxa_dma_outsw(lp->dev, a, lp->physaddr, r, lp->txdma, p, l)
- static inline void
- smc_pxa_dma_outsw(struct device *dev, u_long ioaddr, u_long physaddr,
-                 int reg, int dma, u_char *buf, int len)
- {
-       /* 64 bit alignment is required for memory to memory DMA */
-       while ((long)buf & 6) {
-               SMC_outw(*((u16 *)buf), ioaddr, reg);
-               buf += 2;
-               len--;
-       }
-       len *= 2;
-       tx_dmabuf = dma_map_single(dev, buf, len, DMA_TO_DEVICE);
-       tx_dmalen = len;
-       DCSR(dma) = DCSR_NODESC;
-       DSADR(dma) = tx_dmabuf;
-       DTADR(dma) = physaddr + reg;
-       DCMD(dma) = (DCMD_INCSRCADDR | DCMD_BURST32 |
-               DCMD_WIDTH2 | DCMD_ENDIRQEN | (DCMD_LENGTH & tx_dmalen));
-       DCSR(dma) = DCSR_NODESC | DCSR_RUN;
- }
- #endif
  #endif         /* SMC_USE_PXA_DMA */
  
  
@@@ -639,213 -691,213 +701,213 @@@ static const struct chip_id chip_ids[] 
   * capabilities.  Please use those and not the in/out primitives.
   */
  /* FIFO read/write macros */
- #define SMC_PUSH_DATA(p, l)   SMC_outsl( ioaddr, TX_DATA_FIFO, p, (l) >> 2 )
- #define SMC_PULL_DATA(p, l)   SMC_insl ( ioaddr, RX_DATA_FIFO, p, (l) >> 2 )
- #define SMC_SET_TX_FIFO(x)    SMC_outl( x, ioaddr, TX_DATA_FIFO )
- #define SMC_GET_RX_FIFO()     SMC_inl( ioaddr, RX_DATA_FIFO )
+ #define SMC_PUSH_DATA(lp, p, l)       SMC_outsl( lp, TX_DATA_FIFO, p, (l) >> 2 )
+ #define SMC_PULL_DATA(lp, p, l)       SMC_insl ( lp, RX_DATA_FIFO, p, (l) >> 2 )
+ #define SMC_SET_TX_FIFO(lp, x)        SMC_outl( x, lp, TX_DATA_FIFO )
+ #define SMC_GET_RX_FIFO(lp)   SMC_inl( lp, RX_DATA_FIFO )
  
  
  /* I/O mapped register read/write macros */
- #define SMC_GET_TX_STS_FIFO()         SMC_inl( ioaddr, TX_STATUS_FIFO )
- #define SMC_GET_RX_STS_FIFO()         SMC_inl( ioaddr, RX_STATUS_FIFO )
- #define SMC_GET_RX_STS_FIFO_PEEK()    SMC_inl( ioaddr, RX_STATUS_FIFO_PEEK )
- #define SMC_GET_PN()                  (SMC_inl( ioaddr, ID_REV ) >> 16)
- #define SMC_GET_REV()                 (SMC_inl( ioaddr, ID_REV ) & 0xFFFF)
- #define SMC_GET_IRQ_CFG()             SMC_inl( ioaddr, INT_CFG )
- #define SMC_SET_IRQ_CFG(x)            SMC_outl( x, ioaddr, INT_CFG )
- #define SMC_GET_INT()                 SMC_inl( ioaddr, INT_STS )
- #define SMC_ACK_INT(x)                        SMC_outl( x, ioaddr, INT_STS )
- #define SMC_GET_INT_EN()              SMC_inl( ioaddr, INT_EN )
- #define SMC_SET_INT_EN(x)             SMC_outl( x, ioaddr, INT_EN )
- #define SMC_GET_BYTE_TEST()           SMC_inl( ioaddr, BYTE_TEST )
- #define SMC_SET_BYTE_TEST(x)          SMC_outl( x, ioaddr, BYTE_TEST )
- #define SMC_GET_FIFO_INT()            SMC_inl( ioaddr, FIFO_INT )
- #define SMC_SET_FIFO_INT(x)           SMC_outl( x, ioaddr, FIFO_INT )
- #define SMC_SET_FIFO_TDA(x)                                   \
+ #define SMC_GET_TX_STS_FIFO(lp)               SMC_inl( lp, TX_STATUS_FIFO )
+ #define SMC_GET_RX_STS_FIFO(lp)               SMC_inl( lp, RX_STATUS_FIFO )
+ #define SMC_GET_RX_STS_FIFO_PEEK(lp)  SMC_inl( lp, RX_STATUS_FIFO_PEEK )
+ #define SMC_GET_PN(lp)                        (SMC_inl( lp, ID_REV ) >> 16)
+ #define SMC_GET_REV(lp)                       (SMC_inl( lp, ID_REV ) & 0xFFFF)
+ #define SMC_GET_IRQ_CFG(lp)           SMC_inl( lp, INT_CFG )
+ #define SMC_SET_IRQ_CFG(lp, x)                SMC_outl( x, lp, INT_CFG )
+ #define SMC_GET_INT(lp)                       SMC_inl( lp, INT_STS )
+ #define SMC_ACK_INT(lp, x)                    SMC_outl( x, lp, INT_STS )
+ #define SMC_GET_INT_EN(lp)            SMC_inl( lp, INT_EN )
+ #define SMC_SET_INT_EN(lp, x)         SMC_outl( x, lp, INT_EN )
+ #define SMC_GET_BYTE_TEST(lp)         SMC_inl( lp, BYTE_TEST )
+ #define SMC_SET_BYTE_TEST(lp, x)              SMC_outl( x, lp, BYTE_TEST )
+ #define SMC_GET_FIFO_INT(lp)          SMC_inl( lp, FIFO_INT )
+ #define SMC_SET_FIFO_INT(lp, x)               SMC_outl( x, lp, FIFO_INT )
+ #define SMC_SET_FIFO_TDA(lp, x)                                       \
        do {                                                    \
                unsigned long __flags;                          \
                int __mask;                                     \
                local_irq_save(__flags);                        \
-               __mask = SMC_GET_FIFO_INT() & ~(0xFF<<24);      \
-               SMC_SET_FIFO_INT( __mask | (x)<<24 );           \
+               __mask = SMC_GET_FIFO_INT((lp)) & ~(0xFF<<24);  \
+               SMC_SET_FIFO_INT( (lp), __mask | (x)<<24 );     \
                local_irq_restore(__flags);                     \
        } while (0)
- #define SMC_SET_FIFO_TSL(x)                                   \
+ #define SMC_SET_FIFO_TSL(lp, x)                                       \
        do {                                                    \
                unsigned long __flags;                          \
                int __mask;                                     \
                local_irq_save(__flags);                        \
-               __mask = SMC_GET_FIFO_INT() & ~(0xFF<<16);      \
-               SMC_SET_FIFO_INT( __mask | (((x) & 0xFF)<<16)); \
+               __mask = SMC_GET_FIFO_INT((lp)) & ~(0xFF<<16);  \
+               SMC_SET_FIFO_INT( (lp), __mask | (((x) & 0xFF)<<16));   \
                local_irq_restore(__flags);                     \
        } while (0)
- #define SMC_SET_FIFO_RSA(x)                                   \
+ #define SMC_SET_FIFO_RSA(lp, x)                                       \
        do {                                                    \
                unsigned long __flags;                          \
                int __mask;                                     \
                local_irq_save(__flags);                        \
-               __mask = SMC_GET_FIFO_INT() & ~(0xFF<<8);       \
-               SMC_SET_FIFO_INT( __mask | (((x) & 0xFF)<<8));  \
+               __mask = SMC_GET_FIFO_INT((lp)) & ~(0xFF<<8);   \
+               SMC_SET_FIFO_INT( (lp), __mask | (((x) & 0xFF)<<8));    \
                local_irq_restore(__flags);                     \
        } while (0)
- #define SMC_SET_FIFO_RSL(x)                                   \
+ #define SMC_SET_FIFO_RSL(lp, x)                                       \
        do {                                                    \
                unsigned long __flags;                          \
                int __mask;                                     \
                local_irq_save(__flags);                        \
-               __mask = SMC_GET_FIFO_INT() & ~0xFF;            \
-               SMC_SET_FIFO_INT( __mask | ((x) & 0xFF));       \
+               __mask = SMC_GET_FIFO_INT((lp)) & ~0xFF;        \
+               SMC_SET_FIFO_INT( (lp),__mask | ((x) & 0xFF));  \
                local_irq_restore(__flags);                     \
        } while (0)
- #define SMC_GET_RX_CFG()              SMC_inl( ioaddr, RX_CFG )
- #define SMC_SET_RX_CFG(x)             SMC_outl( x, ioaddr, RX_CFG )
- #define SMC_GET_TX_CFG()              SMC_inl( ioaddr, TX_CFG )
- #define SMC_SET_TX_CFG(x)             SMC_outl( x, ioaddr, TX_CFG )
- #define SMC_GET_HW_CFG()              SMC_inl( ioaddr, HW_CFG )
- #define SMC_SET_HW_CFG(x)             SMC_outl( x, ioaddr, HW_CFG )
- #define SMC_GET_RX_DP_CTRL()          SMC_inl( ioaddr, RX_DP_CTRL )
- #define SMC_SET_RX_DP_CTRL(x)         SMC_outl( x, ioaddr, RX_DP_CTRL )
- #define SMC_GET_PMT_CTRL()            SMC_inl( ioaddr, PMT_CTRL )
- #define SMC_SET_PMT_CTRL(x)           SMC_outl( x, ioaddr, PMT_CTRL )
- #define SMC_GET_GPIO_CFG()            SMC_inl( ioaddr, GPIO_CFG )
- #define SMC_SET_GPIO_CFG(x)           SMC_outl( x, ioaddr, GPIO_CFG )
- #define SMC_GET_RX_FIFO_INF()         SMC_inl( ioaddr, RX_FIFO_INF )
- #define SMC_SET_RX_FIFO_INF(x)                SMC_outl( x, ioaddr, RX_FIFO_INF )
- #define SMC_GET_TX_FIFO_INF()         SMC_inl( ioaddr, TX_FIFO_INF )
- #define SMC_SET_TX_FIFO_INF(x)                SMC_outl( x, ioaddr, TX_FIFO_INF )
- #define SMC_GET_GPT_CFG()             SMC_inl( ioaddr, GPT_CFG )
- #define SMC_SET_GPT_CFG(x)            SMC_outl( x, ioaddr, GPT_CFG )
- #define SMC_GET_RX_DROP()             SMC_inl( ioaddr, RX_DROP )
- #define SMC_SET_RX_DROP(x)            SMC_outl( x, ioaddr, RX_DROP )
- #define SMC_GET_MAC_CMD()             SMC_inl( ioaddr, MAC_CSR_CMD )
- #define SMC_SET_MAC_CMD(x)            SMC_outl( x, ioaddr, MAC_CSR_CMD )
- #define SMC_GET_MAC_DATA()            SMC_inl( ioaddr, MAC_CSR_DATA )
- #define SMC_SET_MAC_DATA(x)           SMC_outl( x, ioaddr, MAC_CSR_DATA )
- #define SMC_GET_AFC_CFG()             SMC_inl( ioaddr, AFC_CFG )
- #define SMC_SET_AFC_CFG(x)            SMC_outl( x, ioaddr, AFC_CFG )
- #define SMC_GET_E2P_CMD()             SMC_inl( ioaddr, E2P_CMD )
- #define SMC_SET_E2P_CMD(x)            SMC_outl( x, ioaddr, E2P_CMD )
- #define SMC_GET_E2P_DATA()            SMC_inl( ioaddr, E2P_DATA )
- #define SMC_SET_E2P_DATA(x)           SMC_outl( x, ioaddr, E2P_DATA )
+ #define SMC_GET_RX_CFG(lp)            SMC_inl( lp, RX_CFG )
+ #define SMC_SET_RX_CFG(lp, x)         SMC_outl( x, lp, RX_CFG )
+ #define SMC_GET_TX_CFG(lp)            SMC_inl( lp, TX_CFG )
+ #define SMC_SET_TX_CFG(lp, x)         SMC_outl( x, lp, TX_CFG )
+ #define SMC_GET_HW_CFG(lp)            SMC_inl( lp, HW_CFG )
+ #define SMC_SET_HW_CFG(lp, x)         SMC_outl( x, lp, HW_CFG )
+ #define SMC_GET_RX_DP_CTRL(lp)                SMC_inl( lp, RX_DP_CTRL )
+ #define SMC_SET_RX_DP_CTRL(lp, x)             SMC_outl( x, lp, RX_DP_CTRL )
+ #define SMC_GET_PMT_CTRL(lp)          SMC_inl( lp, PMT_CTRL )
+ #define SMC_SET_PMT_CTRL(lp, x)               SMC_outl( x, lp, PMT_CTRL )
+ #define SMC_GET_GPIO_CFG(lp)          SMC_inl( lp, GPIO_CFG )
+ #define SMC_SET_GPIO_CFG(lp, x)               SMC_outl( x, lp, GPIO_CFG )
+ #define SMC_GET_RX_FIFO_INF(lp)               SMC_inl( lp, RX_FIFO_INF )
+ #define SMC_SET_RX_FIFO_INF(lp, x)            SMC_outl( x, lp, RX_FIFO_INF )
+ #define SMC_GET_TX_FIFO_INF(lp)               SMC_inl( lp, TX_FIFO_INF )
+ #define SMC_SET_TX_FIFO_INF(lp, x)            SMC_outl( x, lp, TX_FIFO_INF )
+ #define SMC_GET_GPT_CFG(lp)           SMC_inl( lp, GPT_CFG )
+ #define SMC_SET_GPT_CFG(lp, x)                SMC_outl( x, lp, GPT_CFG )
+ #define SMC_GET_RX_DROP(lp)           SMC_inl( lp, RX_DROP )
+ #define SMC_SET_RX_DROP(lp, x)                SMC_outl( x, lp, RX_DROP )
+ #define SMC_GET_MAC_CMD(lp)           SMC_inl( lp, MAC_CSR_CMD )
+ #define SMC_SET_MAC_CMD(lp, x)                SMC_outl( x, lp, MAC_CSR_CMD )
+ #define SMC_GET_MAC_DATA(lp)          SMC_inl( lp, MAC_CSR_DATA )
+ #define SMC_SET_MAC_DATA(lp, x)               SMC_outl( x, lp, MAC_CSR_DATA )
+ #define SMC_GET_AFC_CFG(lp)           SMC_inl( lp, AFC_CFG )
+ #define SMC_SET_AFC_CFG(lp, x)                SMC_outl( x, lp, AFC_CFG )
+ #define SMC_GET_E2P_CMD(lp)           SMC_inl( lp, E2P_CMD )
+ #define SMC_SET_E2P_CMD(lp, x)                SMC_outl( x, lp, E2P_CMD )
+ #define SMC_GET_E2P_DATA(lp)          SMC_inl( lp, E2P_DATA )
+ #define SMC_SET_E2P_DATA(lp, x)               SMC_outl( x, lp, E2P_DATA )
  
  /* MAC register read/write macros */
- #define SMC_GET_MAC_CSR(a,v)                                          \
+ #define SMC_GET_MAC_CSR(lp,a,v)                                               \
        do {                                                            \
-               while (SMC_GET_MAC_CMD() & MAC_CSR_CMD_CSR_BUSY_);      \
-               SMC_SET_MAC_CMD(MAC_CSR_CMD_CSR_BUSY_ |                 \
+               while (SMC_GET_MAC_CMD((lp)) & MAC_CSR_CMD_CSR_BUSY_);  \
+               SMC_SET_MAC_CMD((lp),MAC_CSR_CMD_CSR_BUSY_ |            \
                        MAC_CSR_CMD_R_NOT_W_ | (a) );                   \
-               while (SMC_GET_MAC_CMD() & MAC_CSR_CMD_CSR_BUSY_);      \
-               v = SMC_GET_MAC_DATA();                                 \
+               while (SMC_GET_MAC_CMD((lp)) & MAC_CSR_CMD_CSR_BUSY_);  \
+               v = SMC_GET_MAC_DATA((lp));                             \
        } while (0)
- #define SMC_SET_MAC_CSR(a,v)                                          \
+ #define SMC_SET_MAC_CSR(lp,a,v)                                               \
        do {                                                            \
-               while (SMC_GET_MAC_CMD() & MAC_CSR_CMD_CSR_BUSY_);      \
-               SMC_SET_MAC_DATA(v);                                    \
-               SMC_SET_MAC_CMD(MAC_CSR_CMD_CSR_BUSY_ | (a) );          \
-               while (SMC_GET_MAC_CMD() & MAC_CSR_CMD_CSR_BUSY_);      \
+               while (SMC_GET_MAC_CMD((lp)) & MAC_CSR_CMD_CSR_BUSY_);  \
+               SMC_SET_MAC_DATA((lp), v);                              \
+               SMC_SET_MAC_CMD((lp), MAC_CSR_CMD_CSR_BUSY_ | (a) );    \
+               while (SMC_GET_MAC_CMD((lp)) & MAC_CSR_CMD_CSR_BUSY_);  \
        } while (0)
- #define SMC_GET_MAC_CR(x)     SMC_GET_MAC_CSR( MAC_CR, x )
- #define SMC_SET_MAC_CR(x)     SMC_SET_MAC_CSR( MAC_CR, x )
- #define SMC_GET_ADDRH(x)      SMC_GET_MAC_CSR( ADDRH, x )
- #define SMC_SET_ADDRH(x)      SMC_SET_MAC_CSR( ADDRH, x )
- #define SMC_GET_ADDRL(x)      SMC_GET_MAC_CSR( ADDRL, x )
- #define SMC_SET_ADDRL(x)      SMC_SET_MAC_CSR( ADDRL, x )
- #define SMC_GET_HASHH(x)      SMC_GET_MAC_CSR( HASHH, x )
- #define SMC_SET_HASHH(x)      SMC_SET_MAC_CSR( HASHH, x )
- #define SMC_GET_HASHL(x)      SMC_GET_MAC_CSR( HASHL, x )
- #define SMC_SET_HASHL(x)      SMC_SET_MAC_CSR( HASHL, x )
- #define SMC_GET_MII_ACC(x)    SMC_GET_MAC_CSR( MII_ACC, x )
- #define SMC_SET_MII_ACC(x)    SMC_SET_MAC_CSR( MII_ACC, x )
- #define SMC_GET_MII_DATA(x)   SMC_GET_MAC_CSR( MII_DATA, x )
- #define SMC_SET_MII_DATA(x)   SMC_SET_MAC_CSR( MII_DATA, x )
- #define SMC_GET_FLOW(x)               SMC_GET_MAC_CSR( FLOW, x )
- #define SMC_SET_FLOW(x)               SMC_SET_MAC_CSR( FLOW, x )
- #define SMC_GET_VLAN1(x)      SMC_GET_MAC_CSR( VLAN1, x )
- #define SMC_SET_VLAN1(x)      SMC_SET_MAC_CSR( VLAN1, x )
- #define SMC_GET_VLAN2(x)      SMC_GET_MAC_CSR( VLAN2, x )
- #define SMC_SET_VLAN2(x)      SMC_SET_MAC_CSR( VLAN2, x )
- #define SMC_SET_WUFF(x)               SMC_SET_MAC_CSR( WUFF, x )
- #define SMC_GET_WUCSR(x)      SMC_GET_MAC_CSR( WUCSR, x )
- #define SMC_SET_WUCSR(x)      SMC_SET_MAC_CSR( WUCSR, x )
+ #define SMC_GET_MAC_CR(lp, x) SMC_GET_MAC_CSR( (lp), MAC_CR, x )
+ #define SMC_SET_MAC_CR(lp, x) SMC_SET_MAC_CSR( (lp), MAC_CR, x )
+ #define SMC_GET_ADDRH(lp, x)  SMC_GET_MAC_CSR( (lp), ADDRH, x )
+ #define SMC_SET_ADDRH(lp, x)  SMC_SET_MAC_CSR( (lp), ADDRH, x )
+ #define SMC_GET_ADDRL(lp, x)  SMC_GET_MAC_CSR( (lp), ADDRL, x )
+ #define SMC_SET_ADDRL(lp, x)  SMC_SET_MAC_CSR( (lp), ADDRL, x )
+ #define SMC_GET_HASHH(lp, x)  SMC_GET_MAC_CSR( (lp), HASHH, x )
+ #define SMC_SET_HASHH(lp, x)  SMC_SET_MAC_CSR( (lp), HASHH, x )
+ #define SMC_GET_HASHL(lp, x)  SMC_GET_MAC_CSR( (lp), HASHL, x )
+ #define SMC_SET_HASHL(lp, x)  SMC_SET_MAC_CSR( (lp), HASHL, x )
+ #define SMC_GET_MII_ACC(lp, x)        SMC_GET_MAC_CSR( (lp), MII_ACC, x )
+ #define SMC_SET_MII_ACC(lp, x)        SMC_SET_MAC_CSR( (lp), MII_ACC, x )
+ #define SMC_GET_MII_DATA(lp, x)       SMC_GET_MAC_CSR( (lp), MII_DATA, x )
+ #define SMC_SET_MII_DATA(lp, x)       SMC_SET_MAC_CSR( (lp), MII_DATA, x )
+ #define SMC_GET_FLOW(lp, x)           SMC_GET_MAC_CSR( (lp), FLOW, x )
+ #define SMC_SET_FLOW(lp, x)           SMC_SET_MAC_CSR( (lp), FLOW, x )
+ #define SMC_GET_VLAN1(lp, x)  SMC_GET_MAC_CSR( (lp), VLAN1, x )
+ #define SMC_SET_VLAN1(lp, x)  SMC_SET_MAC_CSR( (lp), VLAN1, x )
+ #define SMC_GET_VLAN2(lp, x)  SMC_GET_MAC_CSR( (lp), VLAN2, x )
+ #define SMC_SET_VLAN2(lp, x)  SMC_SET_MAC_CSR( (lp), VLAN2, x )
+ #define SMC_SET_WUFF(lp, x)           SMC_SET_MAC_CSR( (lp), WUFF, x )
+ #define SMC_GET_WUCSR(lp, x)  SMC_GET_MAC_CSR( (lp), WUCSR, x )
+ #define SMC_SET_WUCSR(lp, x)  SMC_SET_MAC_CSR( (lp), WUCSR, x )
  
  /* PHY register read/write macros */
- #define SMC_GET_MII(a,phy,v)                                  \
+ #define SMC_GET_MII(lp,a,phy,v)                                       \
        do {                                                    \
                u32 __v;                                        \
                do {                                            \
-                       SMC_GET_MII_ACC(__v);                   \
+                       SMC_GET_MII_ACC((lp), __v);                     \
                } while ( __v & MII_ACC_MII_BUSY_ );            \
-               SMC_SET_MII_ACC( ((phy)<<11) | ((a)<<6) |       \
+               SMC_SET_MII_ACC( (lp), ((phy)<<11) | ((a)<<6) | \
                        MII_ACC_MII_BUSY_);                     \
                do {                                            \
-                       SMC_GET_MII_ACC(__v);                   \
+                       SMC_GET_MII_ACC( (lp), __v);                    \
                } while ( __v & MII_ACC_MII_BUSY_ );            \
-               SMC_GET_MII_DATA(v);                            \
+               SMC_GET_MII_DATA((lp), v);                              \
        } while (0)
- #define SMC_SET_MII(a,phy,v)                                  \
+ #define SMC_SET_MII(lp,a,phy,v)                                       \
        do {                                                    \
                u32 __v;                                        \
                do {                                            \
-                       SMC_GET_MII_ACC(__v);                   \
+                       SMC_GET_MII_ACC((lp), __v);                     \
                } while ( __v & MII_ACC_MII_BUSY_ );            \
-               SMC_SET_MII_DATA(v);                            \
-               SMC_SET_MII_ACC( ((phy)<<11) | ((a)<<6) |       \
+               SMC_SET_MII_DATA((lp), v);                              \
+               SMC_SET_MII_ACC( (lp), ((phy)<<11) | ((a)<<6) | \
                        MII_ACC_MII_BUSY_        |              \
                        MII_ACC_MII_WRITE_  );                  \
                do {                                            \
-                       SMC_GET_MII_ACC(__v);                   \
+                       SMC_GET_MII_ACC((lp), __v);                     \
                } while ( __v & MII_ACC_MII_BUSY_ );            \
        } while (0)
- #define SMC_GET_PHY_BMCR(phy,x)               SMC_GET_MII( MII_BMCR, phy, x )
- #define SMC_SET_PHY_BMCR(phy,x)               SMC_SET_MII( MII_BMCR, phy, x )
- #define SMC_GET_PHY_BMSR(phy,x)               SMC_GET_MII( MII_BMSR, phy, x )
- #define SMC_GET_PHY_ID1(phy,x)                SMC_GET_MII( MII_PHYSID1, phy, x )
- #define SMC_GET_PHY_ID2(phy,x)                SMC_GET_MII( MII_PHYSID2, phy, x )
- #define SMC_GET_PHY_MII_ADV(phy,x)    SMC_GET_MII( MII_ADVERTISE, phy, x )
- #define SMC_SET_PHY_MII_ADV(phy,x)    SMC_SET_MII( MII_ADVERTISE, phy, x )
- #define SMC_GET_PHY_MII_LPA(phy,x)    SMC_GET_MII( MII_LPA, phy, x )
- #define SMC_SET_PHY_MII_LPA(phy,x)    SMC_SET_MII( MII_LPA, phy, x )
- #define SMC_GET_PHY_CTRL_STS(phy,x)   SMC_GET_MII( PHY_MODE_CTRL_STS, phy, x )
- #define SMC_SET_PHY_CTRL_STS(phy,x)   SMC_SET_MII( PHY_MODE_CTRL_STS, phy, x )
- #define SMC_GET_PHY_INT_SRC(phy,x)    SMC_GET_MII( PHY_INT_SRC, phy, x )
- #define SMC_SET_PHY_INT_SRC(phy,x)    SMC_SET_MII( PHY_INT_SRC, phy, x )
- #define SMC_GET_PHY_INT_MASK(phy,x)   SMC_GET_MII( PHY_INT_MASK, phy, x )
- #define SMC_SET_PHY_INT_MASK(phy,x)   SMC_SET_MII( PHY_INT_MASK, phy, x )
- #define SMC_GET_PHY_SPECIAL(phy,x)    SMC_GET_MII( PHY_SPECIAL, phy, x )
+ #define SMC_GET_PHY_BMCR(lp,phy,x)            SMC_GET_MII( (lp), MII_BMCR, phy, x )
+ #define SMC_SET_PHY_BMCR(lp,phy,x)            SMC_SET_MII( (lp), MII_BMCR, phy, x )
+ #define SMC_GET_PHY_BMSR(lp,phy,x)            SMC_GET_MII( (lp), MII_BMSR, phy, x )
+ #define SMC_GET_PHY_ID1(lp,phy,x)             SMC_GET_MII( (lp), MII_PHYSID1, phy, x )
+ #define SMC_GET_PHY_ID2(lp,phy,x)             SMC_GET_MII( (lp), MII_PHYSID2, phy, x )
+ #define SMC_GET_PHY_MII_ADV(lp,phy,x) SMC_GET_MII( (lp), MII_ADVERTISE, phy, x )
+ #define SMC_SET_PHY_MII_ADV(lp,phy,x) SMC_SET_MII( (lp), MII_ADVERTISE, phy, x )
+ #define SMC_GET_PHY_MII_LPA(lp,phy,x) SMC_GET_MII( (lp), MII_LPA, phy, x )
+ #define SMC_SET_PHY_MII_LPA(lp,phy,x) SMC_SET_MII( (lp), MII_LPA, phy, x )
+ #define SMC_GET_PHY_CTRL_STS(lp,phy,x)        SMC_GET_MII( (lp), PHY_MODE_CTRL_STS, phy, x )
+ #define SMC_SET_PHY_CTRL_STS(lp,phy,x)        SMC_SET_MII( (lp), PHY_MODE_CTRL_STS, phy, x )
+ #define SMC_GET_PHY_INT_SRC(lp,phy,x) SMC_GET_MII( (lp), PHY_INT_SRC, phy, x )
+ #define SMC_SET_PHY_INT_SRC(lp,phy,x) SMC_SET_MII( (lp), PHY_INT_SRC, phy, x )
+ #define SMC_GET_PHY_INT_MASK(lp,phy,x)        SMC_GET_MII( (lp), PHY_INT_MASK, phy, x )
+ #define SMC_SET_PHY_INT_MASK(lp,phy,x)        SMC_SET_MII( (lp), PHY_INT_MASK, phy, x )
+ #define SMC_GET_PHY_SPECIAL(lp,phy,x) SMC_GET_MII( (lp), PHY_SPECIAL, phy, x )
  
  
  
  /* Misc read/write macros */
  
  #ifndef SMC_GET_MAC_ADDR
- #define SMC_GET_MAC_ADDR(addr)                                        \
+ #define SMC_GET_MAC_ADDR(lp, addr)                            \
        do {                                                    \
                unsigned int __v;                               \
                                                                \
-               SMC_GET_MAC_CSR(ADDRL, __v);                    \
+               SMC_GET_MAC_CSR((lp), ADDRL, __v);                      \
                addr[0] = __v; addr[1] = __v >> 8;              \
                addr[2] = __v >> 16; addr[3] = __v >> 24;       \
-               SMC_GET_MAC_CSR(ADDRH, __v);                    \
+               SMC_GET_MAC_CSR((lp), ADDRH, __v);                      \
                addr[4] = __v; addr[5] = __v >> 8;              \
        } while (0)
  #endif
  
- #define SMC_SET_MAC_ADDR(addr)                                        \
+ #define SMC_SET_MAC_ADDR(lp, addr)                            \
        do {                                                    \
-                SMC_SET_MAC_CSR(ADDRL,                         \
+                SMC_SET_MAC_CSR((lp), ADDRL,                           \
                                 addr[0] |                      \
                                (addr[1] << 8) |                \
                                (addr[2] << 16) |               \
                                (addr[3] << 24));               \
-                SMC_SET_MAC_CSR(ADDRH, addr[4]|(addr[5] << 8));\
+                SMC_SET_MAC_CSR((lp), ADDRH, addr[4]|(addr[5] << 8));\
        } while (0)
  
  
- #define SMC_WRITE_EEPROM_CMD(cmd, addr)                                       \
+ #define SMC_WRITE_EEPROM_CMD(lp, cmd, addr)                           \
        do {                                                            \
-               while (SMC_GET_E2P_CMD() & MAC_CSR_CMD_CSR_BUSY_);      \
-               SMC_SET_MAC_CMD(MAC_CSR_CMD_R_NOT_W_ | a );             \
-               while (SMC_GET_MAC_CMD() & MAC_CSR_CMD_CSR_BUSY_);      \
+               while (SMC_GET_E2P_CMD((lp)) & MAC_CSR_CMD_CSR_BUSY_);  \
+               SMC_SET_MAC_CMD((lp), MAC_CSR_CMD_R_NOT_W_ | a );               \
+               while (SMC_GET_MAC_CMD((lp)) & MAC_CSR_CMD_CSR_BUSY_);  \
        } while (0)
  
  #endif         /* _SMC911X_H_ */
diff --combined drivers/net/smc91x.c
index 776c81de06cd705bd3074f344335f989848afe42,2040965d7724bc29fd0cc92532ca9e65dded071c..d2c493918030198e8c2b1c8b3d8eb76771f306a5
@@@ -308,7 -308,7 +308,7 @@@ static void smc_reset(struct net_devic
         * can't handle it then there will be no recovery except for
         * a hard reset or power cycle
         */
-       if (nowait)
+       if (lp->cfg.flags & SMC91X_NOWAIT)
                cfg |= CONFIG_NO_WAIT;
  
        /*
@@@ -448,11 -448,6 +448,11 @@@ static inline void  smc_rcv(struct net_
                dev->name, packet_number, status,
                packet_len, packet_len);
  
 +      if (unlikely(packet_len == 0 && !(status & RS_ERRORS))) {
 +              printk(KERN_ERR "%s: bad memory timings: rxlen %u status %x\n",
 +                      dev->name, packet_len, status);
 +              status |= RS_TOOSHORT;
 +      }
        back:
        if (unlikely(packet_len < 6 || status & RS_ERRORS)) {
                if (status & RS_TOOLONG && packet_len <= (1514 + 4 + 6)) {
@@@ -1944,8 -1939,11 +1944,11 @@@ static int __init smc_probe(struct net_
                if (retval)
                        goto err_out;
  
- #ifdef SMC_USE_PXA_DMA
-       {
+ #ifdef CONFIG_ARCH_PXA
+ #  ifdef SMC_USE_PXA_DMA
+       lp->cfg.flags |= SMC91X_USE_DMA;
+ #  endif
+       if (lp->cfg.flags & SMC91X_USE_DMA) {
                int dma = pxa_request_dma(dev->name, DMA_PRIO_LOW,
                                          smc_pxa_dma_irq, NULL);
                if (dma >= 0)
        }
  
  err_out:
- #ifdef SMC_USE_PXA_DMA
+ #ifdef CONFIG_ARCH_PXA
        if (retval && dev->dma != (unsigned char)-1)
                pxa_free_dma(dev->dma);
  #endif
@@@ -2055,9 -2053,11 +2058,11 @@@ static int smc_enable_device(struct pla
        return 0;
  }
  
- static int smc_request_attrib(struct platform_device *pdev)
+ static int smc_request_attrib(struct platform_device *pdev,
+                             struct net_device *ndev)
  {
        struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib");
+       struct smc_local *lp = netdev_priv(ndev);
  
        if (!res)
                return 0;
        return 0;
  }
  
- static void smc_release_attrib(struct platform_device *pdev)
+ static void smc_release_attrib(struct platform_device *pdev,
+                              struct net_device *ndev)
  {
        struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib");
+       struct smc_local *lp = netdev_priv(ndev);
  
        if (res)
                release_mem_region(res->start, ATTRIB_SIZE);
@@@ -2128,27 -2130,14 +2135,14 @@@ static int smc_drv_probe(struct platfor
        struct net_device *ndev;
        struct resource *res, *ires;
        unsigned int __iomem *addr;
+       unsigned long irq_flags = SMC_IRQ_FLAGS;
        int ret;
  
-       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-regs");
-       if (!res)
-               res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               ret = -ENODEV;
-               goto out;
-       }
-       if (!request_mem_region(res->start, SMC_IO_EXTENT, CARDNAME)) {
-               ret = -EBUSY;
-               goto out;
-       }
        ndev = alloc_etherdev(sizeof(struct smc_local));
        if (!ndev) {
                printk("%s: could not allocate device.\n", CARDNAME);
                ret = -ENOMEM;
-               goto out_release_io;
+               goto out;
        }
        SET_NETDEV_DEV(ndev, &pdev->dev);
  
         */
  
        lp = netdev_priv(ndev);
-       lp->cfg.irq_flags = SMC_IRQ_FLAGS;
  
- #ifdef SMC_DYNAMIC_BUS_CONFIG
-       if (pd)
+       if (pd) {
                memcpy(&lp->cfg, pd, sizeof(lp->cfg));
-       else {
-               lp->cfg.flags = SMC91X_USE_8BIT;
-               lp->cfg.flags |= SMC91X_USE_16BIT;
-               lp->cfg.flags |= SMC91X_USE_32BIT;
+               lp->io_shift = SMC91X_IO_SHIFT(lp->cfg.flags);
+       } else {
+               lp->cfg.flags |= (SMC_CAN_USE_8BIT)  ? SMC91X_USE_8BIT  : 0;
+               lp->cfg.flags |= (SMC_CAN_USE_16BIT) ? SMC91X_USE_16BIT : 0;
+               lp->cfg.flags |= (SMC_CAN_USE_32BIT) ? SMC91X_USE_32BIT : 0;
+               lp->cfg.flags |= (nowait) ? SMC91X_NOWAIT : 0;
        }
  
-       lp->cfg.flags &= ~(SMC_CAN_USE_8BIT ? 0 : SMC91X_USE_8BIT);
-       lp->cfg.flags &= ~(SMC_CAN_USE_16BIT ? 0 : SMC91X_USE_16BIT);
-       lp->cfg.flags &= ~(SMC_CAN_USE_32BIT ? 0 : SMC91X_USE_32BIT);
- #endif
        ndev->dma = (unsigned char)-1;
  
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-regs");
+       if (!res)
+               res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               ret = -ENODEV;
+               goto out_free_netdev;
+       }
+       if (!request_mem_region(res->start, SMC_IO_EXTENT, CARDNAME)) {
+               ret = -EBUSY;
+               goto out_free_netdev;
+       }
        ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
        if (!ires) {
                ret = -ENODEV;
-               goto out_free_netdev;
+               goto out_release_io;
        }
  
        ndev->irq = ires->start;
-       if (SMC_IRQ_FLAGS == -1)
-               lp->cfg.irq_flags = ires->flags & IRQF_TRIGGER_MASK;
  
-       ret = smc_request_attrib(pdev);
+       if (ires->flags & IRQF_TRIGGER_MASK)
+               irq_flags = ires->flags & IRQF_TRIGGER_MASK;
+       ret = smc_request_attrib(pdev, ndev);
        if (ret)
-               goto out_free_netdev;
+               goto out_release_io;
  #if defined(CONFIG_SA1100_ASSABET)
        NCR_0 |= NCR_ENET_OSC_EN;
  #endif
                goto out_release_attrib;
        }
  
- #ifdef SMC_USE_PXA_DMA
+ #ifdef CONFIG_ARCH_PXA
        {
                struct smc_local *lp = netdev_priv(ndev);
                lp->device = &pdev->dev;
        }
  #endif
  
-       ret = smc_probe(ndev, addr, lp->cfg.irq_flags);
+       ret = smc_probe(ndev, addr, irq_flags);
        if (ret != 0)
                goto out_iounmap;
  
        platform_set_drvdata(pdev, NULL);
        iounmap(addr);
   out_release_attrib:
-       smc_release_attrib(pdev);
-  out_free_netdev:
-       free_netdev(ndev);
+       smc_release_attrib(pdev, ndev);
   out_release_io:
        release_mem_region(res->start, SMC_IO_EXTENT);
+  out_free_netdev:
+       free_netdev(ndev);
   out:
        printk("%s: not found (%d).\n", CARDNAME, ret);
  
@@@ -2245,14 -2244,14 +2249,14 @@@ static int smc_drv_remove(struct platfo
  
        free_irq(ndev->irq, ndev);
  
- #ifdef SMC_USE_PXA_DMA
+ #ifdef CONFIG_ARCH_PXA
        if (ndev->dma != (unsigned char)-1)
                pxa_free_dma(ndev->dma);
  #endif
        iounmap(lp->base);
  
        smc_release_datacs(pdev,ndev);
-       smc_release_attrib(pdev);
+       smc_release_attrib(pdev,ndev);
  
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-regs");
        if (!res)
diff --combined drivers/power/Kconfig
index 80f45cd3f9fec51e3d3ab76d765953e389be7a52,9ce55850271a17c21365dee317f43219756eff53..7bd8c2b415756424e74bf50faad18285a4afdcaf
@@@ -49,33 -49,17 +49,46 @@@ config BATTERY_OLP
        help
          Say Y to enable support for the battery on the OLPC laptop.
  
 +config BATTERY_BQ27x00
 +      tristate "BQ27x00 battery driver"
 +      help
 +        Say Y here to enable support for batteries with BQ27000 or BQ27200 chip.
 +
 +config BATTERY_BQ27000
 +      bool "BQ27000 battery driver"
 +      depends on BATTERY_BQ27x00
 +      select W1
 +      select W1_SLAVE_BQ27000
 +      help
 +        Say Y here to enable support for batteries with BQ27000(HDQ) chip.
 +
 +config BATTERY_BQ27200
 +      bool "BQ27200 battery driver"
 +      depends on BATTERY_BQ27x00
 +      select I2C
 +      select I2C_OMAP
 +      help
 +        Say Y here to enable support for batteries with BQ27200(I2C) chip.
 +
 +config TWL4030_BCI_BATTERY
 +      tristate "OMAP TWL4030 BCI Battery driver"
 +      depends on (MACH_OMAP_2430SDP || MACH_OMAP_3430SDP) && TWL4030_MADC
 +      default y
 +      help
 +        Support for OMAP TWL4030 BCI Battery driver.
 +        This driver can give support for TWL4030 Battery Charge Interface.
 +
+ config BATTERY_TOSA
+       tristate "Sharp SL-6000 (tosa) battery"
+       depends on MACH_TOSA && MFD_TC6393XB
+       help
+         Say Y to enable support for the battery on the Sharp Zaurus
+         SL-6000 (tosa) models.
+ config BATTERY_PALMTX
+       tristate "Palm T|X battery"
+       depends on MACH_PALMTX
+       help
+         Say Y to enable support for the battery in Palm T|X.
  endif # POWER_SUPPLY
diff --combined drivers/power/Makefile
index a877c9077adeb9c8e74a7704245043ae1e55b836,4706bf8ff4595814565ebac8ee4cbb764ab91f63..8da941a8090d42d52443668c3342c09cc7aa6453
@@@ -20,5 -20,5 +20,7 @@@ obj-$(CONFIG_APM_POWER)               += apm_power.
  obj-$(CONFIG_BATTERY_DS2760)  += ds2760_battery.o
  obj-$(CONFIG_BATTERY_PMU)     += pmu_battery.o
  obj-$(CONFIG_BATTERY_OLPC)    += olpc_battery.o
 +obj-$(CONFIG_BATTERY_BQ27x00)   += bq27x00_battery.o
 +obj-$(CONFIG_TWL4030_BCI_BATTERY)     += twl4030_bci_battery.o
+ obj-$(CONFIG_BATTERY_TOSA)    += tosa_battery.o
+ obj-$(CONFIG_BATTERY_PALMTX)  += palmtx_battery.o
diff --combined drivers/rtc/Kconfig
index 3203e17367278d1906c63144ab6e95610a11e5d2,90ab73825401a0b5f4c0b7de15c5ff755a4edb7d..aefeafc0ae79888395f23941ba91b210f4eb4db6
@@@ -246,16 -246,6 +246,16 @@@ config RTC_DRV_TWL9233
          platforms.  The support is integrated with the rest of
          the Menelaus driver; it's not separate module.
  
 +config RTC_DRV_TWL4030
 +      tristate "OMAP TWL4030 Real Time Clock"
 +      depends on RTC_CLASS && TWL4030_CORE
 +      help
 +        If you say yes here you get support for internal Real-Time 
 +        Clock of TWL4030 chip.
 +
 +        This driver can also be built as a module. If so, the module
 +        will be called rtc-twl4030.
 +
  config RTC_DRV_S35390A
        tristate "Seiko Instruments S-35390A"
        select BITREVERSE
@@@ -283,6 -273,25 +283,25 @@@ comment "SPI RTC drivers
  
  if SPI_MASTER
  
+ config RTC_DRV_M41T94
+       tristate "ST M41T94"
+       help
+         If you say yes here you will get support for the
+         ST M41T94 SPI RTC chip.
+         This driver can also be built as a module. If so, the module
+         will be called rtc-m41t94.
+ config RTC_DRV_DS1305
+       tristate "Dallas/Maxim DS1305/DS1306"
+       help
+         Select this driver to get support for the Dallas/Maxim DS1305
+         and DS1306 real time clock chips.  These support a trickle
+         charger, alarms, and NVRAM in addition to the clock.
+         This driver can also be built as a module. If so, the module
+         will be called rtc-ds1305.
  config RTC_DRV_MAX6902
        tristate "Maxim MAX6902"
        help
@@@ -479,6 -488,16 +498,16 @@@ config RTC_DRV_VR41X
          To compile this driver as a module, choose M here: the
          module will be called rtc-vr41xx.
  
+ config RTC_DRV_PL030
+       tristate "ARM AMBA PL030 RTC"
+       depends on ARM_AMBA
+       help
+         If you say Y here you will get access to ARM AMBA
+         PrimeCell PL030 RTC found on certain ARM SOCs.
+         To compile this driver as a module, choose M here: the
+         module will be called rtc-pl030.
  config RTC_DRV_PL031
        tristate "ARM AMBA PL031 RTC"
        depends on ARM_AMBA
@@@ -505,12 -524,13 +534,13 @@@ config RTC_DRV_AT91RM920
          this is powered by the backup power supply.
  
  config RTC_DRV_AT91SAM9
-       tristate "AT91SAM9x"
+       tristate "AT91SAM9x/AT91CAP9"
        depends on ARCH_AT91 && !(ARCH_AT91RM9200 || ARCH_AT91X40)
        help
-         RTC driver for the Atmel AT91SAM9x internal RTT (Real Time Timer).
-         These timers are powered by the backup power supply (such as a
-         small coin cell battery), but do not need to be used as RTCs.
+         RTC driver for the Atmel AT91SAM9x and AT91CAP9 internal RTT
+         (Real Time Timer). These timers are powered by the backup power
+         supply (such as a small coin cell battery), but do not need to
+         be used as RTCs.
  
          (On AT91SAM9rl chips you probably want to use the dedicated RTC
          module and leave the RTT available for other uses.)
diff --combined drivers/rtc/Makefile
index 912b62499928c3e8315fe7a88c306ee0ae82ec2c,18622ef84cab0c4f48e15aa437edccff357136e4..3ef1dfcc90382e6c3ba6b5669c4788d7641b53af
@@@ -24,6 -24,7 +24,7 @@@ obj-$(CONFIG_RTC_DRV_BFIN)    += rtc-bfin.
  obj-$(CONFIG_RTC_DRV_CMOS)    += rtc-cmos.o
  obj-$(CONFIG_RTC_DRV_DS1216)  += rtc-ds1216.o
  obj-$(CONFIG_RTC_DRV_DS1302)  += rtc-ds1302.o
+ obj-$(CONFIG_RTC_DRV_DS1305)  += rtc-ds1305.o
  obj-$(CONFIG_RTC_DRV_DS1307)  += rtc-ds1307.o
  obj-$(CONFIG_RTC_DRV_DS1374)  += rtc-ds1374.o
  obj-$(CONFIG_RTC_DRV_DS1511)  += rtc-ds1511.o
@@@ -34,6 -35,7 +35,7 @@@ obj-$(CONFIG_RTC_DRV_EP93XX)  += rtc-ep9
  obj-$(CONFIG_RTC_DRV_FM3130)  += rtc-fm3130.o
  obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o
  obj-$(CONFIG_RTC_DRV_M41T80)  += rtc-m41t80.o
+ obj-$(CONFIG_RTC_DRV_M41T94)  += rtc-m41t94.o
  obj-$(CONFIG_RTC_DRV_M48T59)  += rtc-m48t59.o
  obj-$(CONFIG_RTC_DRV_M48T86)  += rtc-m48t86.o
  obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o
@@@ -41,6 -43,7 +43,7 @@@ obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-ma
  obj-$(CONFIG_RTC_DRV_OMAP)    += rtc-omap.o
  obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o
  obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o
+ obj-$(CONFIG_RTC_DRV_PL030)   += rtc-pl030.o
  obj-$(CONFIG_RTC_DRV_PL031)   += rtc-pl031.o
  obj-$(CONFIG_RTC_DRV_PPC)     += rtc-ppc.o
  obj-$(CONFIG_RTC_DRV_R9701)   += rtc-r9701.o
@@@ -53,7 -56,6 +56,7 @@@ obj-$(CONFIG_RTC_DRV_SA1100)  += rtc-sa1
  obj-$(CONFIG_RTC_DRV_SH)      += rtc-sh.o
  obj-$(CONFIG_RTC_DRV_STK17TA8)        += rtc-stk17ta8.o
  obj-$(CONFIG_RTC_DRV_TEST)    += rtc-test.o
 +obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl4030.o
  obj-$(CONFIG_RTC_DRV_V3020)   += rtc-v3020.o
  obj-$(CONFIG_RTC_DRV_VR41XX)  += rtc-vr41xx.o
  obj-$(CONFIG_RTC_DRV_X1205)   += rtc-x1205.o
diff --combined drivers/serial/8250.c
index 9b913db147a591fcadab8ba6a7e7be85e8c8ef1c,342e12fb1c2525f74bb15d0e21ca4e473962ecd1..5a5f95f7752301f39dc7057e035cd403f64d3ad8
@@@ -12,8 -12,6 +12,6 @@@
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
-  *  $Id: 8250.c,v 1.90 2002/07/28 10:03:27 rmk Exp $
-  *
   * A note about mapbase / membase
   *
   *  mapbase is the physical address of the IO port.
@@@ -1289,13 -1287,24 +1287,24 @@@ static void serial8250_enable_ms(struc
  static void
  receive_chars(struct uart_8250_port *up, unsigned int *status)
  {
-       struct tty_struct *tty = up->port.info->tty;
+       struct tty_struct *tty = up->port.info->port.tty;
        unsigned char ch, lsr = *status;
        int max_count = 256;
        char flag;
  
        do {
-               ch = serial_inp(up, UART_RX);
+               if (likely(lsr & UART_LSR_DR))
+                       ch = serial_inp(up, UART_RX);
+               else
+                       /*
+                        * Intel 82571 has a Serial Over Lan device that will
+                        * set UART_LSR_BI without setting UART_LSR_DR when
+                        * it receives a break. To avoid reading from the
+                        * receive buffer without UART_LSR_DR bit set, we
+                        * just force the read character to be 0
+                        */
+                       ch = 0;
                flag = TTY_NORMAL;
                up->port.icount.rx++;
  
  
  ignore_char:
                lsr = serial_inp(up, UART_LSR);
-       } while ((lsr & UART_LSR_DR) && (max_count-- > 0));
+       } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (max_count-- > 0));
        spin_unlock(&up->port.lock);
        tty_flip_buffer_push(tty);
        spin_lock(&up->port.lock);
@@@ -1427,7 -1436,7 +1436,7 @@@ serial8250_handle_port(struct uart_8250
  
        DEBUG_INTR("status = %x...", status);
  
-       if (status & UART_LSR_DR)
+       if (status & (UART_LSR_DR | UART_LSR_BI))
                receive_chars(up, &status);
        check_modem_status(up);
        if (status & UART_LSR_THRE)
@@@ -1504,11 -1513,7 +1513,11 @@@ static irqreturn_t serial8250_interrupt
  
        DEBUG_INTR("end.\n");
  
 +#ifdef CONFIG_ARCH_OMAP15XX
 +      return IRQ_HANDLED;     /* FIXME: iir status not ready on 1510 */
 +#else
        return IRQ_RETVAL(handled);
 +#endif
  }
  
  /*
@@@ -1881,6 -1886,8 +1890,8 @@@ static int serial8250_startup(struct ua
                 * allow register changes to become visible.
                 */
                spin_lock_irqsave(&up->port.lock, flags);
+               if (up->port.flags & UPF_SHARE_IRQ)
+                       disable_irq_nosync(up->port.irq);
  
                wait_for_xmitr(up, UART_LSR_THRE);
                serial_out_sync(up, UART_IER, UART_IER_THRI);
                iir = serial_in(up, UART_IIR);
                serial_out(up, UART_IER, 0);
  
+               if (up->port.flags & UPF_SHARE_IRQ)
+                       enable_irq(up->port.irq);
                spin_unlock_irqrestore(&up->port.lock, flags);
  
                /*
@@@ -2228,19 -2237,6 +2241,19 @@@ serial8250_set_termios(struct uart_por
                        /* emulated UARTs (Lucent Venus 167x) need two steps */
                        serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
                }
 +
 +              /* Note that we need to set ECB to access write water mark
 +               * bits. First allow FCR tx fifo write, then set fcr with
 +               * possible TX fifo settings. */
 +              if (uart_config[up->port.type].flags & UART_CAP_EFR) {
 +                      serial_outp(up, UART_LCR, 0xbf);        /* Access EFR */
 +                      serial_outp(up, UART_EFR, UART_EFR_ECB);
 +                      serial_outp(up, UART_LCR, 0x0);         /* Access FCR */
 +                      serial_outp(up, UART_FCR, fcr);
 +                      serial_outp(up, UART_LCR, 0xbf);        /* Access EFR */
 +                      serial_outp(up, UART_EFR, 0);
 +                      serial_outp(up, UART_LCR, cval);        /* Access FCR */
 +        } else
                serial_outp(up, UART_FCR, fcr);         /* set fcr */
        }
        serial8250_set_mctrl(&up->port, up->port.mctrl);
@@@ -2270,11 -2266,6 +2283,11 @@@ static int serial8250_request_std_resou
        unsigned int size = 8 << up->port.regshift;
        int ret = 0;
  
 +#ifdef CONFIG_ARCH_OMAP
 +      if (is_omap_port((unsigned int)up->port.membase))
 +              size = 0x16 << up->port.regshift;
 +#endif
 +
        switch (up->port.iotype) {
        case UPIO_AU:
                size = 0x100000;
@@@ -2956,7 -2947,7 +2969,7 @@@ static int __init serial8250_init(void
        if (nr_uarts > UART_NR)
                nr_uarts = UART_NR;
  
-       printk(KERN_INFO "Serial: 8250/16550 driver $Revision: 1.90 $ "
+       printk(KERN_INFO "Serial: 8250/16550 driver"
                "%d ports, IRQ sharing %sabled\n", nr_uarts,
                share_irqs ? "en" : "dis");
  
@@@ -3017,7 -3008,7 +3030,7 @@@ EXPORT_SYMBOL(serial8250_suspend_port)
  EXPORT_SYMBOL(serial8250_resume_port);
  
  MODULE_LICENSE("GPL");
- MODULE_DESCRIPTION("Generic 8250/16x50 serial driver $Revision: 1.90 $");
+ MODULE_DESCRIPTION("Generic 8250/16x50 serial driver");
  
  module_param(share_irqs, uint, 0644);
  MODULE_PARM_DESC(share_irqs, "Share IRQs with other non-8250/16x50 devices"
diff --combined drivers/spi/Kconfig
index 5b26a7c50b1ce474430d06a1ef4efc04cdb45121,b9d0efb6803f2919695c21ed6ba186303c51353c..c04029a859837ecb87336c8f23bf65e03584351b
@@@ -49,25 -49,26 +49,26 @@@ config SPI_MASTE
          controller and the protocol drivers for the SPI slave chips
          that are connected.
  
+ if SPI_MASTER
  comment "SPI Master Controller Drivers"
-       depends on SPI_MASTER
  
  config SPI_ATMEL
        tristate "Atmel SPI Controller"
-       depends on (ARCH_AT91 || AVR32) && SPI_MASTER
+       depends on (ARCH_AT91 || AVR32)
        help
          This selects a driver for the Atmel SPI Controller, present on
          many AT32 (AVR32) and AT91 (ARM) chips.
  
  config SPI_BFIN
        tristate "SPI controller driver for ADI Blackfin5xx"
-       depends on SPI_MASTER && BLACKFIN
+       depends on BLACKFIN
        help
          This is the SPI controller master driver for Blackfin 5xx processor.
  
  config SPI_AU1550
        tristate "Au1550/Au12x0 SPI Controller"
-       depends on SPI_MASTER && (SOC_AU1550 || SOC_AU1200) && EXPERIMENTAL
+       depends on (SOC_AU1550 || SOC_AU1200) && EXPERIMENTAL
        select SPI_BITBANG
        help
          If you say yes to this option, support will be included for the
@@@ -78,7 -79,6 +79,6 @@@
  
  config SPI_BITBANG
        tristate "Bitbanging SPI master"
-       depends on SPI_MASTER && EXPERIMENTAL
        help
          With a few GPIO pins, your system can bitbang the SPI protocol.
          Select this to get SPI support through I/O pins (GPIO, parallel
@@@ -92,7 -92,7 +92,7 @@@
  
  config SPI_BUTTERFLY
        tristate "Parallel port adapter for AVR Butterfly (DEVELOPMENT)"
-       depends on SPI_MASTER && PARPORT && EXPERIMENTAL
+       depends on PARPORT
        select SPI_BITBANG
        help
          This uses a custom parallel port cable to connect to an AVR
  
  config SPI_IMX
        tristate "Freescale iMX SPI controller"
-       depends on SPI_MASTER && ARCH_IMX && EXPERIMENTAL
+       depends on ARCH_IMX && EXPERIMENTAL
        help
          This enables using the Freescale iMX SPI controller in master
          mode.
  
  config SPI_LM70_LLP
        tristate "Parallel port adapter for LM70 eval board (DEVELOPMENT)"
-       depends on SPI_MASTER && PARPORT && EXPERIMENTAL
+       depends on PARPORT && EXPERIMENTAL
        select SPI_BITBANG
        help
          This driver supports the NS LM70 LLP Evaluation Board,
  
  config SPI_MPC52xx_PSC
        tristate "Freescale MPC52xx PSC SPI controller"
-       depends on SPI_MASTER && PPC_MPC52xx && EXPERIMENTAL
+       depends on PPC_MPC52xx && EXPERIMENTAL
        help
          This enables using the Freescale MPC52xx Programmable Serial
          Controller in master SPI mode.
  
  config SPI_MPC83xx
        tristate "Freescale MPC83xx/QUICC Engine SPI controller"
-       depends on SPI_MASTER && (PPC_83xx || QUICC_ENGINE) && EXPERIMENTAL
+       depends on (PPC_83xx || QUICC_ENGINE) && EXPERIMENTAL
        help
          This enables using the Freescale MPC83xx and QUICC Engine SPI
          controllers in master mode.
  
  config SPI_OMAP_UWIRE
        tristate "OMAP1 MicroWire"
-       depends on SPI_MASTER && ARCH_OMAP1
+       depends on ARCH_OMAP1
        select SPI_BITBANG
        help
          This hooks up to the MicroWire controller on OMAP1 chips.
  
  config SPI_OMAP24XX
        tristate "McSPI driver for OMAP24xx/OMAP34xx"
-       depends on SPI_MASTER && (ARCH_OMAP24XX || ARCH_OMAP34XX)
+       depends on ARCH_OMAP24XX || ARCH_OMAP34XX
        help
          SPI master controller for OMAP24xx/OMAP34xx Multichannel SPI
          (McSPI) modules.
  
+ config SPI_ORION
+       tristate "Orion SPI master (EXPERIMENTAL)"
+       depends on PLAT_ORION && EXPERIMENTAL
+       help
+         This enables using the SPI master controller on the Orion chips.
  config SPI_PXA2XX
        tristate "PXA2xx SSP SPI master"
-       depends on SPI_MASTER && ARCH_PXA && EXPERIMENTAL
+       depends on ARCH_PXA && EXPERIMENTAL
        select PXA_SSP
        help
          This enables using a PXA2xx SSP port as a SPI master controller.
  
  config SPI_S3C24XX
        tristate "Samsung S3C24XX series SPI"
-       depends on SPI_MASTER && ARCH_S3C2410 && EXPERIMENTAL
+       depends on ARCH_S3C2410 && EXPERIMENTAL
        select SPI_BITBANG
        help
          SPI driver for Samsung S3C24XX series ARM SoCs
  
  config SPI_S3C24XX_GPIO
        tristate "Samsung S3C24XX series SPI by GPIO"
-       depends on SPI_MASTER && ARCH_S3C2410 && EXPERIMENTAL
+       depends on ARCH_S3C2410 && EXPERIMENTAL
        select SPI_BITBANG
        help
          SPI driver for Samsung S3C24XX series ARM SoCs using
  
  config SPI_SH_SCI
        tristate "SuperH SCI SPI controller"
-       depends on SPI_MASTER && SUPERH
+       depends on SUPERH
        select SPI_BITBANG
        help
          SPI driver for SuperH SCI blocks.
  
  config SPI_TXX9
        tristate "Toshiba TXx9 SPI controller"
-       depends on SPI_MASTER && GENERIC_GPIO && CPU_TX49XX
+       depends on GENERIC_GPIO && CPU_TX49XX
        help
          SPI driver for Toshiba TXx9 MIPS SoCs
  
  config SPI_XILINX
        tristate "Xilinx SPI controller"
-       depends on SPI_MASTER && XILINX_VIRTEX && EXPERIMENTAL
+       depends on XILINX_VIRTEX && EXPERIMENTAL
        select SPI_BITBANG
        help
          This exposes the SPI controller IP from the Xilinx EDK.
  # being probably the most widely used ones.
  #
  comment "SPI Protocol Masters"
-       depends on SPI_MASTER
  
  config SPI_AT25
        tristate "SPI EEPROMs from most vendors"
-       depends on SPI_MASTER && SYSFS
+       depends on SYSFS
        help
          Enable this driver to get read/write support to most SPI EEPROMs,
          after you configure the board init code to know about each eeprom
          This driver can also be built as a module.  If so, the module
          will be called at25.
  
 +config SPI_TSC2101
 +       depends on SPI_MASTER
 +       tristate "TSC2101 chip support"
 +       ---help---
 +         Say Y here if you want support for the TSC2101 chip.
 +       At the moment it provides basic register read / write interface
 +       as well as a way to enable the MCLK clock.
 +       
 +config SPI_TSC2102
 +       depends on SPI_MASTER
 +       tristate "TSC2102 codec support"
 +       ---help---
 +         Say Y here if you want support for the TSC2102 chip.  It
 +       will be needed for the touchscreen driver on some boards.
 +
 +config SPI_TSC210X
 +      depends on SPI_MASTER && EXPERIMENTAL
 +      tristate "TI TSC210x (TSC2101/TSC2102) support"
 +      help
 +        Say Y here if you want support for the TSC210x chips.  Some
 +        boards use these for touchscreen and audio support.
 +
 +        These are members of a family of highly integrated PDA analog
 +        interface circuit.  They include a 12-bit ADC used for battery,
 +        temperature, touchscreen, and other sensors.  They also have
 +        an audio DAC and amplifier, and in some models an audio ADC.
 +        The audio support is highly chip-specific, but most of the
 +        sensor support works the same.
 +
 +        Note that the device has to be present in the board's SPI
 +        devices table for this driver to load.  This driver doesn't
 +        automatically enable touchscreen, sensors or audio
 +        functionality - enable these in their respective menus.
 +
 +config SPI_TSC2301
 +      tristate "TSC2301 driver"
 +      depends on SPI_MASTER
 +      help
 +        Say Y here if you have a TSC2301 chip connected to an SPI
 +        bus on your board.
 +
 +        The TSC2301 is a highly integrated PDA analog interface circuit.
 +        It contains a complete 12-bit A/D resistive touch screen
 +        converter (ADC) including drivers, touch pressure measurement
 +        capability, keypad controller, and 8-bit D/A converter (DAC) output
 +        for LCD contrast control.
 +
 +        To compile this driver as a module, choose M here: the
 +        module will be called tsc2301.
 +
 +config SPI_TSC2301_AUDIO
 +      boolean "TSC2301 audio support"
 +      depends on SPI_TSC2301 && SND
 +      help
 +        Say Y here for if you are using the audio features of TSC2301.
 +
  config SPI_SPIDEV
        tristate "User mode SPI device driver support"
-       depends on SPI_MASTER && EXPERIMENTAL
+       depends on EXPERIMENTAL
        help
          This supports user mode SPI protocol drivers.
  
  
  config SPI_TLE62X0
        tristate "Infineon TLE62X0 (for power switching)"
-       depends on SPI_MASTER && SYSFS
+       depends on SYSFS
        help
          SPI driver for Infineon TLE62X0 series line driver chips,
          such as the TLE6220, TLE6230 and TLE6240.  This provides a
  # Add new SPI protocol masters in alphabetical order above this line
  #
  
+ endif # SPI_MASTER
  # (slave support would go here)
  
  endif # SPI
diff --combined drivers/spi/Makefile
index 8490a68879989ce26571e7276f204696acccc239,ccf18de34e1e0df26a697b2939d58c7e62cf231d..1c2e7fc928e38f8217b9432aa7074909f77ca98a
@@@ -21,6 -21,7 +21,7 @@@ obj-$(CONFIG_SPI_LM70_LLP)            += spi_lm70
  obj-$(CONFIG_SPI_PXA2XX)              += pxa2xx_spi.o
  obj-$(CONFIG_SPI_OMAP_UWIRE)          += omap_uwire.o
  obj-$(CONFIG_SPI_OMAP24XX)            += omap2_mcspi.o
+ obj-$(CONFIG_SPI_ORION)                       += orion_spi.o
  obj-$(CONFIG_SPI_MPC52xx_PSC)         += mpc52xx_psc_spi.o
  obj-$(CONFIG_SPI_MPC83xx)             += spi_mpc83xx.o
  obj-$(CONFIG_SPI_S3C24XX_GPIO)                += spi_s3c24xx_gpio.o
@@@ -34,12 -35,6 +35,12 @@@ obj-$(CONFIG_SPI_SH_SCI)            += spi_sh_sci
  obj-$(CONFIG_SPI_AT25)                += at25.o
  obj-$(CONFIG_SPI_SPIDEV)      += spidev.o
  obj-$(CONFIG_SPI_TLE62X0)     += tle62x0.o
 +obj-$(CONFIG_SPI_TSC2101)     += tsc2101.o
 +obj-$(CONFIG_SPI_TSC2102)     += tsc2102.o
 +obj-$(CONFIG_SPI_TSC210X)     += tsc210x.o
 +obj-$(CONFIG_SPI_TSC2301)     += tsc2301.o
 +tsc2301-objs                  := tsc2301-core.o
 +tsc2301-$(CONFIG_SPI_TSC2301_AUDIO)   += tsc2301-mixer.o
  #     ... add above this line ...
  
  # SPI slave controller drivers (upstream link)
index 7ce8b9edfde180beb3b9f8be315aa04cf5174fd6,c6a8c6b1116a45381d5ee4acb98bbda541d36ae8..222edf1fe3438bd36000c5cb744f11c3139c929e
@@@ -118,10 -118,10 +118,10 @@@ config USB_AMD5536UD
  config USB_GADGET_ATMEL_USBA
        boolean "Atmel USBA"
        select USB_GADGET_DUALSPEED
-       depends on AVR32 || ARCH_AT91CAP9
+       depends on AVR32 || ARCH_AT91CAP9 || ARCH_AT91SAM9RL
        help
          USBA is the integrated high-speed USB Device controller on
-         the AT32AP700x and AT91CAP9 processors from Atmel.
+         the AT32AP700x, some AT91SAM9 and AT91CAP9 processors from Atmel.
  
  config USB_ATMEL_USBA
        tristate
@@@ -172,7 -172,7 +172,7 @@@ config USB_NET228
        default USB_GADGET
        select USB_GADGET_SELECTED
  
- config USB_GADGET_PXA2XX
+ config USB_GADGET_PXA25X
        boolean "PXA 25x or IXP 4xx"
        depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX
        help
           zero (for control transfers).
  
           Say "y" to link the driver statically, or "m" to build a
-          dynamically linked module called "pxa2xx_udc" and force all
+          dynamically linked module called "pxa25x_udc" and force all
           gadget drivers to also be dynamically linked.
  
- config USB_PXA2XX
+ config USB_PXA25X
        tristate
-       depends on USB_GADGET_PXA2XX
+       depends on USB_GADGET_PXA25X
        default USB_GADGET
        select USB_GADGET_SELECTED
  
  # if there's only one gadget driver, using only two bulk endpoints,
  # don't waste memory for the other endpoints
- config USB_PXA2XX_SMALL
-       depends on USB_GADGET_PXA2XX
+ config USB_PXA25X_SMALL
+       depends on USB_GADGET_PXA25X
        bool
        default n if USB_ETH_RNDIS
        default y if USB_ZERO
@@@ -284,20 -284,10 +284,20 @@@ config USB_LH7A40
        default USB_GADGET
        select USB_GADGET_SELECTED
  
 +# built in ../musb along with host support
 +config USB_GADGET_MUSB_HDRC
 +      boolean "Inventra HDRC USB Peripheral (TI, ...)"
 +      depends on USB_MUSB_HDRC && (USB_MUSB_PERIPHERAL || USB_MUSB_OTG)
 +      select USB_GADGET_DUALSPEED
 +      select USB_GADGET_SELECTED
 +      help
 +        This OTG-capable silicon IP is used in dual designs including
 +        the TI DaVinci, OMAP 243x, OMAP 343x, and TUSB 6010.
 +
  config USB_GADGET_OMAP
        boolean "OMAP USB Device Controller"
        depends on ARCH_OMAP
 -      select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3
 +      select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H4_OTG
        help
           Many Texas Instruments OMAP processors have flexible full
           speed USB device controllers, with support for up to 30
@@@ -596,6 -586,20 +596,20 @@@ config USB_G_PRINTE
          For more information, see Documentation/usb/gadget_printer.txt
          which includes sample code for accessing the device file.
  
+ config USB_CDC_COMPOSITE
+       tristate "CDC Composite Device (Ethernet and ACM)"
+       depends on NET
+       help
+         This driver provides two functions in one configuration:
+         a CDC Ethernet (ECM) link, and a CDC ACM (serial port) link.
+         This driver requires four bulk and two interrupt endpoints,
+         plus the ability to handle altsettings.  Not all peripheral
+         controllers are that capable.
+         Say "y" to link the driver statically, or "m" to build a
+         dynamically linked module.
  # put drivers that need isochronous transfer support (for audio
  # or video class gadget drivers), or specific hardware, here.
  
index 3528f49b670b48227715f0c1c3a443b95b788c4b,395bd18444828577a97487ca87f9cd289d8e1095..1995f9cd2611747d50752d7c9491f0878a6ab81f
@@@ -54,7 -54,6 +54,6 @@@
  
  #include <asm/arch/dma.h>
  #include <asm/arch/usb.h>
- #include <asm/arch/control.h>
  
  #include "omap_udc.h"
  
@@@ -1121,7 -1120,7 +1120,7 @@@ static int omap_ep_set_halt(struct usb_
                        status = -EINVAL;
                else if (value) {
                        if (ep->udc->ep0_set_config) {
-                               WARN("error changing config?\n");
+                               WARNING("error changing config?\n");
                                omap_writew(UDC_CLR_CFG, UDC_SYSCON2);
                        }
                        omap_writew(UDC_STALL_CMD, UDC_SYSCON2);
@@@ -1765,7 -1764,7 +1764,7 @@@ do_stall
                                        u.r.bRequestType, u.r.bRequest, status);
                        if (udc->ep0_set_config) {
                                if (udc->ep0_reset_config)
-                                       WARN("error resetting config?\n");
+                                       WARNING("error resetting config?\n");
                                else
                                        omap_writew(UDC_CLR_CFG, UDC_SYSCON2);
                        }
@@@ -2311,17 -2310,10 +2310,17 @@@ static int proc_otg_show(struct seq_fil
        u32             trans;
        char            *ctrl_name;
  
 -      tmp = OTG_REV_REG;
 +      tmp = omap_readw(OTG_REV);
        if (cpu_is_omap24xx()) {
 +              /*
 +               * REVISIT: Not clear how this works on OMAP2.  trans
 +               * is ANDed to produce bits 7 and 8, which might make
 +               * sense for USB_TRANSCEIVER_CTRL on OMAP1,
 +               * but with CONTROL_DEVCONF, these bits have something to
 +               * do with the frame adjustment counter and McBSP2.
 +               */
                ctrl_name = "control_devconf";
 -              trans = CONTROL_DEVCONF_REG;
 +              trans = omap_ctrl_readb(OMAP2_CONTROL_DEVCONF0);
        } else {
                ctrl_name = "tranceiver_ctrl";
                trans = omap_readw(USB_TRANSCEIVER_CTRL);
@@@ -2604,9 -2596,7 +2603,9 @@@ omap_ep_setup(char *name, u8 addr, u8 t
                 * and ignored for PIO-IN on newer chips
                 * (for more reliable behavior)
                 */
 -              if (!use_dma || cpu_is_omap15xx() || cpu_is_omap24xx())
 +              if ((!use_dma && (addr & USB_DIR_IN))
 +                              || machine_is_omap_apollon()
 +                              || cpu_is_omap15xx())
                        dbuf = 0;
  
                switch (maxp) {
@@@ -2696,7 -2686,7 +2695,7 @@@ omap_udc_setup(struct platform_device *
        udc->gadget.name = driver_name;
  
        device_initialize(&udc->gadget.dev);
 -      dev_set_name(&udc->gadget.dev, "gadget");
 +      strcpy (udc->gadget.dev.bus_id, "gadget");
        udc->gadget.dev.release = omap_udc_release;
        udc->gadget.dev.parent = &odev->dev;
        if (use_dma)
@@@ -3086,7 -3076,7 +3085,7 @@@ static int omap_udc_suspend(struct plat
         * which would prevent entry to deep sleep...
         */
        if ((devstat & UDC_ATT) != 0 && (devstat & UDC_SUS) == 0) {
-               WARN("session active; suspend requires disconnect\n");
+               WARNING("session active; suspend requires disconnect\n");
                omap_pullup(&udc->gadget, 0);
        }
  
index af03b626a7219894364f4b61f19b0d9b175a998d,d9d53f289caf48b83001b42321e1bbaf9ca00886..b0a5d104204797c210df8eea4bfd925b8252ac64
@@@ -84,7 -84,7 +84,7 @@@ static const char     hcd_name [] = "ehci_h
  #define EHCI_IAA_MSECS                10              /* arbitrary */
  #define EHCI_IO_JIFFIES               (HZ/10)         /* io watchdog > irq_thresh */
  #define EHCI_ASYNC_JIFFIES    (HZ/20)         /* async idle timeout */
- #define EHCI_SHRINK_JIFFIES   (HZ/200)        /* async qh unlink delay */
+ #define EHCI_SHRINK_FRAMES    5               /* async qh unlink delay */
  
  /* Initial IRQ latency:  faster than hw default */
  static int log2_irq_thresh = 0;               // 0 to 6
@@@ -1009,11 -1009,6 +1009,11 @@@ MODULE_LICENSE ("GPL")
  #define       PLATFORM_DRIVER         ehci_hcd_au1xxx_driver
  #endif
  
 +#ifdef CONFIG_ARCH_OMAP34XX
 +#include "ehci-omap.c"
 +#define       PLATFORM_DRIVER         ehci_hcd_omap_driver
 +#endif
 +
  #ifdef CONFIG_PPC_PS3
  #include "ehci-ps3.c"
  #define       PS3_SYSTEM_BUS_DRIVER   ps3_ehci_driver
index 7604eecb9bae2402da4307455f589bd16b2f6271,6e5e5f81ac905b89ad50fe61317611c3ab3aa3cf..04855ace199df715fcde2a177f13de47f1f8f21b
@@@ -230,7 -230,7 +230,7 @@@ static int ohci_omap_init(struct usb_hc
  
        omap_ohci_clock_power(1);
  
 -      if (cpu_is_omap1510()) {
 +      if (cpu_is_omap15xx()) {
                omap_1510_local_bus_power(1);
                omap_1510_local_bus_init();
        }
@@@ -318,7 -318,7 +318,7 @@@ static int usb_hcd_omap_probe (const st
        if (IS_ERR(usb_host_ck))
                return PTR_ERR(usb_host_ck);
  
 -      if (!cpu_is_omap1510())
 +      if (!cpu_is_omap15xx())
                usb_dc_ck = clk_get(0, "usb_dc_ck");
        else
                usb_dc_ck = clk_get(0, "lb_ck");
        }
  
  
-       hcd = usb_create_hcd (driver, &pdev->dev, pdev->dev.bus_id);
+       hcd = usb_create_hcd (driver, &pdev->dev, dev_name(&pdev->dev));
        if (!hcd) {
                retval = -ENOMEM;
                goto err0;
index 40b9b1ad3b5d1673bf0d1ca8b2bf221c5040f612,452b770d8cc9a51f8c32261eb4247f14e515ab48..6b8cb23e214a5b102a76d189473964ffb8b64659
@@@ -36,6 -36,30 +36,30 @@@ config LCD_LTV350Q
  
          The LTV350QV panel is present on all ATSTK1000 boards.
  
+ config LCD_ILI9320
+       tristate
+       depends on LCD_CLASS_DEVICE && BACKLIGHT_LCD_SUPPORT
+       default n
+       help
+         If you have a panel based on the ILI9320 controller chip
+         then say y to include a power driver for it.
+ config LCD_VGG2432A4
+       tristate "VGG2432A4 LCM device support"
+       depends on BACKLIGHT_LCD_SUPPORT && LCD_CLASS_DEVICE && SPI_MASTER
+       select LCD_ILI9320
+       default n
+       help
+         If you have a VGG2432A4 panel based on the ILI9320 controller chip
+         then say y to include a power driver for it.
+ config LCD_PLATFORM
+       tristate "Platform LCD controls"
+       depends on LCD_CLASS_DEVICE
+       help
+         This driver provides a platform-device registered LCD power
+         control interface.
  #
  # Backlight
  #
@@@ -63,6 -87,18 +87,18 @@@ config BACKLIGHT_ATMEL_LCD
          If in doubt, it's safe to enable this option; it doesn't kick
          in unless the board's description says it's wired that way.
  
+ config BACKLIGHT_ATMEL_PWM
+       tristate "Atmel PWM backlight control"
+       depends on BACKLIGHT_CLASS_DEVICE && ATMEL_PWM
+       default n
+       help
+         Say Y here if you want to use the PWM peripheral in Atmel AT91 and
+         AVR32 devices. This driver will need additional platform data to know
+         which PWM instance to use and how to configure it.
+         To compile this driver as a module, choose M here: the module will be
+         called atmel-pwm-bl.
  config BACKLIGHT_CORGI
        tristate "Generic (aka Sharp Corgi) Backlight Driver"
        depends on BACKLIGHT_CLASS_DEVICE
@@@ -97,15 -133,6 +133,15 @@@ config BACKLIGHT_HP68
          If you have a HP Jornada 680, say y to enable the
          backlight driver.
  
 +config BACKLIGHT_OMAP
 +      tristate "OMAP LCD Backlight"
 +      depends on BACKLIGHT_CLASS_DEVICE && (ARCH_OMAP1 || ARCH_OMAP2)
 +      default y
 +      help
 +        This driver controls the LCD backlight level and power
 +        for the PWL module of OMAP processors.  Say Y if you plan
 +        to use power saving.
 +
  config BACKLIGHT_PROGEAR
        tristate "Frontpath ProGear Backlight Driver"
        depends on BACKLIGHT_CLASS_DEVICE && PCI && X86
@@@ -121,3 -148,19 +157,19 @@@ config BACKLIGHT_CARILLO_RANC
        help
          If you have a Intel LE80578 (Carillo Ranch) say Y to enable the
          backlight driver.
+ config BACKLIGHT_PWM
+       tristate "Generic PWM based Backlight Driver"
+       depends on BACKLIGHT_CLASS_DEVICE && HAVE_PWM
+       help
+         If you have a LCD backlight adjustable by PWM, say Y to enable
+         this driver.
+ config BACKLIGHT_MBP_NVIDIA
+        tristate "MacBook Pro Nvidia Backlight Driver"
+        depends on BACKLIGHT_CLASS_DEVICE && X86
+        default n
+        help
+          If you have an Apple Macbook Pro with Nvidia graphics hardware say Y
+        to enable a driver for its backlight
index 6aff476e72247c9b08b2705ef1a987123a227018,ab77c51fe9d620bc4f41f0816fb4999d7e1bddaf..c63ee08a0ca5534fc8d6928a342223c7ff402c54
@@@ -20,6 -20,7 +20,7 @@@
   */
  #include <linux/kernel.h>
  #include <linux/dma-mapping.h>
+ #include <linux/mm.h>
  #include <linux/vmalloc.h>
  #include <linux/clk.h>
  #include <linux/io.h>
@@@ -879,24 -880,20 +880,24 @@@ static irqreturn_t omap_dispc_irq_handl
  
  static int get_dss_clocks(void)
  {
 -      if (IS_ERR((dispc.dss_ick = clk_get(dispc.fbdev->dev, "dss_ick")))) {
 -              dev_err(dispc.fbdev->dev, "can't get dss_ick\n");
 +      char *dss_ick = "dss_ick";
 +      char *dss1_fck = cpu_is_omap34xx() ? "dss1_alwon_fck" : "dss1_fck";
 +      char *tv_fck = cpu_is_omap34xx() ? "dss_tv_fck" : "dss_54m_fck";
 +
 +      if (IS_ERR((dispc.dss_ick = clk_get(dispc.fbdev->dev, dss_ick)))) {
 +              dev_err(dispc.fbdev->dev, "can't get %s", dss_ick);
                return PTR_ERR(dispc.dss_ick);
        }
  
 -      if (IS_ERR((dispc.dss1_fck = clk_get(dispc.fbdev->dev, "dss1_fck")))) {
 -              dev_err(dispc.fbdev->dev, "can't get dss1_fck\n");
 +      if (IS_ERR((dispc.dss1_fck = clk_get(dispc.fbdev->dev, dss1_fck)))) {
 +              dev_err(dispc.fbdev->dev, "can't get %s", dss1_fck);
                clk_put(dispc.dss_ick);
                return PTR_ERR(dispc.dss1_fck);
        }
  
        if (IS_ERR((dispc.dss_54m_fck =
 -                              clk_get(dispc.fbdev->dev, "dss_54m_fck")))) {
 -              dev_err(dispc.fbdev->dev, "can't get dss_54m_fck\n");
 +                              clk_get(dispc.fbdev->dev, tv_fck)))) {
 +              dev_err(dispc.fbdev->dev, "can't get %s", tv_fck);
                clk_put(dispc.dss_ick);
                clk_put(dispc.dss1_fck);
                return PTR_ERR(dispc.dss_54m_fck);
@@@ -1393,7 -1390,7 +1394,7 @@@ static int omap_dispc_init(struct omapf
        }
  
        /* Enable smart idle and autoidle */
 -      l = dispc_read_reg(DISPC_CONTROL);
 +      l = dispc_read_reg(DISPC_SYSCONFIG);
        l &= ~((3 << 12) | (3 << 3));
        l |= (2 << 12) | (2 << 3) | (1 << 0);
        dispc_write_reg(DISPC_SYSCONFIG, l);
        dispc_write_reg(DISPC_CONFIG, l);
  
        l = dispc_read_reg(DISPC_IRQSTATUS);
 -      dispc_write_reg(l, DISPC_IRQSTATUS);
 +      dispc_write_reg(DISPC_IRQSTATUS, l);
  
        /* Enable those that we handle always */
        omap_dispc_enable_irqs(DISPC_IRQ_FRAMEMASK);
index 418ed9fadd3a8c32356f7ddacd2a1e788d7fc1b3,f85af5c4fa688a2c6d9be356fa6bd974c89a74f7..032528eb830b7930b00bffbfd545a88a0ecf3482
@@@ -25,6 -25,7 +25,7 @@@
   * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   */
  #include <linux/platform_device.h>
+ #include <linux/mm.h>
  #include <linux/uaccess.h>
  
  #include <asm/mach-types.h>
@@@ -64,7 -65,6 +65,7 @@@ static struct caps_table_struct ctrl_ca
        { OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE, "pixel double window" },
        { OMAPFB_CAPS_WINDOW_SCALE,   "scale window" },
        { OMAPFB_CAPS_WINDOW_OVERLAY, "overlay window" },
 +      { OMAPFB_CAPS_WINDOW_ROTATE,  "rotate window" },
        { OMAPFB_CAPS_SET_BACKLIGHT,  "backlight setting" },
  };
  
@@@ -215,13 -215,6 +216,13 @@@ static int ctrl_change_mode(struct fb_i
                                 offset, var->xres_virtual,
                                 plane->info.pos_x, plane->info.pos_y,
                                 var->xres, var->yres, plane->color_mode);
 +      if (r < 0)
 +              return r;
 +
 +      if (fbdev->ctrl->set_rotate != NULL)
 +              if((r = fbdev->ctrl->set_rotate(var->rotate)) < 0)
 +                      return r;
 +
        if (fbdev->ctrl->set_scale != NULL)
                r = fbdev->ctrl->set_scale(plane->idx,
                                   var->xres, var->yres,
@@@ -559,6 -552,7 +560,6 @@@ static int set_fb_var(struct fb_info *f
                var->xoffset = var->xres_virtual - var->xres;
        if (var->yres + var->yoffset > var->yres_virtual)
                var->yoffset = var->yres_virtual - var->yres;
 -      line_size = var->xres * bpp / 8;
  
        if (plane->color_mode == OMAPFB_COLOR_RGB444) {
                var->red.offset   = 8; var->red.length   = 4;
@@@ -604,7 -598,7 +605,7 @@@ static void omapfb_rotate(struct fb_inf
        struct omapfb_device *fbdev = plane->fbdev;
  
        omapfb_rqueue_lock(fbdev);
 -      if (cpu_is_omap15xx() && rotate != fbi->var.rotate) {
 +      if (rotate != fbi->var.rotate) {
                struct fb_var_screeninfo *new_var = &fbdev->new_var;
  
                memcpy(new_var, &fbi->var, sizeof(*new_var));
@@@ -711,42 -705,28 +712,42 @@@ int omapfb_update_window_async(struct f
                                void (*callback)(void *),
                                void *callback_data)
  {
 +      int xres, yres;
        struct omapfb_plane_struct *plane = fbi->par;
        struct omapfb_device *fbdev = plane->fbdev;
 -      struct fb_var_screeninfo *var;
 +      struct fb_var_screeninfo *var = &fbi->var;
  
 -      var = &fbi->var;
 -      if (win->x >= var->xres || win->y >= var->yres ||
 -          win->out_x > var->xres || win->out_y >= var->yres)
 +      switch (var->rotate) {
 +      case 0:
 +      case 180:
 +              xres = fbdev->panel->x_res;
 +              yres = fbdev->panel->y_res;
 +              break;
 +      case 90:
 +      case 270:
 +              xres = fbdev->panel->y_res;
 +              yres = fbdev->panel->x_res;
 +              break;
 +      default:
 +              return -EINVAL;
 +      }
 +
 +      if (win->x >= xres || win->y >= yres ||
 +          win->out_x > xres || win->out_y > yres)
                return -EINVAL;
  
        if (!fbdev->ctrl->update_window ||
            fbdev->ctrl->get_update_mode() != OMAPFB_MANUAL_UPDATE)
                return -ENODEV;
  
 -      if (win->x + win->width >= var->xres)
 -              win->width = var->xres - win->x;
 -      if (win->y + win->height >= var->yres)
 -              win->height = var->yres - win->y;
 -      /* The out sizes should be cropped to the LCD size */
 -      if (win->out_x + win->out_width > fbdev->panel->x_res)
 -              win->out_width = fbdev->panel->x_res - win->out_x;
 -      if (win->out_y + win->out_height > fbdev->panel->y_res)
 -              win->out_height = fbdev->panel->y_res - win->out_y;
 +      if (win->x + win->width > xres)
 +              win->width = xres - win->x;
 +      if (win->y + win->height > yres)
 +              win->height = yres - win->y;
 +      if (win->out_x + win->out_width > xres)
 +              win->out_width = xres - win->out_x;
 +      if (win->out_y + win->out_height > yres)
 +              win->out_height = yres - win->out_y;
        if (!win->width || !win->height || !win->out_width || !win->out_height)
                return 0;
  
@@@ -1838,8 -1818,8 +1839,8 @@@ static int omapfb_suspend(struct platfo
  {
        struct omapfb_device *fbdev = platform_get_drvdata(pdev);
  
 -      omapfb_blank(VESA_POWERDOWN, fbdev->fb_info[0]);
 -
 +      if (fbdev != NULL)
 +              omapfb_blank(VESA_POWERDOWN, fbdev->fb_info[0]);
        return 0;
  }
  
@@@ -1848,8 -1828,7 +1849,8 @@@ static int omapfb_resume(struct platfor
  {
        struct omapfb_device *fbdev = platform_get_drvdata(pdev);
  
 -      omapfb_blank(VESA_NO_BLANKING, fbdev->fb_info[0]);
 +      if (fbdev != NULL)
 +              omapfb_blank(VESA_NO_BLANKING, fbdev->fb_info[0]);
        return 0;
  }
  
index 658b5da12acd5dcc1456110060ec29c5838caa76,fafd0f26b90f78028afff02d220673a588f6252b..4e1ba45642996cce3ec8adc79dcb2ef80de9ac42
@@@ -2,7 -2,7 +2,7 @@@
   * OMAP1 Special OptimiSed Screen Interface support
   *
   * Copyright (C) 2004-2005 Nokia Corporation
 - * Author: Juha Yrjölä <juha.yrjola@nokia.com>
 + * Author: Juha Yrj�l� <juha.yrjola@nokia.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
@@@ -646,7 -646,7 +646,7 @@@ static int sossi_init(struct omapfb_dev
        sossi_write_reg(SOSSI_INIT1_REG, l);
  
        if ((r = request_irq(INT_1610_SoSSI_MATCH, sossi_match_irq,
-                            IRQT_FALLING,
+                            IRQ_TYPE_EDGE_FALLING,
             "sossi_match", sossi.fbdev->dev)) < 0) {
                dev_err(sossi.fbdev->dev, "can't get SoSSI match IRQ\n");
                goto err;
diff --combined drivers/watchdog/Kconfig
index fb9abfe4164e9c8fc5f1306f64ed99f1e1d64ee1,48399e134c0de37d31cfcd05fc16213b7bc7dc0e..f363341bc15e6c604e78f4aebf61d7c285ce1cdb
@@@ -173,10 -173,10 +173,10 @@@ config EP93XX_WATCHDO
  
  config OMAP_WATCHDOG
        tristate "OMAP Watchdog"
 -      depends on ARCH_OMAP16XX || ARCH_OMAP24XX
 +      depends on ARCH_OMAP16XX || ARCH_OMAP24XX || ARCH_OMAP34XX
        help
 -        Support for TI OMAP1610/OMAP1710/OMAP2420 watchdog.  Say 'Y' here to
 -        enable the OMAP1610/OMAP1710 watchdog timer.
 +        Support for TI OMAP1610/OMAP1710/OMAP2420/OMAP3430 watchdog.  Say 'Y'
 +        here to enable the OMAP1610/OMAP1710/OMAP2420/OMAP3430 watchdog timer.
  
  config PNX4008_WATCHDOG
        tristate "PNX4008 Watchdog"
@@@ -788,8 -788,6 +788,6 @@@ config WATCHDOG_RI
          machines.  The watchdog timeout period is normally one minute but
          can be changed with a boot-time parameter.
  
- # V850 Architecture
  # XTENSA Architecture
  
  #
index fd722f3cb6bd362320b12f191e2e81a19380a602,5c7f9468f753b51fb05a0417930cffb2e709f59f..4c3cb6d77de8dc6e201fc9194bdefad9bba1aec4
  #define CN_VAL_CIFS                     0x1
  #define CN_W1_IDX                     0x3     /* w1 communication */
  #define CN_W1_VAL                     0x1
 +#define CN_IDX_SX1SND                 0x4
 +#define CN_VAL_SX1SND                 0x1
  #define CN_IDX_V86D                   0x4
  #define CN_VAL_V86D_UVESAFB           0x1
+ #define CN_IDX_BB                     0x5     /* BlackBoard, from the TSP GPL sampling framework */
  
- #define CN_NETLINK_USERS              5
+ #define CN_NETLINK_USERS              6
  
  /*
   * Maximum connector's message size.
diff --combined kernel/printk.c
index 9563a7a16664c55036c4db76514cf1b683fa23f2,b51b1567bb5570dfc5b4a19bffd5af865d254e77..8b223afafe63bebc6ca1bde9ba23e89b436db97a
  /*
   * Architectures can override it:
   */
- void __attribute__((weak)) early_printk(const char *fmt, ...)
+ void asmlinkage __attribute__((weak)) early_printk(const char *fmt, ...)
  {
  }
  
  #define __LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT)
  
 +#ifdef CONFIG_DEBUG_LL
 +extern void printascii(char *);
 +#endif
 +
  /* printk's without a loglevel use this.. */
  #define DEFAULT_MESSAGE_LOGLEVEL 4 /* KERN_WARNING */
  
@@@ -79,6 -75,8 +79,8 @@@ EXPORT_SYMBOL(oops_in_progress)
  static DECLARE_MUTEX(console_sem);
  static DECLARE_MUTEX(secondary_console_sem);
  struct console *console_drivers;
+ EXPORT_SYMBOL_GPL(console_drivers);
  /*
   * This is used for debugging the mess that is the VT code by
   * keeping track if we have the console semaphore held. It's
@@@ -125,6 -123,8 +127,8 @@@ struct console_cmdlin
  static struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES];
  static int selected_console = -1;
  static int preferred_console = -1;
+ int console_set_on_cmdline;
+ EXPORT_SYMBOL(console_set_on_cmdline);
  
  /* Flag: console code may call schedule() */
  static int console_may_schedule;
@@@ -235,7 -235,7 +239,7 @@@ static inline void boot_delay_msec(void
  /*
   * Return the number of unread characters in the log buffer.
   */
- int log_buf_get_len(void)
static int log_buf_get_len(void)
  {
        return logged_chars;
  }
@@@ -271,19 -271,6 +275,6 @@@ int log_buf_copy(char *dest, int idx, i
        return ret;
  }
  
- /*
-  * Extract a single character from the log buffer.
-  */
- int log_buf_read(int idx)
- {
-       char ret;
-       if (log_buf_copy(&ret, idx, 1) == 1)
-               return ret;
-       else
-               return -1;
- }
  /*
   * Commands to do_syslog:
   *
@@@ -669,18 -656,17 +660,17 @@@ static int acquire_console_semaphore_fo
        spin_unlock(&logbuf_lock);
        return retval;
  }
- static const char printk_recursion_bug_msg [] =
-                       KERN_CRIT "BUG: recent printk recursion!\n";
- static int printk_recursion_bug;
+ static const char recursion_bug_msg [] =
+               KERN_CRIT "BUG: recent printk recursion!\n";
+ static int recursion_bug;
+       static int new_text_line = 1;
+ static char printk_buf[1024];
  
  asmlinkage int vprintk(const char *fmt, va_list args)
  {
-       static int log_level_unknown = 1;
-       static char printk_buf[1024];
-       unsigned long flags;
        int printed_len = 0;
+       int current_log_level = default_message_loglevel;
+       unsigned long flags;
        int this_cpu;
        char *p;
  
                 * it can be printed at the next appropriate moment:
                 */
                if (!oops_in_progress) {
-                       printk_recursion_bug = 1;
+                       recursion_bug = 1;
                        goto out_restore_irqs;
                }
                zap_locks();
        spin_lock(&logbuf_lock);
        printk_cpu = this_cpu;
  
-       if (printk_recursion_bug) {
-               printk_recursion_bug = 0;
-               strcpy(printk_buf, printk_recursion_bug_msg);
-               printed_len = sizeof(printk_recursion_bug_msg);
+       if (recursion_bug) {
+               recursion_bug = 0;
+               strcpy(printk_buf, recursion_bug_msg);
+               printed_len = sizeof(recursion_bug_msg);
        }
        /* Emit the output into the temporary buffer */
        printed_len += vscnprintf(printk_buf + printed_len,
                                  sizeof(printk_buf) - printed_len, fmt, args);
  
 +#ifdef        CONFIG_DEBUG_LL
 +      printascii(printk_buf);
 +#endif
  
        /*
         * Copy the output into log_buf.  If the caller didn't provide
         * appropriate log level tags, we insert them here
         */
        for (p = printk_buf; *p; p++) {
-               if (log_level_unknown) {
-                         /* log_level_unknown signals the start of a new line */
+               if (new_text_line) {
+                       /* If a token, set current_log_level and skip over */
+                       if (p[0] == '<' && p[1] >= '0' && p[1] <= '7' &&
+                           p[2] == '>') {
+                               current_log_level = p[1] - '0';
+                               p += 3;
+                               printed_len -= 3;
+                       }
+                       /* Always output the token */
+                       emit_log_char('<');
+                       emit_log_char(current_log_level + '0');
+                       emit_log_char('>');
+                       printed_len += 3;
+                       new_text_line = 0;
                        if (printk_time) {
-                               int loglev_char;
+                               /* Follow the token with the time */
                                char tbuf[50], *tp;
                                unsigned tlen;
                                unsigned long long t;
                                unsigned long nanosec_rem;
  
-                               /*
-                                * force the log level token to be
-                                * before the time output.
-                                */
-                               if (p[0] == '<' && p[1] >='0' &&
-                                  p[1] <= '7' && p[2] == '>') {
-                                       loglev_char = p[1];
-                                       p += 3;
-                                       printed_len -= 3;
-                               } else {
-                                       loglev_char = default_message_loglevel
-                                               + '0';
-                               }
                                t = cpu_clock(printk_cpu);
                                nanosec_rem = do_div(t, 1000000000);
-                               tlen = sprintf(tbuf,
-                                               "<%c>[%5lu.%06lu] ",
-                                               loglev_char,
-                                               (unsigned long)t,
-                                               nanosec_rem/1000);
+                               tlen = sprintf(tbuf, "[%5lu.%06lu] ",
+                                               (unsigned long) t,
+                                               nanosec_rem / 1000);
  
                                for (tp = tbuf; tp < tbuf + tlen; tp++)
                                        emit_log_char(*tp);
                                printed_len += tlen;
-                       } else {
-                               if (p[0] != '<' || p[1] < '0' ||
-                                  p[1] > '7' || p[2] != '>') {
-                                       emit_log_char('<');
-                                       emit_log_char(default_message_loglevel
-                                               + '0');
-                                       emit_log_char('>');
-                                       printed_len += 3;
-                               }
                        }
-                       log_level_unknown = 0;
                        if (!*p)
                                break;
                }
                emit_log_char(*p);
                if (*p == '\n')
-                       log_level_unknown = 1;
+                       new_text_line = 1;
        }
  
        /*
@@@ -898,6 -872,7 +879,7 @@@ static int __init console_setup(char *s
        *s = 0;
  
        __add_preferred_console(buf, idx, options, brl_options);
+       console_set_on_cmdline = 1;
        return 1;
  }
  __setup("console=", console_setup);
@@@ -958,7 -933,7 +940,7 @@@ void suspend_console(void
  {
        if (!console_suspend_enabled)
                return;
-       printk("Suspending console(s)\n");
+       printk("Suspending console(s) (use no_console_suspend to debug)\n");
        acquire_console_sem();
        console_suspended = 1;
  }
@@@ -1049,7 -1024,9 +1031,9 @@@ void release_console_sem(void
                _log_end = log_end;
                con_start = log_end;            /* Flush */
                spin_unlock(&logbuf_lock);
+               stop_critical_timings();        /* don't trace print latency */
                call_console_drivers(_con_start, _log_end);
+               start_critical_timings();
                local_irq_restore(flags);
        }
        console_locked = 0;
@@@ -1180,8 -1157,11 +1164,11 @@@ void register_console(struct console *c
                        console->index = 0;
                if (console->setup == NULL ||
                    console->setup(console, NULL) == 0) {
-                       console->flags |= CON_ENABLED | CON_CONSDEV;
-                       preferred_console = 0;
+                       console->flags |= CON_ENABLED;
+                       if (console->device) {
+                               console->flags |= CON_CONSDEV;
+                               preferred_console = 0;
+                       }
                }
        }
  
@@@ -1328,29 -1308,18 +1315,18 @@@ void tty_write_message(struct tty_struc
  }
  
  #if defined CONFIG_PRINTK
  /*
   * printk rate limiting, lifted from the networking subsystem.
   *
-  * This enforces a rate limit: not more than one kernel message
-  * every printk_ratelimit_jiffies to make a denial-of-service
-  * attack impossible.
+  * This enforces a rate limit: not more than 10 kernel messages
+  * every 5s to make a denial-of-service attack impossible.
   */
- int __printk_ratelimit(int ratelimit_jiffies, int ratelimit_burst)
- {
-       return __ratelimit(ratelimit_jiffies, ratelimit_burst);
- }
- EXPORT_SYMBOL(__printk_ratelimit);
- /* minimum time in jiffies between messages */
- int printk_ratelimit_jiffies = 5 * HZ;
- /* number of messages we send before ratelimiting */
- int printk_ratelimit_burst = 10;
+ DEFINE_RATELIMIT_STATE(printk_ratelimit_state, 5 * HZ, 10);
  
  int printk_ratelimit(void)
  {
-       return __printk_ratelimit(printk_ratelimit_jiffies,
-                               printk_ratelimit_burst);
+       return __ratelimit(&printk_ratelimit_state);
  }
  EXPORT_SYMBOL(printk_ratelimit);
  
index 05952173b5723bc13595e2a3653540d6361da0ba,90eb7cb47e7723fb57e035e447e3ff182dd46d77..37e44705ff9dca3125db27e942133931c253ca9e
@@@ -213,22 -213,8 +213,21 @@@ config IP_NF_TARGET_NETMA
        help
          NETMAP is an implementation of static 1:1 NAT mapping of network
          addresses. It maps the network address part, while keeping the host
-         address part intact. It is similar to Fast NAT, except that
-         Netfilter's connection tracking doesn't work well with Fast NAT.
+         address part intact.
  
 +        To compile it as a module, choose M here.  If unsure, say N.
 +
 +config IP_NF_TARGET_IDLETIMER
 +      tristate  "IDLETIMER target support"
 +      depends on IP_NF_IPTABLES
 +      help
 +        This option adds a `IDLETIMER' target. Each matching packet resets
 +        the timer associated with input and/or output interfaces. Timer
 +        expiry causes kobject uevent. Idle timer can be read via sysfs.
 +
 +        To compile it as a module, choose M here.  If unsure, say N.
 +
 +
          To compile it as a module, choose M here.  If unsure, say N.
  
  config NF_NAT_SNMP_BASIC
@@@ -377,6 -363,18 +376,18 @@@ config IP_NF_RA
        
          If you want to compile it as a module, say M here and read
          <file:Documentation/kbuild/modules.txt>.  If unsure, say `N'.
+ # security table for MAC policy
+ config IP_NF_SECURITY
+       tristate "Security table"
+       depends on IP_NF_IPTABLES
+       depends on SECURITY
+       depends on NETFILTER_ADVANCED
+       help
+         This option adds a `security' table to iptables, for use
+         with Mandatory Access Control (MAC) policy.
+        
+         If unsure, say N.
  
  # ARP tables
  config IP_NF_ARPTABLES
index c9cf744d5e86831ea43ee918397c1a912e005237,3f31291f37ce7c6c68513eb269ccb87de09b3dac..927ddabaffb2849e0330dfd553421446b37a7bb8
@@@ -42,6 -42,7 +42,7 @@@ obj-$(CONFIG_IP_NF_FILTER) += iptable_f
  obj-$(CONFIG_IP_NF_MANGLE) += iptable_mangle.o
  obj-$(CONFIG_NF_NAT) += iptable_nat.o
  obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
+ obj-$(CONFIG_IP_NF_SECURITY) += iptable_security.o
  
  # matches
  obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
@@@ -58,7 -59,6 +59,7 @@@ obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) +
  obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
  obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
  obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
 +obj-$(CONFIG_IP_NF_TARGET_IDLETIMER) += ipt_IDLETIMER.o
  obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
  obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
  
diff --combined security/Kconfig
index fb3425231927e6fdec4031a8162ae9e409f5d8b3,559293922a479eabf188b70e963d5264f9032799..811f00270546ce972a10701543edd11024deae59
@@@ -73,17 -73,8 +73,8 @@@ config SECURITY_NETWORK_XFR
          IPSec.
          If you are unsure how to answer this question, answer N.
  
- config SECURITY_CAPABILITIES
-       bool "Default Linux Capabilities"
-       depends on SECURITY
-       default y
-       help
-         This enables the "default" Linux capabilities functionality.
-         If you are unsure how to answer this question, answer Y.
  config SECURITY_FILE_CAPABILITIES
-       bool "File POSIX Capabilities (EXPERIMENTAL)"
-       depends on (SECURITY=n || SECURITY_CAPABILITIES!=n) && EXPERIMENTAL
+       bool "File POSIX Capabilities"
        default n
        help
          This enables filesystem capabilities, allowing you to give
@@@ -104,14 -95,6 +95,14 @@@ config SECURITY_ROOTPLU
          
          If you are unsure how to answer this question, answer N.
  
 +config SECURITY_LOWMEM
 +      tristate "Low memory watermark support"
 +      depends on SECURITY
 +      help
 +        Implements low memory watermark support
 +
 +        If you are unsure how to answer this question, answer N.
 +
  config SECURITY_DEFAULT_MMAP_MIN_ADDR
          int "Low address space to protect from user allocation"
          depends on SECURITY
diff --combined security/Makefile
index 7111cf1e0d6cd15d587745499a2d2766ee66893d,f65426099aa625be9aac60a1a009ea860956dbb7..22f845620580dfc7c2a5f3076c8305592f0ffbbe
@@@ -6,17 -6,13 +6,14 @@@ obj-$(CONFIG_KEYS)                    += keys
  subdir-$(CONFIG_SECURITY_SELINUX)     += selinux
  subdir-$(CONFIG_SECURITY_SMACK)               += smack
  
- # if we don't select a security model, use the default capabilities
- ifneq ($(CONFIG_SECURITY),y)
+ # always enable default capabilities
  obj-y         += commoncap.o
- endif
  
  # Object file lists
- obj-$(CONFIG_SECURITY)                        += security.o dummy.o inode.o
+ obj-$(CONFIG_SECURITY)                        += security.o capability.o inode.o
  # Must precede capability.o in order to stack properly.
  obj-$(CONFIG_SECURITY_SELINUX)                += selinux/built-in.o
- obj-$(CONFIG_SECURITY_SMACK)          += commoncap.o smack/built-in.o
- obj-$(CONFIG_SECURITY_CAPABILITIES)   += commoncap.o capability.o
- obj-$(CONFIG_SECURITY_ROOTPLUG)               += commoncap.o root_plug.o
+ obj-$(CONFIG_SECURITY_SMACK)          += smack/built-in.o
+ obj-$(CONFIG_SECURITY_ROOTPLUG)               += root_plug.o
 +obj-$(CONFIG_SECURITY_LOWMEM)         += commoncap.o lowmem.o
  obj-$(CONFIG_CGROUP_DEVICE)           += device_cgroup.o
diff --combined sound/arm/Kconfig
index c685a9cd9aec4e44bc86a9165ab7756d9a29b981,351e19ea3785ce7159fe6957abc97a1b1c963971..06a24df059f8d1e166bb92a81d165c7ae6a002a3
@@@ -1,11 -1,19 +1,19 @@@
  # ALSA ARM drivers
  
- menu "ALSA ARM devices"
-       depends on SND!=n && ARM
+ menuconfig SND_ARM
+       bool "ARM sound devices"
+       depends on ARM
+       default y
+       help
+         Support for sound devices specific to ARM architectures.
+         Drivers that are implemented on ASoC can be found in
+         "ALSA for SoC audio support" section.
+ if SND_ARM
  
  config SND_SA11XX_UDA1341
        tristate "SA11xx UDA1341TS driver (iPaq H3600)"
-       depends on ARCH_SA1100 && SND && L3
+       depends on ARCH_SA1100 && L3
        select SND_PCM
        help
          Say Y here if you have a Compaq iPaq H3x00 handheld computer
@@@ -16,7 -24,7 +24,7 @@@
  
  config SND_ARMAACI
        tristate "ARM PrimeCell PL041 AC Link support"
-       depends on SND && ARM_AMBA
+       depends on ARM_AMBA
        select SND_PCM
        select SND_AC97_CODEC
  
@@@ -26,75 -34,12 +34,75 @@@ config SND_PXA2XX_PC
  
  config SND_PXA2XX_AC97
        tristate "AC97 driver for the Intel PXA2xx chip"
-       depends on ARCH_PXA && SND
+       depends on ARCH_PXA
        select SND_PXA2XX_PCM
        select SND_AC97_CODEC
        help
          Say Y or M if you want to support any AC97 codec attached to
          the PXA2xx AC97 interface.
  
 -endif # SND_ARM
 +config SND_OMAP_AIC23
 +      tristate "OMAP AIC23 alsa driver (osk5912)"
 +      depends on ARCH_OMAP && SND
 +      select SND_PCM
 +      select I2C
 +      select I2C_OMAP if ARCH_OMAP
 +      select SENSORS_TLV320AIC23
 +      help
 +        Say Y here if you have a OSK platform board
 +        and want to use its AIC23 audio chip.
 +
 +        To compile this driver as a module, choose M here: the module
 +        will be called snd-omap-aic23.
 +        
 +config SND_OMAP_TSC2101
 +      tristate "OMAP TSC2101 alsa driver"
 +      depends on ARCH_OMAP && SND
 +      select SND_PCM
 +         select SPI_TSC2101
 +      help
 +        Say Y here if you have a OMAP platform board
 +        and want to use its TSC2101 audio chip. Driver has
 +        been tested with H2 and iPAQ h6300.
 + 
 +        To compile this driver as a module, choose M here: the module
 +        will be called snd-omap-tsc2101.
 +
 +config SND_SX1
 +      tristate "Siemens SX1 Egold alsa driver"
 +      depends on ARCH_OMAP && SND
 +      select SND_PCM
 +      help
 +        Say Y here if you have a OMAP310 based Siemens SX1.
 +
 +        To compile this driver as a module, choose M here: the module
 +        will be called snd-omap-sx1.
 +
 +config SND_OMAP_TSC2102
 +      tristate "OMAP TSC2102 alsa driver"
 +      depends on ARCH_OMAP && SND
 +      select SND_PCM
 +      select SPI_TSC2102
 +      help
 +        Say Y here if you have an OMAP platform board
 +        and want to use its TSC2102 audio chip.
  
- endmenu
 +        To compile this driver as a module, choose M here: the module
 +        will be called snd-omap-tsc2102.
 +
 +config SND_OMAP24XX_EAC
 +      tristate "Audio driver for OMAP24xx EAC"
 +      depends on SND
 +      help
 +        Audio driver for Enhanced Audio Controller found in TI's OMAP24xx
 +        processors.
 +
 +        Currently contains only low-level support functions for
 +        initializing EAC HW, creating ALSA sound card instance for it
 +        and registering mixer controls implemented by a codec driver.
 +        PCM stream is expected to be under DSP co-processor control.
 +
 +        To compile this driver as a module, choose M here: the module
 +        will be called snd-omap24xx-eac.
 +
++endif # SND_ARM
diff --combined sound/oss/Makefile
index 0dbb89e83c7e039c896e7e83641b3c8b061b67f3,c611514f7ff104ec3289d960d9108d5391fc91c9..45b56473b4fbef30fca3e1296f9fba1ee914e13c
@@@ -7,10 -7,6 +7,10 @@@
  
  obj-$(CONFIG_SOUND_OSS)               += sound.o
  
 +obj-$(CONFIG_SOUND_OMAP)        += omap-audio-dma-intfc.o omap-audio.o
 +obj-$(CONFIG_SOUND_OMAP_TSC2101)+= omap-audio-tsc2101.o
 +obj-$(CONFIG_SOUND_OMAP_AIC23)  += omap-audio-aic23.o
 +
  # Please leave it as is, cause the link order is significant !
  
  obj-$(CONFIG_SOUND_SH_DAC_AUDIO)      += sh_dac_audio.o
@@@ -33,11 -29,8 +33,8 @@@ obj-$(CONFIG_SOUND_MSNDCLAS) += msnd.o 
  obj-$(CONFIG_SOUND_MSNDPIN)   += msnd.o msnd_pinnacle.o
  obj-$(CONFIG_SOUND_VWSND)     += vwsnd.o
  obj-$(CONFIG_SOUND_AU1550_AC97)       += au1550_ac97.o ac97_codec.o
- obj-$(CONFIG_SOUND_TRIDENT)   += trident.o ac97_codec.o
  obj-$(CONFIG_SOUND_BCM_CS4297A)       += swarm_cs4297a.o
  
- obj-$(CONFIG_SOUND_WM97XX)    += ac97_plugin_wm97xx.o
  obj-$(CONFIG_DMASOUND)                += dmasound/
  
  # Declare multi-part drivers.