M: Latchesar Ionkov <lucho@ionkov.net>
L: v9fs-developer@lists.sourceforge.net
W: http://swik.net/v9fs
-T: git git://git.kernel.org/pub/scm/linux/kernel/ericvh/v9fs.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs.git
S: Maintained
F: Documentation/filesystems/9p.txt
F: fs/9p/
S: Maintained
F: drivers/macintosh/therm_adt746x.c
+ADT7475 HARDWARE MONITOR DRIVER
+M: Jean Delvare <khali@linux-fr.org>
+L: lm-sensors@lm-sensors.org
+S: Maintained
+F: Documentation/hwmon/adt7475
+F: drivers/hwmon/adt7475.c
+
ADVANSYS SCSI DRIVER
M: Matthew Wilcox <matthew@wil.cx>
L: linux-scsi@vger.kernel.org
F: drivers/net/appletalk/
F: net/appletalk/
-APPLETOUCH TOUCHPAD DRIVER
-M: Johannes Berg <johannes@sipsolutions.net>
-L: linux-input@vger.kernel.org
-S: Maintained
-F: Documentation/input/appletouch.txt
-F: drivers/input/mouse/appletouch.c
-
ARC FRAMEBUFFER DRIVER
M: Jaya Kumar <jayalk@intworks.biz>
S: Maintained
S: Maintained
F: arch/arm/
+ARM PRIMECELL AACI PL041 DRIVER
+M: Russell King <linux@arm.linux.org.uk>
+S: Maintained
+F: sound/arm/aaci.*
+
+ARM PRIMECELL CLCD PL110 DRIVER
+M: Russell King <linux@arm.linux.org.uk>
+S: Maintained
+F: drivers/video/amba-clcd.*
+
+ARM PRIMECELL KMI PL050 DRIVER
+M: Russell King <linux@arm.linux.org.uk>
+S: Maintained
+F: drivers/input/serio/ambakmi.*
+F: include/linux/amba/kmi.h
+
ARM PRIMECELL MMCI PL180/1 DRIVER
S: Orphan
F: drivers/mmc/host/mmci.*
+ARM PRIMECELL BUS SUPPORT
+M: Russell King <linux@arm.linux.org.uk>
+S: Maintained
+F: drivers/amba/
+F: include/linux/amba/bus.h
+
ARM/ADI ROADRUNNER MACHINE SUPPORT
M: Lennert Buytenhek <kernel@wantstofly.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
M: Sascha Hauer <kernel@pengutronix.de>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
+T: git://git.pengutronix.de/git/imx/linux-2.6.git
+F: arch/arm/mach-mx*/
+F: arch/arm/plat-mxc/
ARM/GLOMATION GESBC9312SX MACHINE SUPPORT
M: Lennert Buytenhek <kernel@wantstofly.org>
S: Maintained
F: arch/arm/mach-ixp4xx/
+ARM/INTEL RESEARCH IMOTE 2 MACHINE SUPPORT
+M: Jonathan Cameron <jic23@cam.ac.uk>
+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S: Maintained
+F: arch/arm/mach-pxa/imote2.c
+
+ARM/INTEL RESEARCH STARGATE 2 MACHINE SUPPORT
+M: Jonathan Cameron <jic23@cam.ac.uk>
+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S: Maintained
+F: arch/arm/mach-pxa/stargate2.c
+F: drivers/pcmcia/pxa2xx_stargate2.c
+
ARM/INTEL XSC3 (MANZANO) ARM CORE
M: Lennert Buytenhek <kernel@wantstofly.org>
M: Dan Williams <dan.j.williams@intel.com>
M: Michael Petchkovsky <mkpetch@internode.on.net>
S: Maintained
+ARM/NOMADIK ARCHITECTURE
+M: Alessandro Rubini <rubini@unipv.it>
+M: STEricsson <STEricsson_nomadik_linux@list.st.com>
+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S: Maintained
+F: arch/arm/mach-nomadik/
+F: arch/arm/plat-nomadik/
+
ARM/OPENMOKO NEO FREERUNNER (GTA02) MACHINE SUPPORT
M: Nelson Castillo <arhuaco@freaks-unidos.net>
L: openmoko-kernel@lists.openmoko.org (subscribers-only)
W: http://wiki.openmoko.org/wiki/Neo_FreeRunner
S: Supported
+ARM/QUALCOMM MSM MACHINE SUPPORT
+M: David Brown <davidb@codeaurora.org>
+M: Daniel Walker <dwalker@codeaurora.org>
+M: Bryan Huntsman <bryanh@codeaurora.org>
+F: arch/arm/mach-msm/
+F: drivers/video/msm/
+F: drivers/mmc/host/msm_sdcc.c
+F: drivers/mmc/host/msm_sdcc.h
+F: drivers/serial/msm_serial.h
+F: drivers/serial/msm_serial.c
+T: git git://codeaurora.org/quic/kernel/dwalker/linux-msm.git
+S: Maintained
+
ARM/TOSA MACHINE SUPPORT
M: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
M: Dirk Opfer <dirk@opfer-online.de>
W: http://www.mcuos.com
S: Maintained
+ARM/U8500 ARM ARCHITECTURE
+M: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S: Maintained
+F: arch/arm/mach-ux500/
+
ARM/VFP SUPPORT
M: Russell King <linux@arm.linux.org.uk>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L: acpi4asus-user@lists.sourceforge.net
W: http://acpi4asus.sf.net
S: Maintained
-F: arch/x86/kernel/acpi/boot.c
F: drivers/platform/x86/asus_acpi.c
ASUS ASB100 HARDWARE MONITOR DRIVER
ATMEL LCDFB DRIVER
M: Nicolas Ferre <nicolas.ferre@atmel.com>
-L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers)
+L: linux-fbdev@vger.kernel.org
S: Maintained
F: drivers/video/atmel_lcdfb.c
F: include/video/atmel_lcdc.h
F: net/ax25/
B43 WIRELESS DRIVER
-M: Michael Buesch <mb@bu3sch.de>
M: Stefano Brivio <stefano.brivio@polimi.it>
L: linux-wireless@vger.kernel.org
W: http://linuxwireless.org/en/users/Drivers/b43
F: drivers/net/tg3.*
BROCADE BFA FC SCSI DRIVER
-P: Jing Huang
-M: huangj@brocade.com
-L: linux-scsi@vger.kernel.org
-S: Supported
-F: drivers/scsi/bfa/
+M: Jing Huang <huangj@brocade.com>
+L: linux-scsi@vger.kernel.org
+S: Supported
+F: drivers/scsi/bfa/
BSG (block layer generic sg v4 driver)
M: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
F: drivers/scsi/dpt*
F: drivers/scsi/dpt/
+DRBD DRIVER
+P: Philipp Reisner
+P: Lars Ellenberg
+M: drbd-dev@lists.linbit.com
+L: drbd-user@lists.linbit.com
+W: http://www.drbd.org
+T: git git://git.drbd.org/linux-2.6-drbd.git drbd
+T: git git://git.drbd.org/drbd-8.3.git
+S: Supported
+F: drivers/block/drbd/
+F: lib/lru_cache.c
+F: Documentation/blockdev/drbd/
+
DRIVER CORE, KOBJECTS, AND SYSFS
M: Greg Kroah-Hartman <gregkh@suse.de>
T: quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
F: drivers/net/wan/sdla.c
FRAMEBUFFER LAYER
-L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers)
+L: linux-fbdev@vger.kernel.org
W: http://linux-fbdev.sourceforge.net/
S: Orphan
F: Documentation/fb/
FREESCALE IMX / MXC FRAMEBUFFER DRIVER
M: Sascha Hauer <kernel@pengutronix.de>
-L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers)
+L: linux-fbdev@vger.kernel.org
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: arch/arm/plat-mxc/include/mach/imxfb.h
S: Maintained
F: drivers/media/video/gspca/finepix.c
+GSPCA GL860 SUBDRIVER
+M: Olivier Lorin <o.lorin@laposte.net>
+L: linux-media@vger.kernel.org
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
+S: Maintained
+F: drivers/media/video/gspca/gl860/
+
GSPCA M5602 SUBDRIVER
M: Erik Andren <erik.andren@gmail.com>
L: linux-media@vger.kernel.org
L: lm-sensors@lm-sensors.org
W: http://www.lm-sensors.org/
S: Orphan
+F: Documentation/hwmon/
F: drivers/hwmon/
+F: include/linux/hwmon*.h
HARDWARE RANDOM NUMBER GENERATOR CORE
M: Matt Mackall <mpm@selenic.com>
F: Documentation/i2c/
F: drivers/i2c/
F: include/linux/i2c.h
-F: include/linux/i2c-dev.h
-F: include/linux/i2c-id.h
+F: include/linux/i2c-*.h
I2C-TINY-USB DRIVER
M: Till Harbaum <till@harbaum.org>
F: security/integrity/ima/
IMS TWINTURBO FRAMEBUFFER DRIVER
-L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers)
+L: linux-fbdev@vger.kernel.org
S: Orphan
F: drivers/video/imsttfb.c
INTEL FRAMEBUFFER DRIVER (excluding 810 and 815)
M: Sylvain Meyer <sylvain.meyer@worldonline.fr>
-L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers)
+L: linux-fbdev@vger.kernel.org
S: Maintained
F: Documentation/fb/intelfb.txt
F: drivers/video/intelfb/
INTEL 810/815 FRAMEBUFFER DRIVER
M: Antonino Daplas <adaplas@gmail.com>
-L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers)
+L: linux-fbdev@vger.kernel.org
S: Maintained
F: drivers/video/i810/
S: Supported
F: drivers/net/wireless/iwlwifi/
+INTEL WIRELESS MULTICOMM 3200 WIFI (iwmc3200wifi)
+M: Samuel Ortiz <samuel.ortiz@intel.com>
+M: Zhu Yi <yi.zhu@intel.com>
+M: Intel Linux Wireless <ilw@linux.intel.com>
+L: linux-wireless@vger.kernel.org
+S: Supported
+W: http://wireless.kernel.org/en/users/Drivers/iwmc3200wifi
+F: drivers/net/wireless/iwmc3200wifi/
+
IOC3 ETHERNET DRIVER
M: Ralf Baechle <ralf@linux-mips.org>
L: linux-mips@linux-mips.org
IPMI SUBSYSTEM
M: Corey Minyard <minyard@acm.org>
-L: openipmi-developer@lists.sourceforge.net
+L: openipmi-developer@lists.sourceforge.net (moderated for non-subscribers)
W: http://openipmi.sourceforge.net/
S: Supported
F: Documentation/IPMI.txt
F: fs/autofs4/
KERNEL BUILD
-M: Sam Ravnborg <sam@ravnborg.org>
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/sam/kbuild-next.git
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/sam/kbuild-fixes.git
L: linux-kbuild@vger.kernel.org
-S: Maintained
+S: Orphan
F: Documentation/kbuild/
F: Makefile
F: scripts/Makefile.*
F: Documentation/s390/kvm.txt
F: arch/s390/include/asm/kvm*
F: arch/s390/kvm/
+F: drivers/s390/kvm/
KEXEC
M: Eric Biederman <ebiederm@xmission.com>
KMEMCHECK
M: Vegard Nossum <vegardno@ifi.uio.no>
-P Pekka Enberg
-M: penberg@cs.helsinki.fi
+M: Pekka Enberg <penberg@cs.helsinki.fi>
S: Maintained
+F: Documentation/kmemcheck.txt
+F: arch/x86/include/asm/kmemcheck.h
+F: arch/x86/mm/kmemcheck/
+F: include/linux/kmemcheck.h
+F: mm/kmemcheck.c
KMEMLEAK
M: Catalin Marinas <catalin.marinas@arm.com>
M: Paul Mackerras <paulus@au.ibm.com>
W: http://www.ibm.com/linux/ltc/projects/ppc
S: Supported
+F: arch/powerpc/boot/rs6000.h
LINUX FOR POWERPC (32-BIT AND 64-BIT)
M: Benjamin Herrenschmidt <benh@kernel.crashing.org>
L: linuxppc-dev@ozlabs.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git
S: Supported
+F: Documentation/powerpc/
+F: arch/powerpc/
LINUX FOR POWER MACINTOSH
M: Benjamin Herrenschmidt <benh@kernel.crashing.org>
W: http://www.penguinppc.org/
L: linuxppc-dev@ozlabs.org
S: Maintained
+F: arch/powerpc/platforms/powermac/
+F: drivers/macintosh/
LINUX FOR POWERPC EMBEDDED MPC5XXX
M: Grant Likely <grant.likely@secretlab.ca>
L: linuxppc-dev@ozlabs.org
T: git git://git.secretlab.ca/git/linux-2.6.git
S: Maintained
+F: arch/powerpc/platforms/512x/
+F: arch/powerpc/platforms/52xx/
LINUX FOR POWERPC EMBEDDED PPC4XX
M: Josh Boyer <jwboyer@linux.vnet.ibm.com>
L: linuxppc-dev@ozlabs.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jwboyer/powerpc-4xx.git
S: Maintained
+F: arch/powerpc/platforms/40x/
+F: arch/powerpc/platforms/44x/
LINUX FOR POWERPC EMBEDDED XILINX VIRTEX
M: Grant Likely <grant.likely@secretlab.ca>
L: linuxppc-dev@ozlabs.org
T: git git://git.secretlab.ca/git/linux-2.6.git
S: Maintained
+F: arch/powerpc/*/*virtex*
+F: arch/powerpc/*/*/*virtex*
LINUX FOR POWERPC EMBEDDED PPC8XX
M: Vitaly Bordug <vitb@kernel.crashing.org>
W: http://www.penguinppc.org/
L: linuxppc-dev@ozlabs.org
S: Maintained
+F: arch/powerpc/platforms/83xx/
LINUX FOR POWERPC PA SEMI PWRFICIENT
M: Olof Johansson <olof@lixom.net>
W: http://www.pasemi.com/
L: linuxppc-dev@ozlabs.org
S: Supported
+F: arch/powerpc/platforms/pasemi/
+F: drivers/*/*pasemi*
+F: drivers/*/*/*pasemi*
LINUX SECURITY MODULE (LSM) FRAMEWORK
M: Chris Wright <chrisw@sous-sol.org>
F: Documentation/hwmon/lis3lv02d
F: drivers/hwmon/lis3lv02d.*
+LM73 HARDWARE MONITOR DRIVER
+M: Guillaume Ligneul <guillaume.ligneul@gmail.com>
+L: lm-sensors@lm-sensors.org
+S: Maintained
+F: drivers/hwmon/lm73.c
+
LM83 HARDWARE MONITOR DRIVER
M: Jean Delvare <khali@linux-fr.org>
L: lm-sensors@lm-sensors.org
MATROX FRAMEBUFFER DRIVER
M: Petr Vandrovec <vandrove@vc.cvut.cz>
-L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers)
+L: linux-fbdev@vger.kernel.org
S: Maintained
F: drivers/video/matrox/matroxfb_*
F: include/linux/matroxfb.h
L: coreteam@netfilter.org
W: http://www.netfilter.org/
W: http://www.iptables.org/
-T: git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-2.6.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-2.6.git
S: Supported
F: include/linux/netfilter*
F: include/linux/netfilter/
W: http://www.linuxfoundation.org/en/Net
W: http://patchwork.ozlabs.org/project/netdev/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6.git
S: Maintained
F: net/
F: include/net/
F: include/linux/*device.h
NETXEN (1/10) GbE SUPPORT
-M: Dhananjay Phadke <dhananjay@netxen.com>
+M: Amit Kumar Salecha <amit.salecha@qlogic.com>
L: netdev@vger.kernel.org
-W: http://www.netxen.com
+W: http://www.qlogic.com
S: Supported
F: drivers/net/netxen/
NVIDIA (rivafb and nvidiafb) FRAMEBUFFER DRIVER
M: Antonino Daplas <adaplas@gmail.com>
-L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers)
+L: linux-fbdev@vger.kernel.org
S: Maintained
F: drivers/video/riva/
F: drivers/video/nvidia/
OMAP FRAMEBUFFER SUPPORT
M: Imre Deak <imre.deak@nokia.com>
-L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers)
+L: linux-fbdev@vger.kernel.org
L: linux-omap@vger.kernel.org
S: Maintained
F: drivers/video/omap/
+OMAP DISPLAY SUBSYSTEM SUPPORT (DSS2)
+M: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+L: linux-omap@vger.kernel.org
+L: linux-fbdev@vger.kernel.org (moderated for non-subscribers)
+S: Maintained
+F: drivers/video/omap2/dss/
+F: drivers/video/omap2/vrfb.c
+F: drivers/video/omap2/vram.c
+F: Documentation/arm/OMAP/DSS
+
+OMAP FRAMEBUFFER SUPPORT (FOR DSS2)
+M: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+L: linux-omap@vger.kernel.org
+L: linux-fbdev@vger.kernel.org (moderated for non-subscribers)
+S: Maintained
+F: drivers/video/omap2/omapfb/
+
OMAP MMC SUPPORT
M: Jarkko Lavinen <jarkko.lavinen@nokia.com>
L: linux-omap@vger.kernel.org
S: Supported
F: drivers/scsi/pmcraid.*
+PMC SIERRA PM8001 DRIVER
+M: jack_wang@usish.com
+M: lindar_liu@usish.com
+L: linux-scsi@vger.kernel.org
+S: Supported
+F: drivers/scsi/pm8001/
+
POSIX CLOCKS and TIMERS
M: Thomas Gleixner <tglx@linutronix.de>
S: Supported
RADEON FRAMEBUFFER DISPLAY DRIVER
M: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers)
+L: linux-fbdev@vger.kernel.org
S: Maintained
F: drivers/video/aty/radeon*
F: include/linux/radeonfb.h
RAGE128 FRAMEBUFFER DISPLAY DRIVER
M: Paul Mackerras <paulus@samba.org>
-L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers)
+L: linux-fbdev@vger.kernel.org
S: Maintained
F: drivers/video/aty/aty128fb.c
RALINK RT2X00 WIRELESS LAN DRIVER
P: rt2x00 project
+M: Ivo van Doorn <IvDoorn@gmail.com>
+M: Gertjan van Wingerde <gwingerde@gmail.com>
L: linux-wireless@vger.kernel.org
L: users@rt2x00.serialmonkey.com (moderated for non-subscribers)
W: http://rt2x00.serialmonkey.com/
M: Johannes Berg <johannes@sipsolutions.net>
L: linux-wireless@vger.kernel.org
S: Maintained
-F Documentation/rfkill.txt
+F: Documentation/rfkill.txt
F: net/rfkill/
RISCOM8 DRIVER
S3 SAVAGE FRAMEBUFFER DRIVER
M: Antonino Daplas <adaplas@gmail.com>
-L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers)
+L: linux-fbdev@vger.kernel.org
S: Maintained
F: drivers/video/savage/
W: http://www.ibm.com/developerworks/linux/linux390/
S: Supported
F: arch/s390/
+F: drivers/s390/
S390 NETWORK DRIVERS
M: Ursula Braun <ursula.braun@de.ibm.com>
M: Ralph Wuerthner <ralph.wuerthner@de.ibm.com>
M: linux390@de.ibm.com
L: linux-s390@vger.kernel.org
+W: http://www.ibm.com/developerworks/linux/linux390/
S: Supported
F: drivers/s390/crypto/
SECURITY SUBSYSTEM
M: James Morris <jmorris@namei.org>
L: linux-security-module@vger.kernel.org (suggested Cc:)
-T: git git://www.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6.git
W: http://security.wiki.kernel.org/
S: Supported
F: security/
F: include/linux/libata.h
SERVER ENGINES 10Gbps iSCSI - BladeEngine 2 DRIVER
-P: Jayamohan Kallickal
-M: jayamohank@serverengines.com
-L: linux-scsi@vger.kernel.org
-W: http://www.serverengines.com
-S: Supported
-F: drivers/scsi/be2iscsi/
+M: Jayamohan Kallickal <jayamohank@serverengines.com>
+L: linux-scsi@vger.kernel.org
+W: http://www.serverengines.com
+S: Supported
+F: drivers/scsi/be2iscsi/
SERVER ENGINES 10Gbps NIC - BladeEngine 2 DRIVER
M: Sathya Perla <sathyap@serverengines.com>
SPI SUBSYSTEM
M: David Brownell <dbrownell@users.sourceforge.net>
+ M: Grant Likely <grant.likely@secretlab.ca>
L: spi-devel-general@lists.sourceforge.net
S: Maintained
F: Documentation/spi/
F: drivers/scsi/u14-34f.c
UBI FILE SYSTEM (UBIFS)
-M: Artem Bityutskiy <dedekind@infradead.org>
+M: Artem Bityutskiy <dedekind1@gmail.com>
M: Adrian Hunter <adrian.hunter@nokia.com>
L: linux-mtd@lists.infradead.org
T: git git://git.infradead.org/ubifs-2.6.git
F: include/linux/cdrom.h
UNSORTED BLOCK IMAGES (UBI)
-M: Artem Bityutskiy <dedekind@infradead.org>
+M: Artem Bityutskiy <dedekind1@gmail.com>
W: http://www.linux-mtd.infradead.org/
L: linux-mtd@lists.infradead.org
T: git git://git.infradead.org/ubi-2.6.git
F: drivers/block/ub.c
USB CDC ETHERNET DRIVER
-M: Greg Kroah-Hartman <greg@kroah.com>
+M: Oliver Neukum <oliver@neukum.name>
L: linux-usb@vger.kernel.org
S: Maintained
-W: http://www.kroah.com/linux-usb/
F: drivers/net/usb/cdc_*.c
F: include/linux/usb/cdc.h
F: drivers/net/wireless/rndis_wlan.c
USB XHCI DRIVER
-M: Sarah Sharp <sarah.a.sharp@intel.com>
+M: Sarah Sharp <sarah.a.sharp@linux.intel.com>
L: linux-usb@vger.kernel.org
S: Supported
+F: drivers/usb/host/xhci*
+F: drivers/usb/host/pci-quirks*
USB ZC0301 DRIVER
M: Luca Risolia <luca.risolia@studio.unibo.it>
UVESAFB DRIVER
M: Michal Januszewski <spock@gentoo.org>
-L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers)
+L: linux-fbdev@vger.kernel.org
W: http://dev.gentoo.org/~spock/projects/uvesafb/
S: Maintained
F: Documentation/fb/uvesafb.txt
VIA UNICHROME(PRO)/CHROME9 FRAMEBUFFER DRIVER
M: Joseph Chan <JosephChan@via.com.tw>
M: Scott Fang <ScottFang@viatech.com.cn>
-L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers)
+L: linux-fbdev@vger.kernel.org
S: Maintained
F: drivers/video/via/
F: include/linux/vlynq.h
VMWARE VMXNET3 ETHERNET DRIVER
-M: Shreyas Bhatewara <sbhatewara@vmware.com>
-M: VMware, Inc. <pv-drivers@vmware.com>
-L: netdev@vger.kernel.org
-S: Maintained
-F: drivers/net/vmxnet3/
+M: Shreyas Bhatewara <sbhatewara@vmware.com>
+M: "VMware, Inc." <pv-drivers@vmware.com>
+L: netdev@vger.kernel.org
+S: Maintained
+F: drivers/net/vmxnet3/
+
+VMware PVSCSI driver
+M: Alok Kataria <akataria@vmware.com>
+M: VMware PV-Drivers <pv-drivers@vmware.com>
+L: linux-scsi@vger.kernel.org
+S: Maintained
+F: drivers/scsi/vmw_pvscsi.c
+F: drivers/scsi/vmw_pvscsi.h
VOLTAGE AND CURRENT REGULATOR FRAMEWORK
M: Liam Girdwood <lrg@slimlogic.co.uk>
*
* Copyright (C) 2006 Polycom, Inc.
*
+ * CPM SPI and QE buffer descriptors mode support:
+ * Copyright (c) 2009 MontaVista Software, Inc.
+ * Author: Anton Vorontsov <avorontsov@ru.mvista.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
#include <linux/spi/spi_bitbang.h>
#include <linux/platform_device.h>
#include <linux/fsl_devices.h>
+#include <linux/dma-mapping.h>
+#include <linux/mm.h>
+#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/gpio.h>
#include <linux/of_spi.h>
#include <sysdev/fsl_soc.h>
+#include <asm/cpm.h>
+#include <asm/qe.h>
#include <asm/irq.h>
+/* CPM1 and CPM2 are mutually exclusive. */
+#ifdef CONFIG_CPM1
+#include <asm/cpm1.h>
+#define CPM_SPI_CMD mk_cr_cmd(CPM_CR_CH_SPI, 0)
+#else
+#include <asm/cpm2.h>
+#define CPM_SPI_CMD mk_cr_cmd(CPM_CR_SPI_PAGE, CPM_CR_SPI_SBLOCK, 0, 0)
+#endif
+
/* SPI Controller registers */
struct mpc8xxx_spi_reg {
u8 res1[0x20];
__be32 receive;
};
+/* SPI Parameter RAM */
+struct spi_pram {
+ __be16 rbase; /* Rx Buffer descriptor base address */
+ __be16 tbase; /* Tx Buffer descriptor base address */
+ u8 rfcr; /* Rx function code */
+ u8 tfcr; /* Tx function code */
+ __be16 mrblr; /* Max receive buffer length */
+ __be32 rstate; /* Internal */
+ __be32 rdp; /* Internal */
+ __be16 rbptr; /* Internal */
+ __be16 rbc; /* Internal */
+ __be32 rxtmp; /* Internal */
+ __be32 tstate; /* Internal */
+ __be32 tdp; /* Internal */
+ __be16 tbptr; /* Internal */
+ __be16 tbc; /* Internal */
+ __be32 txtmp; /* Internal */
+ __be32 res; /* Tx temp. */
+ __be16 rpbase; /* Relocation pointer (CPM1 only) */
+ __be16 res1; /* Reserved */
+};
+
/* SPI Controller mode register definitions */
#define SPMODE_LOOP (1 << 30)
#define SPMODE_CI_INACTIVEHIGH (1 << 29)
#define SPIM_NE 0x00000200 /* Not empty */
#define SPIM_NF 0x00000100 /* Not full */
+#define SPIE_TXB 0x00000200 /* Last char is written to tx fifo */
+#define SPIE_RXB 0x00000100 /* Last char is written to rx buf */
+
+/* SPCOM register values */
+#define SPCOM_STR (1 << 23) /* Start transmit */
+
+#define SPI_PRAM_SIZE 0x100
+#define SPI_MRBLR ((unsigned int)PAGE_SIZE)
+
/* SPI Controller driver's private data. */
struct mpc8xxx_spi {
+ struct device *dev;
struct mpc8xxx_spi_reg __iomem *base;
/* rx & tx bufs from the spi_transfer */
const void *tx;
void *rx;
+ int subblock;
+ struct spi_pram __iomem *pram;
+ struct cpm_buf_desc __iomem *tx_bd;
+ struct cpm_buf_desc __iomem *rx_bd;
+
+ struct spi_transfer *xfer_in_progress;
+
+ /* dma addresses for CPM transfers */
+ dma_addr_t tx_dma;
+ dma_addr_t rx_dma;
+ bool map_tx_dma;
+ bool map_rx_dma;
+
+ dma_addr_t dma_dummy_tx;
+ dma_addr_t dma_dummy_rx;
+
/* functions to deal with different sized buffers */
void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *);
u32(*get_tx) (struct mpc8xxx_spi *);
u32 rx_shift; /* RX data reg shift when in qe mode */
u32 tx_shift; /* TX data reg shift when in qe mode */
- bool qe_mode;
+ unsigned int flags;
struct workqueue_struct *workqueue;
struct work_struct work;
struct completion done;
};
+static void *mpc8xxx_dummy_rx;
+static DEFINE_MUTEX(mpc8xxx_dummy_rx_lock);
+static int mpc8xxx_dummy_rx_refcnt;
+
struct spi_mpc8xxx_cs {
/* functions to deal with different sized buffers */
void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *);
MPC83XX_SPI_TX_BUF(u16)
MPC83XX_SPI_TX_BUF(u32)
+static void mpc8xxx_spi_change_mode(struct spi_device *spi)
+{
+ struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
+ struct spi_mpc8xxx_cs *cs = spi->controller_state;
+ __be32 __iomem *mode = &mspi->base->mode;
+ unsigned long flags;
+
+ if (cs->hw_mode == mpc8xxx_spi_read_reg(mode))
+ return;
+
+ /* Turn off IRQs locally to minimize time that SPI is disabled. */
+ local_irq_save(flags);
+
+ /* Turn off SPI unit prior changing mode */
+ mpc8xxx_spi_write_reg(mode, cs->hw_mode & ~SPMODE_ENABLE);
+ mpc8xxx_spi_write_reg(mode, cs->hw_mode);
+
+ /* When in CPM mode, we need to reinit tx and rx. */
+ if (mspi->flags & SPI_CPM_MODE) {
+ if (mspi->flags & SPI_QE) {
+ qe_issue_cmd(QE_INIT_TX_RX, mspi->subblock,
+ QE_CR_PROTOCOL_UNSPECIFIED, 0);
+ } else {
+ cpm_command(CPM_SPI_CMD, CPM_CR_INIT_TRX);
+ if (mspi->flags & SPI_CPM1) {
+ out_be16(&mspi->pram->rbptr,
+ in_be16(&mspi->pram->rbase));
+ out_be16(&mspi->pram->tbptr,
+ in_be16(&mspi->pram->tbase));
+ }
+ }
+ }
+
+ local_irq_restore(flags);
+}
+
static void mpc8xxx_spi_chipselect(struct spi_device *spi, int value)
{
struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
}
if (value == BITBANG_CS_ACTIVE) {
- u32 regval = mpc8xxx_spi_read_reg(&mpc8xxx_spi->base->mode);
-
mpc8xxx_spi->rx_shift = cs->rx_shift;
mpc8xxx_spi->tx_shift = cs->tx_shift;
mpc8xxx_spi->get_rx = cs->get_rx;
mpc8xxx_spi->get_tx = cs->get_tx;
- if (cs->hw_mode != regval) {
- unsigned long flags;
- __be32 __iomem *mode = &mpc8xxx_spi->base->mode;
-
- regval = cs->hw_mode;
- /* Turn off IRQs locally to minimize time that
- * SPI is disabled
- */
- local_irq_save(flags);
- /* Turn off SPI unit prior changing mode */
- mpc8xxx_spi_write_reg(mode, regval & ~SPMODE_ENABLE);
- mpc8xxx_spi_write_reg(mode, regval);
- local_irq_restore(flags);
- }
+ mpc8xxx_spi_change_mode(spi);
+
if (pdata->cs_control)
pdata->cs_control(spi, pol);
}
int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
{
struct mpc8xxx_spi *mpc8xxx_spi;
- u32 regval;
u8 bits_per_word, pm;
u32 hz;
struct spi_mpc8xxx_cs *cs = spi->controller_state;
if (bits_per_word <= 8) {
cs->get_rx = mpc8xxx_spi_rx_buf_u8;
cs->get_tx = mpc8xxx_spi_tx_buf_u8;
- if (mpc8xxx_spi->qe_mode) {
+ if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
cs->rx_shift = 16;
cs->tx_shift = 24;
}
} else if (bits_per_word <= 16) {
cs->get_rx = mpc8xxx_spi_rx_buf_u16;
cs->get_tx = mpc8xxx_spi_tx_buf_u16;
- if (mpc8xxx_spi->qe_mode) {
+ if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
cs->rx_shift = 16;
cs->tx_shift = 16;
}
} else
return -EINVAL;
- if (mpc8xxx_spi->qe_mode && spi->mode & SPI_LSB_FIRST) {
+ if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE &&
+ spi->mode & SPI_LSB_FIRST) {
cs->tx_shift = 0;
if (bits_per_word <= 8)
cs->rx_shift = 8;
pm--;
cs->hw_mode |= SPMODE_PM(pm);
- regval = mpc8xxx_spi_read_reg(&mpc8xxx_spi->base->mode);
- if (cs->hw_mode != regval) {
- unsigned long flags;
- __be32 __iomem *mode = &mpc8xxx_spi->base->mode;
-
- regval = cs->hw_mode;
- /* Turn off IRQs locally to minimize time
- * that SPI is disabled
- */
- local_irq_save(flags);
- /* Turn off SPI unit prior changing mode */
- mpc8xxx_spi_write_reg(mode, regval & ~SPMODE_ENABLE);
- mpc8xxx_spi_write_reg(mode, regval);
- local_irq_restore(flags);
+
+ mpc8xxx_spi_change_mode(spi);
+ return 0;
+}
+
+static void mpc8xxx_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi)
+{
+ struct cpm_buf_desc __iomem *tx_bd = mspi->tx_bd;
+ struct cpm_buf_desc __iomem *rx_bd = mspi->rx_bd;
+ unsigned int xfer_len = min(mspi->count, SPI_MRBLR);
+ unsigned int xfer_ofs;
+
+ xfer_ofs = mspi->xfer_in_progress->len - mspi->count;
+
+ out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma + xfer_ofs);
+ out_be16(&rx_bd->cbd_datlen, 0);
+ out_be16(&rx_bd->cbd_sc, BD_SC_EMPTY | BD_SC_INTRPT | BD_SC_WRAP);
+
+ out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma + xfer_ofs);
+ out_be16(&tx_bd->cbd_datlen, xfer_len);
+ out_be16(&tx_bd->cbd_sc, BD_SC_READY | BD_SC_INTRPT | BD_SC_WRAP |
+ BD_SC_LAST);
+
+ /* start transfer */
+ mpc8xxx_spi_write_reg(&mspi->base->command, SPCOM_STR);
+}
+
+static int mpc8xxx_spi_cpm_bufs(struct mpc8xxx_spi *mspi,
+ struct spi_transfer *t, bool is_dma_mapped)
+{
+ struct device *dev = mspi->dev;
+
+ if (is_dma_mapped) {
+ mspi->map_tx_dma = 0;
+ mspi->map_rx_dma = 0;
+ } else {
+ mspi->map_tx_dma = 1;
+ mspi->map_rx_dma = 1;
+ }
+
+ if (!t->tx_buf) {
+ mspi->tx_dma = mspi->dma_dummy_tx;
+ mspi->map_tx_dma = 0;
+ }
+
+ if (!t->rx_buf) {
+ mspi->rx_dma = mspi->dma_dummy_rx;
+ mspi->map_rx_dma = 0;
+ }
+
+ if (mspi->map_tx_dma) {
+ void *nonconst_tx = (void *)mspi->tx; /* shut up gcc */
+
+ mspi->tx_dma = dma_map_single(dev, nonconst_tx, t->len,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, mspi->tx_dma)) {
+ dev_err(dev, "unable to map tx dma\n");
+ return -ENOMEM;
+ }
+ } else {
+ mspi->tx_dma = t->tx_dma;
+ }
+
+ if (mspi->map_rx_dma) {
+ mspi->rx_dma = dma_map_single(dev, mspi->rx, t->len,
+ DMA_FROM_DEVICE);
+ if (dma_mapping_error(dev, mspi->rx_dma)) {
+ dev_err(dev, "unable to map rx dma\n");
+ goto err_rx_dma;
+ }
+ } else {
+ mspi->rx_dma = t->rx_dma;
}
+
+ /* enable rx ints */
+ mpc8xxx_spi_write_reg(&mspi->base->mask, SPIE_RXB);
+
+ mspi->xfer_in_progress = t;
+ mspi->count = t->len;
+
+ /* start CPM transfers */
+ mpc8xxx_spi_cpm_bufs_start(mspi);
+
return 0;
+
+err_rx_dma:
+ if (mspi->map_tx_dma)
+ dma_unmap_single(dev, mspi->tx_dma, t->len, DMA_TO_DEVICE);
+ return -ENOMEM;
}
-static int mpc8xxx_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
+static void mpc8xxx_spi_cpm_bufs_complete(struct mpc8xxx_spi *mspi)
{
- struct mpc8xxx_spi *mpc8xxx_spi;
- u32 word, len, bits_per_word;
+ struct device *dev = mspi->dev;
+ struct spi_transfer *t = mspi->xfer_in_progress;
+
+ if (mspi->map_tx_dma)
+ dma_unmap_single(dev, mspi->tx_dma, t->len, DMA_TO_DEVICE);
+ if (mspi->map_tx_dma)
+ dma_unmap_single(dev, mspi->rx_dma, t->len, DMA_FROM_DEVICE);
+ mspi->xfer_in_progress = NULL;
+}
- mpc8xxx_spi = spi_master_get_devdata(spi->master);
+static int mpc8xxx_spi_cpu_bufs(struct mpc8xxx_spi *mspi,
+ struct spi_transfer *t, unsigned int len)
+{
+ u32 word;
+
+ mspi->count = len;
+
+ /* enable rx ints */
+ mpc8xxx_spi_write_reg(&mspi->base->mask, SPIM_NE);
+
+ /* transmit word */
+ word = mspi->get_tx(mspi);
+ mpc8xxx_spi_write_reg(&mspi->base->transmit, word);
+
+ return 0;
+}
+
+static int mpc8xxx_spi_bufs(struct spi_device *spi, struct spi_transfer *t,
+ bool is_dma_mapped)
+{
+ struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
+ unsigned int len = t->len;
+ u8 bits_per_word;
+ int ret;
bits_per_word = spi->bits_per_word;
if (t->bits_per_word)
bits_per_word = t->bits_per_word;
- len = t->len;
+
if (bits_per_word > 8) {
/* invalid length? */
if (len & 1)
return -EINVAL;
len /= 2;
}
- mpc8xxx_spi->count = len;
- INIT_COMPLETION(mpc8xxx_spi->done);
+ mpc8xxx_spi->tx = t->tx_buf;
+ mpc8xxx_spi->rx = t->rx_buf;
- /* enable rx ints */
- mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mask, SPIM_NE);
+ INIT_COMPLETION(mpc8xxx_spi->done);
- /* transmit word */
- word = mpc8xxx_spi->get_tx(mpc8xxx_spi);
- mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->transmit, word);
+ if (mpc8xxx_spi->flags & SPI_CPM_MODE)
+ ret = mpc8xxx_spi_cpm_bufs(mpc8xxx_spi, t, is_dma_mapped);
+ else
+ ret = mpc8xxx_spi_cpu_bufs(mpc8xxx_spi, t, len);
+ if (ret)
+ return ret;
wait_for_completion(&mpc8xxx_spi->done);
/* disable rx ints */
mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mask, 0);
+ if (mpc8xxx_spi->flags & SPI_CPM_MODE)
+ mpc8xxx_spi_cpm_bufs_complete(mpc8xxx_spi);
+
return mpc8xxx_spi->count;
}
}
cs_change = t->cs_change;
if (t->len)
- status = mpc8xxx_spi_bufs(spi, t);
+ status = mpc8xxx_spi_bufs(spi, t, m->is_dma_mapped);
if (status) {
status = -EMSGSIZE;
break;
return 0;
}
-static irqreturn_t mpc8xxx_spi_irq(s32 irq, void *context_data)
+static void mpc8xxx_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events)
{
- struct mpc8xxx_spi *mpc8xxx_spi = context_data;
- u32 event;
- irqreturn_t ret = IRQ_NONE;
+ u16 len;
- /* Get interrupt events(tx/rx) */
- event = mpc8xxx_spi_read_reg(&mpc8xxx_spi->base->event);
+ dev_dbg(mspi->dev, "%s: bd datlen %d, count %d\n", __func__,
+ in_be16(&mspi->rx_bd->cbd_datlen), mspi->count);
- /* We need handle RX first */
- if (event & SPIE_NE) {
- u32 rx_data = mpc8xxx_spi_read_reg(&mpc8xxx_spi->base->receive);
+ len = in_be16(&mspi->rx_bd->cbd_datlen);
+ if (len > mspi->count) {
+ WARN_ON(1);
+ len = mspi->count;
+ }
- if (mpc8xxx_spi->rx)
- mpc8xxx_spi->get_rx(rx_data, mpc8xxx_spi);
+ /* Clear the events */
+ mpc8xxx_spi_write_reg(&mspi->base->event, events);
- ret = IRQ_HANDLED;
+ mspi->count -= len;
+ if (mspi->count)
+ mpc8xxx_spi_cpm_bufs_start(mspi);
+ else
+ complete(&mspi->done);
+}
+
+static void mpc8xxx_spi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events)
+{
+ /* We need handle RX first */
+ if (events & SPIE_NE) {
+ u32 rx_data = mpc8xxx_spi_read_reg(&mspi->base->receive);
+
+ if (mspi->rx)
+ mspi->get_rx(rx_data, mspi);
}
- if ((event & SPIE_NF) == 0)
+ if ((events & SPIE_NF) == 0)
/* spin until TX is done */
- while (((event =
- mpc8xxx_spi_read_reg(&mpc8xxx_spi->base->event)) &
+ while (((events =
+ mpc8xxx_spi_read_reg(&mspi->base->event)) &
SPIE_NF) == 0)
cpu_relax();
- mpc8xxx_spi->count -= 1;
- if (mpc8xxx_spi->count) {
- u32 word = mpc8xxx_spi->get_tx(mpc8xxx_spi);
- mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->transmit, word);
+ /* Clear the events */
+ mpc8xxx_spi_write_reg(&mspi->base->event, events);
+
+ mspi->count -= 1;
+ if (mspi->count) {
+ u32 word = mspi->get_tx(mspi);
+
+ mpc8xxx_spi_write_reg(&mspi->base->transmit, word);
} else {
- complete(&mpc8xxx_spi->done);
+ complete(&mspi->done);
}
+}
- /* Clear the events */
- mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->event, event);
+static irqreturn_t mpc8xxx_spi_irq(s32 irq, void *context_data)
+{
+ struct mpc8xxx_spi *mspi = context_data;
+ irqreturn_t ret = IRQ_NONE;
+ u32 events;
+
+ /* Get interrupt events(tx/rx) */
+ events = mpc8xxx_spi_read_reg(&mspi->base->event);
+ if (events)
+ ret = IRQ_HANDLED;
+
+ dev_dbg(mspi->dev, "%s: events %x\n", __func__, events);
+
+ if (mspi->flags & SPI_CPM_MODE)
+ mpc8xxx_spi_cpm_irq(mspi, events);
+ else
+ mpc8xxx_spi_cpu_irq(mspi, events);
return ret;
}
+
static int mpc8xxx_spi_transfer(struct spi_device *spi,
struct spi_message *m)
{
kfree(spi->controller_state);
}
+static void *mpc8xxx_spi_alloc_dummy_rx(void)
+{
+ mutex_lock(&mpc8xxx_dummy_rx_lock);
+
+ if (!mpc8xxx_dummy_rx)
+ mpc8xxx_dummy_rx = kmalloc(SPI_MRBLR, GFP_KERNEL);
+ if (mpc8xxx_dummy_rx)
+ mpc8xxx_dummy_rx_refcnt++;
+
+ mutex_unlock(&mpc8xxx_dummy_rx_lock);
+
+ return mpc8xxx_dummy_rx;
+}
+
+static void mpc8xxx_spi_free_dummy_rx(void)
+{
+ mutex_lock(&mpc8xxx_dummy_rx_lock);
+
+ switch (mpc8xxx_dummy_rx_refcnt) {
+ case 0:
+ WARN_ON(1);
+ break;
+ case 1:
+ kfree(mpc8xxx_dummy_rx);
+ mpc8xxx_dummy_rx = NULL;
+ /* fall through */
+ default:
+ mpc8xxx_dummy_rx_refcnt--;
+ break;
+ }
+
+ mutex_unlock(&mpc8xxx_dummy_rx_lock);
+}
+
+static unsigned long mpc8xxx_spi_cpm_get_pram(struct mpc8xxx_spi *mspi)
+{
+ struct device *dev = mspi->dev;
+ struct device_node *np = dev_archdata_get_node(&dev->archdata);
+ const u32 *iprop;
+ int size;
+ unsigned long spi_base_ofs;
+ unsigned long pram_ofs = -ENOMEM;
+
+ /* Can't use of_address_to_resource(), QE muram isn't at 0. */
+ iprop = of_get_property(np, "reg", &size);
+
+ /* QE with a fixed pram location? */
+ if (mspi->flags & SPI_QE && iprop && size == sizeof(*iprop) * 4)
+ return cpm_muram_alloc_fixed(iprop[2], SPI_PRAM_SIZE);
+
+ /* QE but with a dynamic pram location? */
+ if (mspi->flags & SPI_QE) {
+ pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64);
+ qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, mspi->subblock,
+ QE_CR_PROTOCOL_UNSPECIFIED, pram_ofs);
+ return pram_ofs;
+ }
+
+ /* CPM1 and CPM2 pram must be at a fixed addr. */
+ if (!iprop || size != sizeof(*iprop) * 4)
+ return -ENOMEM;
+
+ spi_base_ofs = cpm_muram_alloc_fixed(iprop[2], 2);
+ if (IS_ERR_VALUE(spi_base_ofs))
+ return -ENOMEM;
+
+ if (mspi->flags & SPI_CPM2) {
+ pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64);
+ if (!IS_ERR_VALUE(pram_ofs)) {
+ u16 __iomem *spi_base = cpm_muram_addr(spi_base_ofs);
+
+ out_be16(spi_base, pram_ofs);
+ }
+ } else {
+ struct spi_pram __iomem *pram = cpm_muram_addr(spi_base_ofs);
+ u16 rpbase = in_be16(&pram->rpbase);
+
+ /* Microcode relocation patch applied? */
+ if (rpbase)
+ pram_ofs = rpbase;
+ else
+ return spi_base_ofs;
+ }
+
+ cpm_muram_free(spi_base_ofs);
+ return pram_ofs;
+}
+
+static int mpc8xxx_spi_cpm_init(struct mpc8xxx_spi *mspi)
+{
+ struct device *dev = mspi->dev;
+ struct device_node *np = dev_archdata_get_node(&dev->archdata);
+ const u32 *iprop;
+ int size;
+ unsigned long pram_ofs;
+ unsigned long bds_ofs;
+
+ if (!(mspi->flags & SPI_CPM_MODE))
+ return 0;
+
+ if (!mpc8xxx_spi_alloc_dummy_rx())
+ return -ENOMEM;
+
+ if (mspi->flags & SPI_QE) {
+ iprop = of_get_property(np, "cell-index", &size);
+ if (iprop && size == sizeof(*iprop))
+ mspi->subblock = *iprop;
+
+ switch (mspi->subblock) {
+ default:
+ dev_warn(dev, "cell-index unspecified, assuming SPI1");
+ /* fall through */
+ case 0:
+ mspi->subblock = QE_CR_SUBBLOCK_SPI1;
+ break;
+ case 1:
+ mspi->subblock = QE_CR_SUBBLOCK_SPI2;
+ break;
+ }
+ }
+
+ pram_ofs = mpc8xxx_spi_cpm_get_pram(mspi);
+ if (IS_ERR_VALUE(pram_ofs)) {
+ dev_err(dev, "can't allocate spi parameter ram\n");
+ goto err_pram;
+ }
+
+ bds_ofs = cpm_muram_alloc(sizeof(*mspi->tx_bd) +
+ sizeof(*mspi->rx_bd), 8);
+ if (IS_ERR_VALUE(bds_ofs)) {
+ dev_err(dev, "can't allocate bds\n");
+ goto err_bds;
+ }
+
+ mspi->dma_dummy_tx = dma_map_single(dev, empty_zero_page, PAGE_SIZE,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, mspi->dma_dummy_tx)) {
+ dev_err(dev, "unable to map dummy tx buffer\n");
+ goto err_dummy_tx;
+ }
+
+ mspi->dma_dummy_rx = dma_map_single(dev, mpc8xxx_dummy_rx, SPI_MRBLR,
+ DMA_FROM_DEVICE);
+ if (dma_mapping_error(dev, mspi->dma_dummy_rx)) {
+ dev_err(dev, "unable to map dummy rx buffer\n");
+ goto err_dummy_rx;
+ }
+
+ mspi->pram = cpm_muram_addr(pram_ofs);
+
+ mspi->tx_bd = cpm_muram_addr(bds_ofs);
+ mspi->rx_bd = cpm_muram_addr(bds_ofs + sizeof(*mspi->tx_bd));
+
+ /* Initialize parameter ram. */
+ out_be16(&mspi->pram->tbase, cpm_muram_offset(mspi->tx_bd));
+ out_be16(&mspi->pram->rbase, cpm_muram_offset(mspi->rx_bd));
+ out_8(&mspi->pram->tfcr, CPMFCR_EB | CPMFCR_GBL);
+ out_8(&mspi->pram->rfcr, CPMFCR_EB | CPMFCR_GBL);
+ out_be16(&mspi->pram->mrblr, SPI_MRBLR);
+ out_be32(&mspi->pram->rstate, 0);
+ out_be32(&mspi->pram->rdp, 0);
+ out_be16(&mspi->pram->rbptr, 0);
+ out_be16(&mspi->pram->rbc, 0);
+ out_be32(&mspi->pram->rxtmp, 0);
+ out_be32(&mspi->pram->tstate, 0);
+ out_be32(&mspi->pram->tdp, 0);
+ out_be16(&mspi->pram->tbptr, 0);
+ out_be16(&mspi->pram->tbc, 0);
+ out_be32(&mspi->pram->txtmp, 0);
+
+ return 0;
+
+err_dummy_rx:
+ dma_unmap_single(dev, mspi->dma_dummy_tx, PAGE_SIZE, DMA_TO_DEVICE);
+err_dummy_tx:
+ cpm_muram_free(bds_ofs);
+err_bds:
+ cpm_muram_free(pram_ofs);
+err_pram:
+ mpc8xxx_spi_free_dummy_rx();
+ return -ENOMEM;
+}
+
+static void mpc8xxx_spi_cpm_free(struct mpc8xxx_spi *mspi)
+{
+ struct device *dev = mspi->dev;
+
+ dma_unmap_single(dev, mspi->dma_dummy_rx, SPI_MRBLR, DMA_FROM_DEVICE);
+ dma_unmap_single(dev, mspi->dma_dummy_tx, PAGE_SIZE, DMA_TO_DEVICE);
+ cpm_muram_free(cpm_muram_offset(mspi->tx_bd));
+ cpm_muram_free(cpm_muram_offset(mspi->pram));
+ mpc8xxx_spi_free_dummy_rx();
+}
+
+static const char *mpc8xxx_spi_strmode(unsigned int flags)
+{
+ if (flags & SPI_QE_CPU_MODE) {
+ return "QE CPU";
+ } else if (flags & SPI_CPM_MODE) {
+ if (flags & SPI_QE)
+ return "QE";
+ else if (flags & SPI_CPM2)
+ return "CPM2";
+ else
+ return "CPM1";
+ }
+ return "CPU";
+}
+
static struct spi_master * __devinit
mpc8xxx_spi_probe(struct device *dev, struct resource *mem, unsigned int irq)
{
master->cleanup = mpc8xxx_spi_cleanup;
mpc8xxx_spi = spi_master_get_devdata(master);
- mpc8xxx_spi->qe_mode = pdata->qe_mode;
+ mpc8xxx_spi->dev = dev;
mpc8xxx_spi->get_rx = mpc8xxx_spi_rx_buf_u8;
mpc8xxx_spi->get_tx = mpc8xxx_spi_tx_buf_u8;
+ mpc8xxx_spi->flags = pdata->flags;
mpc8xxx_spi->spibrg = pdata->sysclk;
+ ret = mpc8xxx_spi_cpm_init(mpc8xxx_spi);
+ if (ret)
+ goto err_cpm_init;
+
mpc8xxx_spi->rx_shift = 0;
mpc8xxx_spi->tx_shift = 0;
- if (mpc8xxx_spi->qe_mode) {
+ if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
mpc8xxx_spi->rx_shift = 16;
mpc8xxx_spi->tx_shift = 24;
}
mpc8xxx_spi->base = ioremap(mem->start, mem->end - mem->start + 1);
if (mpc8xxx_spi->base == NULL) {
ret = -ENOMEM;
- goto put_master;
+ goto err_ioremap;
}
mpc8xxx_spi->irq = irq;
/* Enable SPI interface */
regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE;
- if (pdata->qe_mode)
+ if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE)
regval |= SPMODE_OP;
mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mode, regval);
if (ret < 0)
goto unreg_master;
- printk(KERN_INFO
- "%s: MPC8xxx SPI Controller driver at 0x%p (irq = %d)\n",
- dev_name(dev), mpc8xxx_spi->base, mpc8xxx_spi->irq);
+ dev_info(dev, "at 0x%p (irq = %d), %s mode\n", mpc8xxx_spi->base,
+ mpc8xxx_spi->irq, mpc8xxx_spi_strmode(mpc8xxx_spi->flags));
return master;
free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
unmap_io:
iounmap(mpc8xxx_spi->base);
-put_master:
+err_ioremap:
+ mpc8xxx_spi_cpm_free(mpc8xxx_spi);
+err_cpm_init:
spi_master_put(master);
err:
return ERR_PTR(ret);
free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
iounmap(mpc8xxx_spi->base);
+ mpc8xxx_spi_cpm_free(mpc8xxx_spi);
return 0;
}
gpio = of_get_gpio_flags(np, i, &flags);
if (!gpio_is_valid(gpio)) {
dev_err(dev, "invalid gpio #%d: %d\n", i, gpio);
+ ret = gpio;
goto err_loop;
}
prop = of_get_property(np, "mode", NULL);
if (prop && !strcmp(prop, "cpu-qe"))
- pdata->qe_mode = 1;
+ pdata->flags = SPI_QE_CPU_MODE;
+ else if (prop && !strcmp(prop, "qe"))
+ pdata->flags = SPI_CPM_MODE | SPI_QE;
+ else if (of_device_is_compatible(np, "fsl,cpm2-spi"))
+ pdata->flags = SPI_CPM_MODE | SPI_CPM2;
+ else if (of_device_is_compatible(np, "fsl,cpm1-spi"))
+ pdata->flags = SPI_CPM_MODE | SPI_CPM1;
ret = of_mpc8xxx_spi_get_chipselects(dev);
if (ret)
MODULE_ALIAS("platform:mpc8xxx_spi");
static struct platform_driver mpc8xxx_spi_driver = {
.probe = plat_mpc8xxx_spi_probe,
- .remove = __exit_p(plat_mpc8xxx_spi_remove),
+ .remove = __devexit_p(plat_mpc8xxx_spi_remove),
.driver = {
.name = "mpc8xxx_spi",
.owner = THIS_MODULE,