Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@home.transmeta.com>2002-09-30 05:34:45 -0700
committerLinus Torvalds <torvalds@home.transmeta.com>2002-09-30 05:34:45 -0700
commit2b9fa51a14b2c4e41b8abecb134d997c1eae5a02 (patch)
treef15f538a78a4b5e8499fbaec0898de9985aeb6c8
parentfd0a1c61869aa279d6a8c484a3f6cda1e13a57ef (diff)
parent5dd171035db04c910d66819d0522e3dedacc3ffa (diff)
Merge http://linux-scsi.bkbits.net/scsi-for-linus-2.5
into home.transmeta.com:/home/torvalds/v2.5/linux
-rw-r--r--CREDITS2
-rw-r--r--Documentation/Changes5
-rw-r--r--Documentation/DocBook/sis900.tmpl6
-rw-r--r--Documentation/filesystems/isofs.txt7
-rw-r--r--Documentation/kernel-docs.txt6
-rw-r--r--Documentation/networking/00-INDEX4
-rw-r--r--Documentation/networking/ip-sysctl.txt10
-rw-r--r--Documentation/s390/Debugging390.txt2
-rw-r--r--Documentation/scsi-generic.txt4
-rw-r--r--Documentation/scsi.txt2
-rw-r--r--Documentation/sound/oss/PAS162
-rw-r--r--MAINTAINERS32
-rw-r--r--arch/arm/config.in10
-rw-r--r--arch/arm/kernel/compat.c5
-rw-r--r--arch/arm/kernel/irq.c18
-rw-r--r--arch/arm/mach-sa1100/adsbitsy.c3
-rw-r--r--arch/arm/mach-sa1100/badge4.c3
-rw-r--r--arch/arm/mach-sa1100/cpu-sa1100.c86
-rw-r--r--arch/arm/mach-sa1100/cpu-sa1110.c50
-rw-r--r--arch/arm/mach-sa1100/generic.c18
-rw-r--r--arch/arm/mach-sa1100/generic.h6
-rw-r--r--arch/arm/mach-sa1100/graphicsmaster.c3
-rw-r--r--arch/arm/mach-sa1100/h3600.c793
-rw-r--r--arch/arm/mach-sa1100/jornada720.c7
-rw-r--r--arch/arm/mach-sa1100/neponset.c58
-rw-r--r--arch/arm/mach-sa1100/pfs168.c3
-rw-r--r--arch/arm/mach-sa1100/pm.c21
-rw-r--r--arch/arm/mach-sa1100/sa1111.c728
-rw-r--r--arch/arm/mach-sa1100/sa1111.h20
-rw-r--r--arch/arm/mach-sa1100/stork.c13
-rw-r--r--arch/arm/mach-sa1100/system3.c3
-rw-r--r--arch/arm/mm/fault-common.c4
-rw-r--r--arch/arm/tools/mach-types30
-rw-r--r--arch/mips/kernel/time.c2
-rw-r--r--drivers/base/hotplug.c40
-rw-r--r--drivers/char/toshiba.c9
-rw-r--r--drivers/ide/Config.help2
-rw-r--r--drivers/input/serio/sa1111ps2.c275
-rw-r--r--drivers/mtd/nand/nand_ecc.c2
-rw-r--r--drivers/net/3c505.c2
-rw-r--r--drivers/net/3c509.c8
-rw-r--r--drivers/net/arcnet/arcnet.c4
-rw-r--r--drivers/net/at1700.c2
-rw-r--r--drivers/net/hamradio/scc.c2
-rw-r--r--drivers/net/ni65.c2
-rw-r--r--drivers/net/pcmcia/aironet4500_cs.c2
-rw-r--r--drivers/net/skfp/skfddi.c1
-rw-r--r--drivers/net/tc35815.c2
-rw-r--r--drivers/net/tokenring/olympic.c2
-rw-r--r--drivers/net/wan/lmc/lmc_var.h2
-rw-r--r--drivers/pci/quirks.c2
-rw-r--r--drivers/pcmcia/Config.in1
-rw-r--r--drivers/pcmcia/Makefile20
-rw-r--r--drivers/pcmcia/sa1100_adsbitsy.c1
-rw-r--r--drivers/pcmcia/sa1100_badge4.c1
-rw-r--r--drivers/pcmcia/sa1100_generic.c123
-rw-r--r--drivers/pcmcia/sa1100_graphicsmaster.c1
-rw-r--r--drivers/pcmcia/sa1100_jornada720.c1
-rw-r--r--drivers/pcmcia/sa1100_neponset.c68
-rw-r--r--drivers/pcmcia/sa1100_pfs168.c3
-rw-r--r--drivers/pcmcia/sa1100_system3.c1
-rw-r--r--drivers/pcmcia/sa1100_xp860.c1
-rw-r--r--drivers/pcmcia/sa1111_generic.c162
-rw-r--r--drivers/tc/lk201-map.map4
-rw-r--r--drivers/tc/lk201-remap.c8
-rw-r--r--drivers/tc/zs.h4
-rw-r--r--drivers/usb/class/bluetty.c4
-rw-r--r--drivers/usb/class/cdc-acm.c3
-rw-r--r--drivers/usb/core/Makefile2
-rw-r--r--drivers/usb/core/devio.c36
-rw-r--r--drivers/usb/core/driverfs.c177
-rw-r--r--drivers/usb/core/hcd.c24
-rw-r--r--drivers/usb/core/hub.c7
-rw-r--r--drivers/usb/core/message.c327
-rw-r--r--drivers/usb/core/urb.c31
-rw-r--r--drivers/usb/core/usb.c110
-rw-r--r--drivers/usb/core/usb.h5
-rw-r--r--drivers/usb/host/ehci-hcd.c2
-rw-r--r--drivers/usb/host/ehci-q.c47
-rw-r--r--drivers/usb/host/hc_sl811.c3
-rw-r--r--drivers/usb/host/ohci-hcd.c6
-rw-r--r--drivers/usb/host/ohci-mem.c8
-rw-r--r--drivers/usb/host/ohci-q.c5
-rw-r--r--drivers/usb/host/ohci-sa1111.c136
-rw-r--r--drivers/usb/serial/cyberjack.c14
-rw-r--r--drivers/usb/serial/empeg.c6
-rw-r--r--drivers/usb/serial/ftdi_sio.c4
-rw-r--r--drivers/usb/serial/ipaq.c6
-rw-r--r--drivers/usb/serial/ir-usb.c5
-rw-r--r--drivers/usb/serial/keyspan.c6
-rw-r--r--drivers/usb/serial/kl5kusb105.c5
-rw-r--r--drivers/usb/serial/mct_u232.c3
-rw-r--r--drivers/usb/serial/omninet.c5
-rw-r--r--drivers/usb/serial/pl2303.c5
-rw-r--r--drivers/usb/serial/usbserial.c5
-rw-r--r--drivers/usb/serial/visor.c11
-rw-r--r--drivers/usb/serial/visor.h1
-rw-r--r--drivers/usb/serial/whiteheat.c5
-rw-r--r--drivers/usb/storage/transport.c2
-rw-r--r--drivers/video/sa1100fb.c1061
-rw-r--r--drivers/video/sa1100fb.h3
-rw-r--r--fs/devfs/base.c1
-rw-r--r--fs/driverfs/inode.c1
-rw-r--r--fs/jfs/jfs_logmgr.c2
-rw-r--r--fs/nls/nls_cp1250.c2
-rw-r--r--include/asm-arm/arch-sa1100/h3600.h104
-rw-r--r--include/asm-arm/arch-sa1100/irqs.h26
-rw-r--r--include/asm-arm/hardware/sa1111.h232
-rw-r--r--include/asm-arm/pci.h8
-rw-r--r--include/linux/auto_fs.h2
-rw-r--r--include/linux/module.h1
-rw-r--r--include/linux/usb.h77
-rw-r--r--include/linux/usbdevice_fs.h2
113 files changed, 3242 insertions, 2020 deletions
diff --git a/CREDITS b/CREDITS
index 8bb3ce976019..227adee1bfca 100644
--- a/CREDITS
+++ b/CREDITS
@@ -39,7 +39,7 @@ S: Ireland
N: Tigran A. Aivazian
E: tigran@veritas.com
-W: http://www.ocston.org/~tigran
+W: http://www.moses.uklinux.net/patches
D: BFS filesystem
D: Intel IA32 CPU microcode update support
D: Various kernel patches
diff --git a/Documentation/Changes b/Documentation/Changes
index 378c5cc7675c..9efd9ac3b3f8 100644
--- a/Documentation/Changes
+++ b/Documentation/Changes
@@ -55,7 +55,7 @@ o util-linux 2.10o # fdformat --version
o modutils 2.4.2 # insmod -V
o e2fsprogs 1.25 # tune2fs
o jfsutils 1.0.14 # fsck.jfs -V
-o reiserfsprogs 3.x.1b # reiserfsck 2>&1|grep reiserfsprogs
+o reiserfsprogs 3.6.3 # reiserfsck -V 2>&1|grep reiserfsprogs
o xfsprogs 2.1.0 # xfs_db -V
o pcmcia-cs 3.1.21 # cardmgr -V
o PPP 2.4.0 # pppd --version
@@ -229,7 +229,6 @@ If you are running v0.1.17 or earlier, you should upgrade to
version v0.99.0 or higher. Running old versions may cause problems
with programs using shared memory.
-
Networking
==========
@@ -326,7 +325,7 @@ o <http://oss.software.ibm.com/jfs>
Reiserfsprogs
-------------
-o <ftp://ftp.namesys.com/pub/reiserfsprogs/reiserfsprogs-3.x.1b.tar.gz>
+o <http://www.namesys.com/pub/reiserfsprogs/reiserfsprogs-3.6.3.tar.gz>
Xfsprogs
--------
diff --git a/Documentation/DocBook/sis900.tmpl b/Documentation/DocBook/sis900.tmpl
index 88c8ff6a3d06..f3912413b52c 100644
--- a/Documentation/DocBook/sis900.tmpl
+++ b/Documentation/DocBook/sis900.tmpl
@@ -323,8 +323,8 @@ and its mirrors.
The 1.06 revision can be found in kernel version later than 2.3.15 and pre-2.2.14,
and 1.07 revision can be found in kernel version 2.4.0.
If you have no prior experience in networking under Linux, please read
-<ULink URL="http://www.linuxdoc.org/">Ethernet HOWTO</ULink> and
-<ULink URL="http://www.linuxdoc.org/">Networking HOWTO</ULink> available from
+<ULink URL="http://www.tldp.org/">Ethernet HOWTO</ULink> and
+<ULink URL="http://www.tldp.org/">Networking HOWTO</ULink> available from
Linux Documentation Project (LDP).
</Para>
@@ -435,7 +435,7 @@ netmask respectively. TYPE is used to set medium type used by the device.
Typical values are "10baseT"(twisted-pair 10Mbps Ethernet) or "100baseT"
(twisted-pair 100Mbps Ethernet). For more information on how to configure
network interface, please refer to
-<ULink URL="http://www.linuxdoc.org/">Networking HOWTO</ULink>.
+<ULink URL="http://www.tldp.org/">Networking HOWTO</ULink>.
</Para>
<Para>
diff --git a/Documentation/filesystems/isofs.txt b/Documentation/filesystems/isofs.txt
index 28dced255ced..f64a10506689 100644
--- a/Documentation/filesystems/isofs.txt
+++ b/Documentation/filesystems/isofs.txt
@@ -29,3 +29,10 @@ Mount options unique to the isofs filesystem.
unhide Show hidden files.
session=x Select number of session on multisession CD
sbsector=xxx Session begins from sector xxx
+
+Recommended documents about ISO 9660 standard are located at:
+http://www.y-adagio.com/public/standards/iso_cdromr/tocont.htm
+ftp://ftp.ecma.ch/ecma-st/Ecma-119.pdf
+Quoting from the PDF "This 2nd Edition of Standard ECMA-119 is technically
+identical with ISO 9660.", so it is a valid and gratis substitute of the
+official ISO specification.
diff --git a/Documentation/kernel-docs.txt b/Documentation/kernel-docs.txt
index a635573b8055..95f692f08263 100644
--- a/Documentation/kernel-docs.txt
+++ b/Documentation/kernel-docs.txt
@@ -41,7 +41,7 @@
* Title: "The Linux Kernel"
Author: David A. Rusling.
- URL: http://www.linuxdoc.org/LDP/tlk/tlk.html
+ URL: http://www.tldp.org/LDP/tlk/tlk.html
Keywords: everything!, book.
Description: On line, 200 pages book describing most aspects of
the Linux Kernel. Probably, the first reference for beginners.
@@ -57,7 +57,7 @@
* Title: "The Linux Kernel Hackers' Guide"
Author: Michael K.Johnson and others.
- URL: http://www.linuxdoc.org/LDP/khg/HyperNews/get/khg.html
+ URL: http://www.tldp.org/LDP/khg/HyperNews/get/khg.html
Keywords: everything!
Description: No more Postscript book-like version. Only HTML now.
Many people have contributed. The interface is similar to web
@@ -277,7 +277,7 @@
* Title: "Linux Kernel Module Programming Guide"
Author: Ori Pomerantz.
- URL: http://www.linuxdoc.org/LDP/lkmpg/mpg.html
+ URL: http://www.tldp.org/LDP/lkmpg/mpg.html
Keywords: modules, GPL book, /proc, ioctls, system calls,
interrupt handlers .
Description: Very nice 92 pages GPL book on the topic of modules
diff --git a/Documentation/networking/00-INDEX b/Documentation/networking/00-INDEX
index 8a4d41b0b2c5..3105a937ec77 100644
--- a/Documentation/networking/00-INDEX
+++ b/Documentation/networking/00-INDEX
@@ -44,6 +44,10 @@ dgrs.txt
- the Digi International RightSwitch SE-X Ethernet driver
dmfe.txt
- info on the Davicom DM9102(A)/DM9132/DM9801 fast ethernet driver.
+e100.txt
+ - info on Intel's EtherExpress PRO/100 line of 10/100 boards
+e1000.txt
+ - info on Intel's E1000 line of gigabit ethernet boards
eql.txt
- serial IP load balancing
ethertap.txt
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index b87325fadb9a..e7722f6785f0 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -89,7 +89,7 @@ tcp_keepalive_intvl - INTEGER
tcp_retries1 - INTEGER
How many times to retry before deciding that something is wrong
- and it is necessary to report this suspection to network layer.
+ and it is necessary to report this suspicion to network layer.
Minimal RFC value is 3, it is default, which corresponds
to ~3sec-8min depending on RTO.
@@ -200,7 +200,7 @@ tcp_sack - BOOLEAN
Enable select acknowledgments (SACKS).
tcp_fack - BOOLEAN
- Enable FACK congestion avoidance and fast restransmission.
+ Enable FACK congestion avoidance and fast retransmission.
The value is not used, if tcp_sack is not enabled.
tcp_dsack - BOOLEAN
@@ -256,7 +256,7 @@ tcp_mem - vector of 3 INTEGERs: min, pressure, max
pressure: when amount of memory allocated by TCP exceeds this number
of pages, TCP moderates its memory consumption and enters memory
- pressure mode, which is exited when memory consumtion falls
+ pressure mode, which is exited when memory consumption falls
under "low".
high: number of pages allowed for queueing by all TCP sockets.
@@ -278,7 +278,7 @@ tcp_adv_win_scale - INTEGER
tcp_rfc1337 - BOOLEAN
If set, the TCP stack behaves conforming to RFC1337. If unset,
we are not conforming to RFC, but prevent TCP TIME_WAIT
- asassination.
+ assassination.
Default: 0
ip_local_port_range - 2 INTEGERS
@@ -295,7 +295,7 @@ ip_local_port_range - 2 INTEGERS
2000 connections per second to systems supporting timestamps.
ip_nonlocal_bind - BOOLEAN
- If set, allows processes to bind() to non-local IP adresses,
+ If set, allows processes to bind() to non-local IP addresses,
which can be quite useful - but may break some applications.
Default: 0
diff --git a/Documentation/s390/Debugging390.txt b/Documentation/s390/Debugging390.txt
index ffc6ac42ad87..63c373af4485 100644
--- a/Documentation/s390/Debugging390.txt
+++ b/Documentation/s390/Debugging390.txt
@@ -238,7 +238,7 @@ they go to 64 Bit.
On 390 our limitations & strengths make us slightly different.
For backward compatibility ( because of the psw address hi bit which
-indicates whether we are in 31 or 24 bit mode ) we are only allowed
+indicates whether we are in 31 or 64 bit mode ) we are only allowed
use 31 bits (2GB) of our 32 bit addresses. However,
we use entirely separate address spaces for the user & kernel.
diff --git a/Documentation/scsi-generic.txt b/Documentation/scsi-generic.txt
index 88da90139d90..c38e2b3648e4 100644
--- a/Documentation/scsi-generic.txt
+++ b/Documentation/scsi-generic.txt
@@ -30,7 +30,7 @@ Sg driver documentation
=======================
The most recent documentation of the sg driver is kept at the Linux
Documentation Project's (LDP) site:
-http://www.linuxdoc.org/HOWTO/SCSI-Generic-HOWTO
+http://www.tldp.org/HOWTO/SCSI-Generic-HOWTO
This describes the sg version 3 driver found in the lk 2.4 series.
The LDP renders documents in single and multiple page HTML, postscript
and pdf. This document can also be found at:
@@ -51,7 +51,7 @@ in /usr/include/scsi/sg.h . Driver debugging information and other notes
can be found at the top of the /usr/src/linux/drivers/scsi/sg.c file.
A more general description of the Linux SCSI subsystem of which sg is a
-part can be found at http://www.linuxdoc.org/HOWTO/SCSI-2.4-HOWTO .
+part can be found at http://www.tldp.org/HOWTO/SCSI-2.4-HOWTO .
Example code and utilities
diff --git a/Documentation/scsi.txt b/Documentation/scsi.txt
index 934fe73e788a..dd1bbf4e98e3 100644
--- a/Documentation/scsi.txt
+++ b/Documentation/scsi.txt
@@ -2,7 +2,7 @@ SCSI subsystem documentation
============================
The Linux Documentation Project (LDP) maintains a document describing
the SCSI subsystem in the Linux kernel (lk) 2.4 series. See:
-http://www.linuxdoc.org/HOWTO/SCSI-2.4-HOWTO . The LDP has single
+http://www.tldp.org/HOWTO/SCSI-2.4-HOWTO . The LDP has single
and multiple page HTML renderings as well as postscript and pdf.
It can also be found at http://www.torque.net/scsi/SCSI-2.4-HOWTO .
diff --git a/Documentation/sound/oss/PAS16 b/Documentation/sound/oss/PAS16
index fc0b6fe0716a..7a42ad7b6690 100644
--- a/Documentation/sound/oss/PAS16
+++ b/Documentation/sound/oss/PAS16
@@ -71,7 +71,7 @@ CONFIG_SOUND
interrupt and DMA channel), because you will be asked for it.
You want to read the Sound-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto . General information
+ http://www.tldp.org/docs.html#howto . General information
about the modular sound system is contained in the files
Documentation/sound/Introduction. The file
Documentation/sound/README.OSS contains some slightly outdated but
diff --git a/MAINTAINERS b/MAINTAINERS
index 3f529b4b14d1..3a9119b564ae 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -552,7 +552,7 @@ S: Maintained
EMU10K1 SOUND DRIVER
P: Rui Sousa
M: rui.p.m.sousa@clix.pt
-L: emu10k1-devel@opensource.creative.com
+L: emu10k1-devel@lists.sourceforge.net
W: http://opensource.creative.com/
S: Maintained
@@ -575,14 +575,12 @@ M: miku@iki.fi
S: Maintained
EXT2 FILE SYSTEM
-P: Remy Card
-M: Remy.Card@linux.org
-L: linux-kernel@vger.kernel.org
+L: ext2-devel@lists.sourceforge.net
S: Maintained
EXT3 FILE SYSTEM
-P: Remy Card, Stephen Tweedie
-M: sct@redhat.com, akpm@zip.com.au, adilger@turbolinux.com
+P: Stephen Tweedie, Andrew Morton
+M: sct@redhat.com, akpm@zip.com.au, adilger@clusterfs.com
L: ext3-users@redhat.com
S: Maintained
@@ -708,7 +706,7 @@ S: Maintained
i386 BOOT CODE
P: Riley H. Williams
-M: rhw@memalpha.cx
+M: Riley@Williams.Name
L: Linux-Kernel@vger.kernel.org
S: Maintained
@@ -739,9 +737,9 @@ W: http://www.uni-mainz.de/~langm000/linux.html
S: Maintained
IBM ServeRAID RAID DRIVER
-P: Jack Hammer
+P: Jack Hammer
P: Dave Jeffrey
-M: ipslinux@us.ibm.com
+M: ipslinux@adaptec.com
W: http://www.developer.ibm.com/welcome/netfinity/serveraid.html
S: Supported
@@ -839,7 +837,7 @@ S: Maintained
IOC3 DRIVER
P: Ralf Baechle
M: ralf@oss.sgi.com
-L: linux-mips@oss.sgi.com
+L: linux-mips@linux-mips.org
S: Maintained
IP MASQUERADING:
@@ -1052,7 +1050,7 @@ MIPS
P: Ralf Baechle
M: ralf@gnu.org
W: http://oss.sgi.com/mips/mips-howto.html
-L: linux-mips@oss.sgi.com
+L: linux-mips@linux-mips.org
S: Maintained
MISCELLANEOUS MCA-SUPPORT
@@ -1084,8 +1082,8 @@ S: Maintained
NATSEMI ETHERNET DRIVER (DP8381x)
P: Tim Hockin
-M: thockin@hockin.org
-S: Maintained
+M: thockin@hockin.org
+S: Maintained
NCP FILESYSTEM
P: Petr Vandrovec
@@ -1333,10 +1331,10 @@ W: http://www.alarsen.net/linux/qnx4fs/
S: Maintained
RADEON FRAMEBUFFER DISPLAY DRIVER
-P: Ani Joshi
-M: ajoshi@shell.unixbox.com
-L: linux-fbdev-devel@lists.sourceforge.net
-S: Maintained
+P: Ani Joshi
+M: ajoshi@shell.unixbox.com
+L: linux-fbdev-devel@lists.sourceforge.net
+S: Maintained
RAGE128 FRAMEBUFFER DISPLAY DRIVER
P: Ani Joshi
diff --git a/arch/arm/config.in b/arch/arm/config.in
index 1aae024f83f0..635874b18bfc 100644
--- a/arch/arm/config.in
+++ b/arch/arm/config.in
@@ -335,6 +335,16 @@ hex 'Compressed ROM boot loader BSS address' CONFIG_ZBOOT_ROM_BSS 0
if [ "$CONFIG_ARCH_SA1100" = "y" -o \
"$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
dep_bool 'Support CPU clock change (EXPERIMENTAL)' CONFIG_CPU_FREQ $CONFIG_EXPERIMENTAL
+else
+ define_bool CONFIG_CPU_FREQ n
+fi
+
+if [ "$CONFIG_CPU_FREQ" = "y" ]; then
+ define_bool CONFIG_CPU_FREQ_24_API y
+ define_bool CONFIG_CPU_FREQ_26_API y
+else
+ define_bool CONFIG_CPU_FREQ_24_API n
+ define_bool CONFIG_CPU_FREQ_26_API n
fi
source drivers/pci/Config.in
diff --git a/arch/arm/kernel/compat.c b/arch/arm/kernel/compat.c
index 8fd9632d0c08..7195add42e74 100644
--- a/arch/arm/kernel/compat.c
+++ b/arch/arm/kernel/compat.c
@@ -95,13 +95,14 @@ static void __init build_tag_list(struct param_struct *params, void *taglist)
{
struct tag *tag = taglist;
- printk(KERN_DEBUG "Converting old-style param struct to taglist\n");
-
if (params->u1.s.page_size != PAGE_SIZE) {
printk(KERN_WARNING "Warning: bad configuration page, "
"trying to continue\n");
return;
}
+
+ printk(KERN_DEBUG "Converting old-style param struct to taglist\n");
+
#ifdef CONFIG_ARCH_NETWINDER
if (params->u1.s.nr_pages != 0x02000 &&
params->u1.s.nr_pages != 0x04000 &&
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index 73a253c6fe6e..399d81bf412a 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -569,7 +569,7 @@ int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *)
* On a shared IRQ the caller must ensure the interrupt is disabled
* on the card it drives before calling this function.
*
- * This function may be called from interrupt context.
+ * This function must not be called from interrupt context.
*/
void free_irq(unsigned int irq, void *dev_id)
{
@@ -591,15 +591,19 @@ void free_irq(unsigned int irq, void *dev_id)
/* Found it - now free it */
*p = action->next;
- kfree(action);
- goto out;
+ break;
}
- printk(KERN_ERR "Trying to free free IRQ%d\n",irq);
+ spin_unlock_irqrestore(&irq_controller_lock, flags);
+
+ if (!action) {
+ printk(KERN_ERR "Trying to free free IRQ%d\n",irq);
#ifdef CONFIG_DEBUG_ERRORS
- __backtrace();
+ __backtrace();
#endif
-out:
- spin_unlock_irqrestore(&irq_controller_lock, flags);
+ } else {
+ synchronize_irq(irq);
+ kfree(action);
+ }
}
/* Start the interrupt probing. Unlike other architectures,
diff --git a/arch/arm/mach-sa1100/adsbitsy.c b/arch/arm/mach-sa1100/adsbitsy.c
index b0c97a9b7b8e..d5eb9b677449 100644
--- a/arch/arm/mach-sa1100/adsbitsy.c
+++ b/arch/arm/mach-sa1100/adsbitsy.c
@@ -28,7 +28,6 @@
#include <asm/mach/serial_sa1100.h>
#include "generic.h"
-#include "sa1111.h"
static int __init adsbitsy_init(void)
{
@@ -53,7 +52,7 @@ static int __init adsbitsy_init(void)
/*
* Probe for SA1111.
*/
- ret = sa1111_init(NULL, 0x18000000, IRQ_GPIO0);
+ ret = sa1111_init(0x18000000, IRQ_GPIO0);
if (ret < 0)
return ret;
diff --git a/arch/arm/mach-sa1100/badge4.c b/arch/arm/mach-sa1100/badge4.c
index aace82ac1870..6136ee54c473 100644
--- a/arch/arm/mach-sa1100/badge4.c
+++ b/arch/arm/mach-sa1100/badge4.c
@@ -32,7 +32,6 @@
#include <asm/mach/serial_sa1100.h>
#include "generic.h"
-#include "sa1111.h"
static int __init badge4_sa1111_init(void)
{
@@ -45,7 +44,7 @@ static int __init badge4_sa1111_init(void)
/*
* Probe for SA1111.
*/
- return sa1111_init(NULL, BADGE4_SA1111_BASE, BADGE4_IRQ_GPIO_SA1111);
+ return sa1111_init(BADGE4_SA1111_BASE, BADGE4_IRQ_GPIO_SA1111);
}
static int __init badge4_init(void)
diff --git a/arch/arm/mach-sa1100/cpu-sa1100.c b/arch/arm/mach-sa1100/cpu-sa1100.c
index e587cf543608..64295a0fbe56 100644
--- a/arch/arm/mach-sa1100/cpu-sa1100.c
+++ b/arch/arm/mach-sa1100/cpu-sa1100.c
@@ -90,9 +90,7 @@
#include <asm/hardware.h>
-extern unsigned int sa11x0_freq_to_ppcr(unsigned int khz);
-extern unsigned int sa11x0_validatespeed(unsigned int cpu, unsigned int khz);
-extern unsigned int sa11x0_getspeed(void);
+#include "generic.h"
typedef struct {
int speed;
@@ -107,7 +105,7 @@ typedef struct {
static sa1100_dram_regs_t sa1100_dram_settings[] =
{
- /* { mdcnfg, mdcas0, mdcas1, mdcas2 } */ /* clock frequency */
+ /* speed, mdcnfg, mdcas0, mdcas1, mdcas2 clock frequency */
{ 59000, 0x00dc88a3, 0xcccccccf, 0xfffffffc, 0xffffffff }, /* 59.0 MHz */
{ 73700, 0x011490a3, 0xcccccccf, 0xfffffffc, 0xffffffff }, /* 73.7 MHz */
{ 88500, 0x014e90a3, 0xcccccccf, 0xfffffffc, 0xffffffff }, /* 88.5 MHz */
@@ -127,28 +125,25 @@ static sa1100_dram_regs_t sa1100_dram_settings[] =
{ 0, 0, 0, 0, 0 } /* last entry */
};
-
-
-
static void sa1100_update_dram_timings(int current_speed, int new_speed)
{
sa1100_dram_regs_t *settings = sa1100_dram_settings;
/* find speed */
- while(settings->speed != 0) {
+ while (settings->speed != 0) {
if(new_speed == settings->speed)
break;
settings++;
}
- if(settings->speed == 0) {
+ if (settings->speed == 0) {
panic("%s: couldn't find dram setting for speed %d\n",
__FUNCTION__, new_speed);
}
/* No risk, no fun: run with interrupts on! */
- if(new_speed > current_speed) {
+ if (new_speed > current_speed) {
/* We're going FASTER, so first relax the memory
* timings before changing the core frequency
*/
@@ -181,60 +176,39 @@ static void sa1100_update_dram_timings(int current_speed, int new_speed)
}
}
-
-
-
-static int sa1100_dram_notifier(struct notifier_block *nb,
- unsigned long val, void *data)
+static void sa1100_setspeed(struct cpufreq_policy *policy)
{
- struct cpufreq_freqs *ci = data;
-
- switch(val) {
- case CPUFREQ_MINMAX:
- cpufreq_updateminmax(data, sa1100_dram_settings->speed, -1);
- break;
+ unsigned int cur = sa11x0_getspeed();
+ struct cpufreq_freqs freqs;
- case CPUFREQ_PRECHANGE:
- if(ci->new > ci->cur)
- sa1100_update_dram_timings(ci->cur, ci->new);
- break;
+ freqs.old = cur;
+ freqs.new = policy->max;
+ freqs.cpu = CPUFREQ_ALL_CPUS;
- case CPUFREQ_POSTCHANGE:
- if(ci->new < ci->cur)
- sa1100_update_dram_timings(ci->cur, ci->new);
- break;
-
- default:
- printk(KERN_INFO "%s: ignoring unknown notifier type (%ld)\n",
- __FUNCTION__, val);
- }
-
- return 0;
-}
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+ if (policy->max > cur)
+ sa1100_update_dram_timings(cur, policy->max);
+ PPCR = sa11x0_freq_to_ppcr(policy->max);
+ if (policy->max < cur)
+ sa1100_update_dram_timings(cur, policy->max);
-static struct notifier_block sa1100_dram_block = {
- .notifier_call = sa1100_dram_notifier,
-};
-
-
-static void sa1100_setspeed(unsigned int cpu, unsigned int khz)
-{
- PPCR = sa11x0_freq_to_ppcr(khz);
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
}
-static struct cpufreq_freqs sa1100_freqs = {
- .min = 59000,
- .max = 287000,
+static struct cpufreq_policy sa1100_policy = {
+ .cpu = 0,
+ .policy = CPUFREQ_POLICY_POWERSAVE,
+ .max_cpu_freq = 287000,
};
static struct cpufreq_driver sa1100_driver = {
- .freq = &sa1100_freqs,
- .validate = sa11x0_validatespeed,
- .setspeed = sa1100_setspeed,
- .sync = 1,
+ .verify = sa11x0_verify_speed,
+ .setpolicy = sa1100_setspeed,
+ .policy = &sa1100_policy,
+ .cpu_min_freq = 59000,
};
static int __init sa1100_dram_init(void)
@@ -242,11 +216,9 @@ static int __init sa1100_dram_init(void)
int ret = -ENODEV;
if ((processor_id & CPU_SA1100_MASK) == CPU_SA1100_ID) {
- ret = cpufreq_register_notifier(&sa1100_dram_block);
- if (ret)
- return ret;
-
- sa1100_freqs.cur = sa11x0_getspeed();
+ sa1100_driver.cpu_curr_freq[0] =
+ sa1100_policy.min =
+ sa1100_policy.max = sa11x0_getspeed();
ret = cpufreq_register(&sa1100_driver);
}
diff --git a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c
index 0a9777f732d0..ee0b097fc2a8 100644
--- a/arch/arm/mach-sa1100/cpu-sa1110.c
+++ b/arch/arm/mach-sa1100/cpu-sa1110.c
@@ -28,11 +28,9 @@
#include <asm/io.h>
#include <asm/system.h>
-#undef DEBUG
+#include "generic.h"
-extern unsigned int sa11x0_freq_to_ppcr(unsigned int khz);
-extern unsigned int sa11x0_validatespeed(unsigned int cpu, unsigned int khz);
-extern unsigned int sa11x0_getspeed(void);
+#undef DEBUG
struct sdram_params {
u_char rows; /* bits */
@@ -214,15 +212,16 @@ sdram_update_refresh(u_int cpu_khz, struct sdram_params *sdram)
* above, we can match for an exact frequency. If we don't find
* an exact match, we will to set the lowest frequency to be safe.
*/
-static void sa1110_setspeed(unsigned int cpu, unsigned int khz)
+static void sa1110_setspeed(struct cpufreq_policy *policy)
{
struct sdram_params *sdram = &sdram_params;
+ struct cpufreq_freqs freqs;
struct sdram_info sd;
unsigned long flags;
unsigned int ppcr, unused;
- ppcr = sa11x0_freq_to_ppcr(khz);
- sdram_calculate_timing(&sd, khz, sdram);
+ ppcr = sa11x0_freq_to_ppcr(policy->max);
+ sdram_calculate_timing(&sd, policy->max, sdram);
#if 0
/*
@@ -230,7 +229,7 @@ static void sa1110_setspeed(unsigned int cpu, unsigned int khz)
* and errata, but they seem to work. Need to get a storage
* scope on to the SDRAM signals to work out why.
*/
- if (khz < 147500) {
+ if (policy->max < 147500) {
sd.mdrefr |= MDREFR_K1DB2;
sd.mdcas[0] = 0xaaaaaa7f;
} else {
@@ -240,6 +239,13 @@ static void sa1110_setspeed(unsigned int cpu, unsigned int khz)
sd.mdcas[1] = 0xaaaaaaaa;
sd.mdcas[2] = 0xaaaaaaaa;
#endif
+
+ freqs.old = sa11x0_getspeed();
+ freqs.new = policy->max;
+ freqs.cpu = CPUFREQ_ALL_CPUS;
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
/*
* The clock could be going away for some time. Set the SDRAMs
* to refresh rapidly (every 64 memory clock cycles). To get
@@ -257,7 +263,7 @@ static void sa1110_setspeed(unsigned int cpu, unsigned int khz)
* the programming.
*/
local_irq_save(flags);
- asm("mcr p15, 0, %0, c10, c4" : : "r" (0));
+ asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (0));
udelay(10);
__asm__ __volatile__("
b 2f
@@ -282,19 +288,22 @@ static void sa1110_setspeed(unsigned int cpu, unsigned int khz)
/*
* Now, return the SDRAM refresh back to normal.
*/
- sdram_update_refresh(khz, sdram);
+ sdram_update_refresh(policy->max, sdram);
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
}
-static struct cpufreq_freqs sa1110_freqs = {
- .min = 59000,
- .max = 287000,
+static struct cpufreq_policy sa1110_policy = {
+ .cpu = 0,
+ .policy = CPUFREQ_POLICY_POWERSAVE,
+ .max_cpu_freq = 287000,
};
static struct cpufreq_driver sa1110_driver = {
- .freq = &sa1110_freqs,
- .validate = sa11x0_validatespeed,
- .setspeed = sa1110_setspeed,
- .sync = 1,
+ .verify = sa11x0_verify_speed,
+ .setpolicy = sa1110_setspeed,
+ .policy = &sa1110_policy,
+ .cpu_min_freq = 59000,
};
static int __init sa1110_clk_init(void)
@@ -318,8 +327,11 @@ static int __init sa1110_clk_init(void)
memcpy(&sdram_params, sdram, sizeof(sdram_params));
- sa1110_freqs.cur = sa11x0_getspeed();
- sa1110_setspeed(0, sa1110_freqs.cur);
+ sa1110_driver.cpu_cur_freq[0] =
+ sa1110_policy.min =
+ sa1110_policy.max = sa11x0_getspeed();
+
+ sa1110_setspeed(&sa1110_policy);
return cpufreq_register(&sa1110_driver);
}
diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c
index ad06a06c84f5..45eae6434f68 100644
--- a/arch/arm/mach-sa1100/generic.c
+++ b/arch/arm/mach-sa1100/generic.c
@@ -55,20 +55,26 @@ unsigned int sa11x0_freq_to_ppcr(unsigned int khz)
khz /= 100;
- for (i = NR_FREQS - 1; i > 0; i--)
- if (cclk_frequency_100khz[i] <= khz)
+ for (i = 0; i < ARRAY_SIZE(cclk_frequency_100khz); i--)
+ if (cclk_frequency_100khz[i] >= khz)
break;
return i;
}
/*
- * Validate the speed in khz. If we can't generate the precise
- * frequency requested, round it down (to be on the safe side).
+ * Validate the policy. We aren't able to do any fancy in-kernel
+ * scaling, so we force min=max, and set the policy to "performance".
+ * If we can't generate the precise frequency requested, round it up.
*/
-unsigned int sa11x0_validatespeed(unsigned int cpu, unsigned int khz)
+void sa11x0_verify_speed(struct cpufreq_policy *policy)
{
- return cclk_frequency_100khz[sa11x0_freq_to_ppcr(khz)] * 100;
+ if (policy->max > policy->max_cpu_freq)
+ policy->max = policy->max_cpu_freq;
+
+ policy->max = cclk_frequency_100khz[sa11x0_freq_to_ppcr(policy->max)] * 100;
+ policy->min = policy->max;
+ policy->policy = CPUFREQ_POLICY_POWERSAVE;
}
unsigned int sa11x0_getspeed(void)
diff --git a/arch/arm/mach-sa1100/generic.h b/arch/arm/mach-sa1100/generic.h
index abb28817b275..6a27b9b7e715 100644
--- a/arch/arm/mach-sa1100/generic.h
+++ b/arch/arm/mach-sa1100/generic.h
@@ -17,3 +17,9 @@ extern void (*sa1100fb_lcd_power)(int on);
extern void sa1110_mb_enable(void);
extern void sa1110_mb_disable(void);
+
+struct cpufreq_policy;
+
+extern unsigned int sa11x0_freq_to_ppcr(unsigned int khz);
+extern void sa11x0_verify_speed(struct cpufreq_policy *policy);
+extern unsigned int sa11x0_getspeed(void);
diff --git a/arch/arm/mach-sa1100/graphicsmaster.c b/arch/arm/mach-sa1100/graphicsmaster.c
index 9600b3e620b5..d3eddf63205e 100644
--- a/arch/arm/mach-sa1100/graphicsmaster.c
+++ b/arch/arm/mach-sa1100/graphicsmaster.c
@@ -25,7 +25,6 @@
#include <asm/mach/serial_sa1100.h>
#include "generic.h"
-#include "sa1111.h"
static int __init graphicsmaster_init(void)
{
@@ -43,7 +42,7 @@ static int __init graphicsmaster_init(void)
/*
* Probe for SA1111.
*/
- ret = sa1111_init(NULL, 0x18000000, ADS_EXT_IRQ(0));
+ ret = sa1111_init(0x18000000, ADS_EXT_IRQ(0));
if (ret < 0)
return ret;
diff --git a/arch/arm/mach-sa1100/h3600.c b/arch/arm/mach-sa1100/h3600.c
index 0881cc01ad25..41e19e37d0c0 100644
--- a/arch/arm/mach-sa1100/h3600.c
+++ b/arch/arm/mach-sa1100/h3600.c
@@ -24,65 +24,171 @@
#include <linux/kernel.h>
#include <linux/tty.h>
#include <linux/sched.h>
+#include <linux/pm.h>
+#include <linux/serial_core.h>
#include <asm/irq.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
#include <asm/setup.h>
+#include <asm/mach/irq.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/serial_sa1100.h>
-#include <linux/serial_core.h>
+
+#include <asm/arch/h3600.h>
+
+#if defined (CONFIG_SA1100_H3600) || defined (CONFIG_SA1100_H3100)
#include <asm/arch/h3600_gpio.h>
+#endif
+
+#ifdef CONFIG_SA1100_H3800
+#include <asm/arch/h3600_asic.h>
+#endif
#include "generic.h"
+struct ipaq_model_ops ipaq_model_ops;
+EXPORT_SYMBOL(ipaq_model_ops);
+
+static void msleep(unsigned int msec)
+{
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout((msec * HZ + 999) / 1000);
+}
+
/*
- * H3600 has extended, write-only memory-mapped GPIO's
- * H3100 has 1/2 extended, write-only GPIO and 1/2 on
- * regular GPIO lines.
- * H3800 has memory-mapped GPIO through ASIC1 & 2
+ * low-level UART features
*/
-#define H3600_EGPIO (*(volatile unsigned int *)H3600_EGPIO_VIRT)
+static void h3600_uart_set_mctrl(struct uart_port *port, u_int mctrl)
+{
+ if (port->mapbase == _Ser3UTCR0) {
+ if (mctrl & TIOCM_RTS)
+ GPCR = GPIO_H3600_COM_RTS;
+ else
+ GPSR = GPIO_H3600_COM_RTS;
+ }
+}
-static unsigned int h3600_egpio;
+static u_int h3600_uart_get_mctrl(struct uart_port *port)
+{
+ u_int ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR;
-/************************* H3100 *************************/
+ if (port->mapbase == _Ser3UTCR0) {
+ int gplr = GPLR;
+ /* DCD and CTS bits are inverted in GPLR by RS232 transceiver */
+ if (gplr & GPIO_H3600_COM_DCD)
+ ret &= ~TIOCM_CD;
+ if (gplr & GPIO_H3600_COM_CTS)
+ ret &= ~TIOCM_CTS;
+ }
-#define H3100_DIRECT_EGPIO (GPIO_H3100_BT_ON \
- | GPIO_H3100_GPIO3 \
- | GPIO_H3100_QMUTE \
- | GPIO_H3100_LCD_3V_ON \
- | GPIO_H3100_AUD_ON \
- | GPIO_H3100_AUD_PWR_ON \
- | GPIO_H3100_IR_ON \
- | GPIO_H3100_IR_FSEL)
+ return ret;
+}
-static void h3100_init_egpio( void )
+static void h3600_uart_pm(struct uart_port *port, u_int state, u_int oldstate)
{
- GPDR |= H3100_DIRECT_EGPIO;
- GPCR = H3100_DIRECT_EGPIO; /* Initially all off */
+ if (port->mapbase == _Ser2UTCR0) { /* TODO: REMOVE THIS */
+ assign_h3600_egpio(IPAQ_EGPIO_IR_ON, !state);
+ } else if (port->mapbase == _Ser3UTCR0) {
+ assign_h3600_egpio(IPAQ_EGPIO_RS232_ON, !state);
+ }
+}
- /* Older bootldrs put GPIO2-9 in alternate mode on the
- assumption that they are used for video */
- GAFR &= ~H3100_DIRECT_EGPIO;
+/*
+ * Enable/Disable wake up events for this serial port.
+ * Obviously, we only support this on the normal COM port.
+ */
+static int h3600_uart_set_wake(struct uart_port *port, u_int enable)
+{
+ int err = -EINVAL;
+
+ if (port->mapbase == _Ser3UTCR0) {
+ if (enable)
+ PWER |= PWER_GPIO23 | PWER_GPIO25; /* DCD and CTS */
+ else
+ PWER &= ~(PWER_GPIO23 | PWER_GPIO25); /* DCD and CTS */
+ err = 0;
+ }
+ return err;
+}
+
+static struct sa1100_port_fns h3600_port_fns __initdata = {
+ .set_mctrl = h3600_uart_set_mctrl,
+ .get_mctrl = h3600_uart_get_mctrl,
+ .pm = h3600_uart_pm,
+ .set_wake = h3600_uart_set_wake,
+};
+
+/*
+ * helper for sa1100fb
+ */
+static void h3xxx_lcd_power(int enable)
+{
+ assign_h3600_egpio(IPAQ_EGPIO_LCD_POWER, enable);
+}
+
+static struct map_desc h3600_io_desc[] __initdata = {
+ /* virtual physical length type */
+ { H3600_BANK_2_VIRT, SA1100_CS2_PHYS, 0x02800000, MT_DEVICE }, /* static memory bank 2 CS#2 */
+ { H3600_BANK_4_VIRT, SA1100_CS4_PHYS, 0x00800000, MT_DEVICE }, /* static memory bank 4 CS#4 */
+ { H3600_EGPIO_VIRT, H3600_EGPIO_PHYS, 0x01000000, MT_DEVICE }, /* EGPIO 0 CS#5 */
+};
+
+/*
+ * Common map_io initialization
+ */
+
+static void __init h3xxx_map_io(void)
+{
+ sa1100_map_io();
+ iotable_init(h3600_io_desc, ARRAY_SIZE(h3600_io_desc));
+
+ sa1100_register_uart_fns(&h3600_port_fns);
+ sa1100_register_uart(0, 3); /* Common serial port */
+// sa1100_register_uart(1, 1); /* Microcontroller on 3100/3600 */
+
+ /* Ensure those pins are outputs and driving low */
+ PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
+ PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
+
+ /* Configure suspend conditions */
+ PGSR = 0;
+ PWER = PWER_GPIO0 | PWER_RTC;
+ PCFR = PCFR_OPDE;
+ PSDR = 0;
+
+ sa1100fb_lcd_power = h3xxx_lcd_power;
+}
- h3600_egpio = EGPIO_H3600_RS232_ON;
- H3600_EGPIO = h3600_egpio;
+static __inline__ void do_blank(int setp)
+{
+ if (ipaq_model_ops.blank_callback)
+ ipaq_model_ops.blank_callback(1-setp);
}
-static void h3100_control_egpio( enum ipaq_egpio_type x, int setp )
+/************************* H3100 *************************/
+
+#ifdef CONFIG_SA1100_H3100
+
+#define H3100_EGPIO (*(volatile unsigned int *)H3600_EGPIO_VIRT)
+static unsigned int h3100_egpio = 0;
+
+static void h3100_control_egpio(enum ipaq_egpio_type x, int setp)
{
unsigned int egpio = 0;
long gpio = 0;
unsigned long flags;
switch (x) {
- case IPAQ_EGPIO_LCD_ON:
+ case IPAQ_EGPIO_LCD_POWER:
egpio |= EGPIO_H3600_LCD_ON;
gpio |= GPIO_H3100_LCD_3V_ON;
+ do_blank(setp);
+ break;
+ case IPAQ_EGPIO_LCD_ENABLE:
break;
case IPAQ_EGPIO_CODEC_NRESET:
egpio |= EGPIO_H3600_CODEC_NRESET;
@@ -120,66 +226,104 @@ static void h3100_control_egpio( enum ipaq_egpio_type x, int setp )
break;
}
- local_irq_save(flags);
- if ( setp ) {
- h3600_egpio |= egpio;
- GPSR = gpio;
- } else {
- h3600_egpio &= ~egpio;
- GPCR = gpio;
- }
- H3600_EGPIO = h3600_egpio;
- local_irq_restore(flags);
-
- /*
- if ( x != IPAQ_EGPIO_VPP_ON ) {
- printk("%s: type=%d (%s) gpio=0x%x (0x%x) egpio=0x%x (0x%x) setp=%d\n",
- __FUNCTION__,
- x, egpio_names[x], GPLR, gpio, h3600_egpio, egpio, setp );
+ if (egpio || gpio) {
+ local_irq_save(flags);
+ if (setp) {
+ h3100_egpio |= egpio;
+ GPSR = gpio;
+ } else {
+ h3100_egpio &= ~egpio;
+ GPCR = gpio;
+ }
+ H3100_EGPIO = h3100_egpio;
+ local_irq_restore(flags);
}
- */
}
-static unsigned long h3100_read_egpio( void )
+static unsigned long h3100_read_egpio(void)
{
- return h3600_egpio;
+ return h3100_egpio;
+}
+
+static int h3100_pm_callback(int req)
+{
+ if (ipaq_model_ops.pm_callback_aux)
+ return ipaq_model_ops.pm_callback_aux(req);
+ return 0;
}
static struct ipaq_model_ops h3100_model_ops __initdata = {
- model : IPAQ_H3100,
- generic_name : "3100",
- initialize : h3100_init_egpio,
- control : h3100_control_egpio,
- read : h3100_read_egpio
+ .generic_name = "3100",
+ .control = h3100_control_egpio,
+ .read = h3100_read_egpio,
+ .pm_callback = h3100_pm_callback
};
+#define H3100_DIRECT_EGPIO (GPIO_H3100_BT_ON \
+ | GPIO_H3100_GPIO3 \
+ | GPIO_H3100_QMUTE \
+ | GPIO_H3100_LCD_3V_ON \
+ | GPIO_H3100_AUD_ON \
+ | GPIO_H3100_AUD_PWR_ON \
+ | GPIO_H3100_IR_ON \
+ | GPIO_H3100_IR_FSEL)
-/************************* H3600 *************************/
-
-static void h3600_init_egpio( void )
+static void __init h3100_map_io(void)
{
- h3600_egpio = EGPIO_H3600_RS232_ON;
- H3600_EGPIO = h3600_egpio;
+ h3xxx_map_io();
+
+ /* Initialize h3100-specific values here */
+ GPCR = 0x0fffffff; /* All outputs are set low by default */
+ GPDR = GPIO_H3600_COM_RTS | GPIO_H3600_L3_CLOCK |
+ GPIO_H3600_L3_MODE | GPIO_H3600_L3_DATA |
+ GPIO_H3600_CLK_SET1 | GPIO_H3600_CLK_SET0 |
+ H3100_DIRECT_EGPIO;
+
+ /* Older bootldrs put GPIO2-9 in alternate mode on the
+ assumption that they are used for video */
+ GAFR &= ~H3100_DIRECT_EGPIO;
+
+ H3100_EGPIO = h3100_egpio;
+ ipaq_model_ops = h3100_model_ops;
}
-static void h3600_control_egpio( enum ipaq_egpio_type x, int setp )
+MACHINE_START(H3100, "Compaq iPAQ H3100")
+ BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
+ BOOT_PARAMS(0xc0000100)
+ MAPIO(h3100_map_io)
+ INITIRQ(sa1100_init_irq)
+MACHINE_END
+
+#endif /* CONFIG_SA1100_H3100 */
+
+/************************* H3600 *************************/
+
+#ifdef CONFIG_SA1100_H3600
+
+#define H3600_EGPIO (*(volatile unsigned int *)H3600_EGPIO_VIRT)
+static unsigned int h3600_egpio = EGPIO_H3600_RS232_ON;
+
+static void h3600_control_egpio(enum ipaq_egpio_type x, int setp)
{
unsigned int egpio = 0;
unsigned long flags;
switch (x) {
- case IPAQ_EGPIO_LCD_ON:
+ case IPAQ_EGPIO_LCD_POWER:
egpio |= EGPIO_H3600_LCD_ON |
EGPIO_H3600_LCD_PCI |
EGPIO_H3600_LCD_5V_ON |
EGPIO_H3600_LVDD_ON;
+ do_blank(setp);
+ break;
+ case IPAQ_EGPIO_LCD_ENABLE:
break;
case IPAQ_EGPIO_CODEC_NRESET:
egpio |= EGPIO_H3600_CODEC_NRESET;
break;
case IPAQ_EGPIO_AUDIO_ON:
egpio |= EGPIO_H3600_AUD_AMP_ON |
- EGPIO_H3600_AUD_PWR_ON;
+ EGPIO_H3600_AUD_PWR_ON;
break;
case IPAQ_EGPIO_QMUTE:
egpio |= EGPIO_H3600_QMUTE;
@@ -210,288 +354,441 @@ static void h3600_control_egpio( enum ipaq_egpio_type x, int setp )
break;
}
- local_irq_save(flags);
- if ( setp )
- h3600_egpio |= egpio;
- else
- h3600_egpio &= ~egpio;
- H3600_EGPIO = h3600_egpio;
- local_irq_restore(flags);
+ if (egpio) {
+ local_irq_save(flags);
+ if (setp)
+ h3600_egpio |= egpio;
+ else
+ h3600_egpio &= ~egpio;
+ H3600_EGPIO = h3600_egpio;
+ local_irq_restore(flags);
+ }
}
-static unsigned long h3600_read_egpio( void )
+static unsigned long h3600_read_egpio(void)
{
return h3600_egpio;
}
+static int h3600_pm_callback(int req)
+{
+ if (ipaq_model_ops.pm_callback_aux)
+ return ipaq_model_ops.pm_callback_aux(req);
+ return 0;
+}
+
static struct ipaq_model_ops h3600_model_ops __initdata = {
- model : IPAQ_H3600,
- generic_name : "3600",
- initialize : h3600_init_egpio,
- control : h3600_control_egpio,
- read : h3600_read_egpio
+ .generic_name = "3600",
+ .control = h3600_control_egpio,
+ .read = h3600_read_egpio,
+ .pm_callback = h3600_pm_callback
};
-/************************* H3800 *************************/
+static void __init h3600_map_io(void)
+{
+ h3xxx_map_io();
-#define ASIC1_OUTPUTS 0x7fff /* First 15 bits are used */
+ /* Initialize h3600-specific values here */
-static unsigned int h3800_asic1_gpio;
-static unsigned int h3800_asic2_gpio;
+ GPCR = 0x0fffffff; /* All outputs are set low by default */
+ GPDR = GPIO_H3600_COM_RTS | GPIO_H3600_L3_CLOCK |
+ GPIO_H3600_L3_MODE | GPIO_H3600_L3_DATA |
+ GPIO_H3600_CLK_SET1 | GPIO_H3600_CLK_SET0 |
+ GPIO_LDD15 | GPIO_LDD14 | GPIO_LDD13 | GPIO_LDD12 |
+ GPIO_LDD11 | GPIO_LDD10 | GPIO_LDD9 | GPIO_LDD8;
-static void h3800_init_egpio(void)
-{
- /* Set up ASIC #1 */
- H3800_ASIC1_GPIO_Direction = ASIC1_OUTPUTS; /* All outputs */
- H3800_ASIC1_GPIO_Mask = ASIC1_OUTPUTS; /* No interrupts */
- H3800_ASIC1_GPIO_SleepMask = ASIC1_OUTPUTS;
- H3800_ASIC1_GPIO_SleepDir = ASIC1_OUTPUTS;
- H3800_ASIC1_GPIO_SleepOut = GPIO_H3800_ASIC1_EAR_ON_N;
- H3800_ASIC1_GPIO_BattFaultDir = ASIC1_OUTPUTS;
- H3800_ASIC1_GPIO_BattFaultOut = GPIO_H3800_ASIC1_EAR_ON_N;
+ H3600_EGPIO = h3600_egpio; /* Maintains across sleep? */
+ ipaq_model_ops = h3600_model_ops;
+}
+
+MACHINE_START(H3600, "Compaq iPAQ H3600")
+ BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
+ BOOT_PARAMS(0xc0000100)
+ MAPIO(h3600_map_io)
+ INITIRQ(sa1100_init_irq)
+MACHINE_END
- h3800_asic1_gpio = GPIO_H3800_ASIC1_IR_ON_N /* TODO: Check IR level */
- | GPIO_H3800_ASIC1_RS232_ON
- | GPIO_H3800_ASIC1_EAR_ON_N;
+#endif /* CONFIG_SA1100_H3600 */
- H3800_ASIC1_GPIO_Out = h3800_asic1_gpio;
+#ifdef CONFIG_SA1100_H3800
- /* Set up ASIC #2 */
- H3800_ASIC2_GPIO_Direction = GPIO_H3800_ASIC2_PEN_IRQ
- | GPIO_H3800_ASIC2_SD_DETECT
- | GPIO_H3800_ASIC2_EAR_IN_N
- | GPIO_H3800_ASIC2_USB_DETECT_N
- | GPIO_H3800_ASIC2_SD_CON_SLT;
+#define SET_ASIC1(x) \
+ do {if (setp) { H3800_ASIC1_GPIO_OUT |= (x); } else { H3800_ASIC1_GPIO_OUT &= ~(x); }} while(0)
- h3800_asic2_gpio = GPIO_H3800_ASIC2_IN_Y1_N | GPIO_H3800_ASIC2_IN_X1_N;
- H3800_ASIC2_GPIO_Data = h3800_asic2_gpio;
- H3800_ASIC2_GPIO_BattFaultOut = h3800_asic2_gpio;
+#define SET_ASIC2(x) \
+ do {if (setp) { H3800_ASIC2_GPIOPIOD |= (x); } else { H3800_ASIC2_GPIOPIOD &= ~(x); }} while(0)
- /* TODO : Set sleep states & battery fault states */
+#define CLEAR_ASIC1(x) \
+ do {if (setp) { H3800_ASIC1_GPIO_OUT &= ~(x); } else { H3800_ASIC1_GPIO_OUT |= (x); }} while(0)
- /* Clear VPP Enable */
- H3800_ASIC1_FlashWP_VPP_ON = 0;
+#define CLEAR_ASIC2(x) \
+ do {if (setp) { H3800_ASIC2_GPIOPIOD &= ~(x); } else { H3800_ASIC2_GPIOPIOD |= (x); }} while(0)
+
+
+/*
+ On screen enable, we get
+
+ h3800_video_power_on(1)
+ LCD controller starts
+ h3800_video_lcd_enable(1)
+
+ On screen disable, we get
+
+ h3800_video_lcd_enable(0)
+ LCD controller stops
+ h3800_video_power_on(0)
+*/
+
+
+static void h3800_video_power_on(int setp)
+{
+ if (setp) {
+ H3800_ASIC1_GPIO_OUT |= GPIO1_LCD_ON;
+ msleep(30);
+ H3800_ASIC1_GPIO_OUT |= GPIO1_VGL_ON;
+ msleep(5);
+ H3800_ASIC1_GPIO_OUT |= GPIO1_VGH_ON;
+ msleep(50);
+ H3800_ASIC1_GPIO_OUT |= GPIO1_LCD_5V_ON;
+ msleep(5);
+ } else {
+ msleep(5);
+ H3800_ASIC1_GPIO_OUT &= ~GPIO1_LCD_5V_ON;
+ msleep(50);
+ H3800_ASIC1_GPIO_OUT &= ~GPIO1_VGL_ON;
+ msleep(5);
+ H3800_ASIC1_GPIO_OUT &= ~GPIO1_VGH_ON;
+ msleep(100);
+ H3800_ASIC1_GPIO_OUT &= ~GPIO1_LCD_ON;
+ }
}
-static void h3800_control_egpio( enum ipaq_egpio_type x, int setp )
+static void h3800_video_lcd_enable(int setp)
{
- unsigned int set_asic1_egpio = 0;
- unsigned int clear_asic1_egpio = 0;
- unsigned long flags;
+ if (setp) {
+ msleep(17); // Wait one from before turning on
+ H3800_ASIC1_GPIO_OUT |= GPIO1_LCD_PCI;
+ } else {
+ H3800_ASIC1_GPIO_OUT &= ~GPIO1_LCD_PCI;
+ msleep(30); // Wait before turning off
+ }
+}
+
+static void h3800_control_egpio(enum ipaq_egpio_type x, int setp)
+{
switch (x) {
- case IPAQ_EGPIO_LCD_ON:
- set_asic1_egpio |= GPIO_H3800_ASIC1_LCD_5V_ON
- | GPIO_H3800_ASIC1_LCD_ON
- | GPIO_H3800_ASIC1_LCD_PCI
- | GPIO_H3800_ASIC1_VGH_ON
- | GPIO_H3800_ASIC1_VGL_ON;
+ case IPAQ_EGPIO_LCD_POWER:
+ h3800_video_power_on(setp);
break;
- case IPAQ_EGPIO_CODEC_NRESET:
+ case IPAQ_EGPIO_LCD_ENABLE:
+ h3800_video_lcd_enable(setp);
break;
+ case IPAQ_EGPIO_CODEC_NRESET:
case IPAQ_EGPIO_AUDIO_ON:
- break;
case IPAQ_EGPIO_QMUTE:
+ printk(__FUNCTION__ ": error - should not be called\n");
break;
case IPAQ_EGPIO_OPT_NVRAM_ON:
+ SET_ASIC2(GPIO2_OPT_ON_NVRAM);
break;
case IPAQ_EGPIO_OPT_ON:
+ SET_ASIC2(GPIO2_OPT_ON);
break;
case IPAQ_EGPIO_CARD_RESET:
+ SET_ASIC2(GPIO2_OPT_PCM_RESET);
break;
case IPAQ_EGPIO_OPT_RESET:
+ SET_ASIC2(GPIO2_OPT_RESET);
break;
case IPAQ_EGPIO_IR_ON:
- clear_asic1_egpio |= GPIO_H3800_ASIC1_IR_ON_N; /* TODO : This is backwards? */
+ CLEAR_ASIC1(GPIO1_IR_ON_N);
break;
case IPAQ_EGPIO_IR_FSEL:
break;
case IPAQ_EGPIO_RS232_ON:
- set_asic1_egpio |= GPIO_H3800_ASIC1_RS232_ON;
+ SET_ASIC1(GPIO1_RS232_ON);
break;
case IPAQ_EGPIO_VPP_ON:
- H3800_ASIC1_FlashWP_VPP_ON = setp;
+ H3800_ASIC2_FlashWP_VPP_ON = setp;
break;
}
+}
- local_irq_save(flags);
- if ( setp ) {
- h3800_asic1_gpio |= set_asic1_egpio;
- h3800_asic1_gpio &= ~clear_asic1_egpio;
- }
- else {
- h3800_asic1_gpio &= ~set_asic1_egpio;
- h3800_asic1_gpio |= clear_asic1_egpio;
- }
- H3800_ASIC1_GPIO_Out = h3800_asic1_gpio;
- local_irq_restore(flags);
+static unsigned long h3800_read_egpio(void)
+{
+ return H3800_ASIC1_GPIO_OUT | (H3800_ASIC2_GPIOPIOD << 16);
}
-static unsigned long h3800_read_egpio( void )
+/* We need to fix ASIC2 GPIO over suspend/resume. At the moment,
+ it doesn't appear that ASIC1 GPIO has the same problem */
+
+static int h3800_pm_callback(int req)
{
- return h3800_asic1_gpio | (h3800_asic2_gpio << 16);
+ static u16 asic1_data;
+ static u16 asic2_data;
+ int result = 0;
+
+ printk(__FUNCTION__ " %d\n", req);
+
+ switch (req) {
+ case PM_RESUME:
+ MSC2 = (MSC2 & 0x0000ffff) | 0xE4510000; /* Set MSC2 correctly */
+
+ H3800_ASIC2_GPIOPIOD = asic2_data;
+ H3800_ASIC2_GPIODIR = GPIO2_PEN_IRQ
+ | GPIO2_SD_DETECT
+ | GPIO2_EAR_IN_N
+ | GPIO2_USB_DETECT_N
+ | GPIO2_SD_CON_SLT;
+
+ H3800_ASIC1_GPIO_OUT = asic1_data;
+
+ if (ipaq_model_ops.pm_callback_aux)
+ result = ipaq_model_ops.pm_callback_aux(req);
+ break;
+
+ case PM_SUSPEND:
+ if (ipaq_model_ops.pm_callback_aux &&
+ ((result = ipaq_model_ops.pm_callback_aux(req)) != 0))
+ return result;
+
+ asic1_data = H3800_ASIC1_GPIO_OUT;
+ asic2_data = H3800_ASIC2_GPIOPIOD;
+ break;
+ default:
+ printk(__FUNCTION__ ": unrecognized PM callback\n");
+ break;
+ }
+ return result;
}
static struct ipaq_model_ops h3800_model_ops __initdata = {
- model : IPAQ_H3800,
- generic_name : "3800",
- initialize : h3800_init_egpio,
- control : h3800_control_egpio,
- read : h3800_read_egpio
+ .generic_name = "3800",
+ .control = h3800_control_egpio,
+ .read = h3800_read_egpio,
+ .pm_callback = h3800_pm_callback
};
+#define MAX_ASIC_ISR_LOOPS 20
+
+/* The order of these is important - see #include <asm/arch/irqs.h> */
+static u32 kpio_irq_mask[] = {
+ KPIO_KEY_ALL,
+ KPIO_SPI_INT,
+ KPIO_OWM_INT,
+ KPIO_ADC_INT,
+ KPIO_UART_0_INT,
+ KPIO_UART_1_INT,
+ KPIO_TIMER_0_INT,
+ KPIO_TIMER_1_INT,
+ KPIO_TIMER_2_INT
+};
+
+static u32 gpio_irq_mask[] = {
+ GPIO2_PEN_IRQ,
+ GPIO2_SD_DETECT,
+ GPIO2_EAR_IN_N,
+ GPIO2_USB_DETECT_N,
+ GPIO2_SD_CON_SLT,
+};
-static void h3600_lcd_power(int on)
+static void h3800_IRQ_demux(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
{
- if (on)
- set_h3600_egpio(IPAQ_EGPIO_LCD_ON);
- else
- clr_h3600_egpio(IPAQ_EGPIO_LCD_ON);
-}
+ int i;
+ if (0) printk(__FUNCTION__ ": interrupt received\n");
-struct ipaq_model_ops ipaq_model_ops;
-EXPORT_SYMBOL(ipaq_model_ops);
+ desc->chip->ack(irq);
-static int __init h3600_init_model_ops(void)
-{
- if (machine_is_h3xxx()) {
- sa1100fb_lcd_power = h3600_lcd_power;
-
- if (machine_is_h3100()) {
- ipaq_model_ops = h3100_model_ops;
- } else if (machine_is_h3600()) {
- ipaq_model_ops = h3600_model_ops;
- } else if (machine_is_h3800()) {
- ipaq_model_ops = h3800_model_ops;
- }
- init_h3600_egpio();
+ for (i = 0; i < MAX_ASIC_ISR_LOOPS && (GPLR & GPIO_H3800_ASIC); i++) {
+ u32 irq;
+ int j;
+
+ /* KPIO */
+ irq = H3800_ASIC2_KPIINTFLAG;
+ if (0) printk(__FUNCTION__" KPIO 0x%08X\n", irq);
+ for (j = 0; j < H3800_KPIO_IRQ_COUNT; j++)
+ if (irq & kpio_irq_mask[j])
+ do_edge_IRQ(H3800_KPIO_IRQ_COUNT + j, irq_desc + H3800_KPIO_IRQ_COUNT + j, regs);
+
+ /* GPIO2 */
+ irq = H3800_ASIC2_GPIINTFLAG;
+ if (0) printk(__FUNCTION__" GPIO 0x%08X\n", irq);
+ for (j = 0; j < H3800_GPIO_IRQ_COUNT; j++)
+ if (irq & gpio_irq_mask[j])
+ do_edge_IRQ(H3800_GPIO_IRQ_COUNT + j, irq_desc + H3800_GPIO_IRQ_COUNT + j , regs);
}
- return 0;
+
+ if (i >= MAX_ASIC_ISR_LOOPS)
+ printk(__FUNCTION__ ": interrupt processing overrun\n");
+
+ /* For level-based interrupts */
+ desc->chip->unmask(irq);
+
}
-__initcall(h3600_init_model_ops);
+static struct irqaction h3800_irq = {
+ .name = "h3800_asic",
+ .handler = h3800_IRQ_demux,
+ .flags = SA_INTERRUPT,
+};
+
+u32 kpio_int_shadow = 0;
-/*
- * low-level UART features
+
+/* mask_ack <- IRQ is first serviced.
+ mask <- IRQ is disabled.
+ unmask <- IRQ is enabled
+
+ The INTCLR registers are poorly documented. I believe that writing
+ a "1" to the register clears the specific interrupt, but the documentation
+ indicates writing a "0" clears the interrupt. In any case, they shouldn't
+ be read (that's the INTFLAG register)
*/
-static void h3600_uart_set_mctrl(struct uart_port *port, u_int mctrl)
+static void h3800_mask_ack_kpio_irq(unsigned int irq)
{
- if (port->mapbase == _Ser3UTCR0) {
- if (mctrl & TIOCM_RTS)
- GPCR = GPIO_H3600_COM_RTS;
- else
- GPSR = GPIO_H3600_COM_RTS;
- }
+ u32 mask = kpio_irq_mask[irq - H3800_KPIO_IRQ_START];
+ kpio_int_shadow &= ~mask;
+ H3800_ASIC2_KPIINTSTAT = kpio_int_shadow;
+ H3800_ASIC2_KPIINTCLR = mask;
}
-static u_int h3600_uart_get_mctrl(struct uart_port *port)
+static void h3800_mask_kpio_irq(unsigned int irq)
{
- u_int ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR;
+ u32 mask = kpio_irq_mask[irq - H3800_KPIO_IRQ_START];
+ kpio_int_shadow &= ~mask;
+ H3800_ASIC2_KPIINTSTAT = kpio_int_shadow;
+}
- if (port->mapbase == _Ser3UTCR0) {
- int gplr = GPLR;
- if (gplr & GPIO_H3600_COM_DCD)
- ret &= ~TIOCM_CD;
- if (gplr & GPIO_H3600_COM_CTS)
- ret &= ~TIOCM_CTS;
- }
+static void h3800_unmask_kpio_irq(unsigned int irq)
+{
+ u32 mask = kpio_irq_mask[irq - H3800_KPIO_IRQ_START];
+ kpio_int_shadow |= mask;
+ H3800_ASIC2_KPIINTSTAT = kpio_int_shadow;
+}
- return ret;
+static void h3800_mask_ack_gpio_irq(unsigned int irq)
+{
+ u32 mask = gpio_irq_mask[irq - H3800_GPIO_IRQ_START];
+ H3800_ASIC2_GPIINTSTAT &= ~mask;
+ H3800_ASIC2_GPIINTCLR = mask;
}
-static void h3600_uart_pm(struct uart_port *port, u_int state, u_int oldstate)
+static void h3800_mask_gpio_irq(unsigned int irq)
{
- if (port->mapbase == _Ser2UTCR0) {
- assign_h3600_egpio( IPAQ_EGPIO_IR_ON, !state );
- } else if (port->mapbase == _Ser3UTCR0) {
- assign_h3600_egpio( IPAQ_EGPIO_RS232_ON, !state );
+ u32 mask = gpio_irq_mask[irq - H3800_GPIO_IRQ_START];
+ H3800_ASIC2_GPIINTSTAT &= ~mask;
}
+
+static void h3800_unmask_gpio_irq(unsigned int irq)
+{
+ u32 mask = gpio_irq_mask[irq - H3800_GPIO_IRQ_START];
+ H3800_ASIC2_GPIINTSTAT |= mask;
}
-/*
- * Enable/Disable wake up events for this serial port.
- * Obviously, we only support this on the normal COM port.
- */
-static int h3600_uart_set_wake(struct uart_port *port, u_int enable)
+static void __init h3800_init_irq(void)
{
- int err = -EINVAL;
+ int i;
- if (port->mapbase == _Ser3UTCR0) {
- if (enable)
- PWER |= PWER_GPIO23 | PWER_GPIO25 ; /* DCD and CTS */
- else
- PWER &= ~(PWER_GPIO23 | PWER_GPIO25); /* DCD and CTS */
- err = 0;
+ /* Initialize standard IRQs */
+ sa1100_init_irq();
+
+ /* Disable all IRQs and set up clock */
+ H3800_ASIC2_KPIINTSTAT = 0; /* Disable all interrupts */
+ H3800_ASIC2_GPIINTSTAT = 0;
+
+ H3800_ASIC2_KPIINTCLR = 0; /* Clear all KPIO interrupts */
+ H3800_ASIC2_GPIINTCLR = 0; /* Clear all GPIO interrupts */
+
+// H3800_ASIC2_KPIINTCLR = 0xffff; /* Clear all KPIO interrupts */
+// H3800_ASIC2_GPIINTCLR = 0xffff; /* Clear all GPIO interrupts */
+
+ H3800_ASIC2_CLOCK_Enable |= ASIC2_CLOCK_EX0; /* 32 kHZ crystal on */
+ H3800_ASIC2_INTR_ClockPrescale |= ASIC2_INTCPS_SET;
+ H3800_ASIC2_INTR_ClockPrescale = ASIC2_INTCPS_CPS(0x0e) | ASIC2_INTCPS_SET;
+ H3800_ASIC2_INTR_TimerSet = 1;
+
+#if 0
+ for (i = 0; i < H3800_KPIO_IRQ_COUNT; i++) {
+ int irq = i + H3800_KPIO_IRQ_START;
+ irq_desc[irq].valid = 1;
+ irq_desc[irq].probe_ok = 1;
+ set_irq_chip(irq, &h3800_kpio_irqchip);
}
- return err;
+
+ for (i = 0; i < H3800_GPIO_IRQ_COUNT; i++) {
+ int irq = i + H3800_GPIO_IRQ_START;
+ irq_desc[irq].valid = 1;
+ irq_desc[irq].probe_ok = 1;
+ set_irq_chip(irq, &h3800_gpio_irqchip);
+ }
+#endif
+ set_irq_type(IRQ_GPIO_H3800_ASIC, IRQT_RISING);
+ set_irq_chained_handler(IRQ_GPIO_H3800_ASIC, &h3800_IRQ_demux);
}
-static struct sa1100_port_fns h3600_port_fns __initdata = {
- .set_mctrl = h3600_uart_set_mctrl,
- .get_mctrl = h3600_uart_get_mctrl,
- .pm = h3600_uart_pm,
- .set_wake = h3600_uart_set_wake,
-};
-static struct map_desc h3600_io_desc[] __initdata = {
- /* virtual physical length type */
- { H3600_EGPIO_VIRT, 0x49000000, 0x01000000, MT_DEVICE }, /* EGPIO 0 CS#5 */
- { H3600_BANK_2_VIRT, 0x10000000, 0x02800000, MT_DEVICE }, /* static memory bank 2 CS#2 */
- { H3600_BANK_4_VIRT, 0x40000000, 0x00800000, MT_DEVICE } /* static memory bank 4 CS#4 */
-};
+#define ASIC1_OUTPUTS 0x7fff /* First 15 bits are used */
-static void __init h3600_map_io(void)
+static void __init h3800_map_io(void)
{
- sa1100_map_io();
- iotable_init(h3600_io_desc, ARRAY_SIZE(h3600_io_desc));
+ h3xxx_map_io();
+
+ /* Add wakeup on AC plug/unplug */
+ PWER |= PWER_GPIO12;
+
+ /* Initialize h3800-specific values here */
+ GPCR = 0x0fffffff; /* All outputs are set low by default */
+ GAFR = GPIO_H3800_CLK_OUT |
+ GPIO_LDD15 | GPIO_LDD14 | GPIO_LDD13 | GPIO_LDD12 |
+ GPIO_LDD11 | GPIO_LDD10 | GPIO_LDD9 | GPIO_LDD8;
+ GPDR = GPIO_H3800_CLK_OUT |
+ GPIO_H3600_COM_RTS | GPIO_H3600_L3_CLOCK |
+ GPIO_H3600_L3_MODE | GPIO_H3600_L3_DATA |
+ GPIO_LDD15 | GPIO_LDD14 | GPIO_LDD13 | GPIO_LDD12 |
+ GPIO_LDD11 | GPIO_LDD10 | GPIO_LDD9 | GPIO_LDD8;
+ TUCR = TUCR_3_6864MHz; /* Seems to be used only for the Bluetooth UART */
+
+ /* Fix the memory bus */
+ MSC2 = (MSC2 & 0x0000ffff) | 0xE4510000;
- sa1100_register_uart_fns(&h3600_port_fns);
- sa1100_register_uart(0, 3);
- sa1100_register_uart(1, 1); /* isn't this one driven elsewhere? */
-
- /*
- * Default GPIO settings. Should be set by machine
- */
- GPCR = 0x0fffffff;
-// GPDR = 0x0401f3fc;
- GPDR = GPIO_H3600_COM_RTS | GPIO_H3600_L3_CLOCK |
- GPIO_H3600_L3_MODE | GPIO_H3600_L3_DATA |
- GPIO_H3600_CLK_SET1 | GPIO_H3600_CLK_SET0 |
- GPIO_LDD15 | GPIO_LDD14 | GPIO_LDD13 | GPIO_LDD12 |
- GPIO_LDD11 | GPIO_LDD10 | GPIO_LDD9 | GPIO_LDD8;
+ /* Set up ASIC #1 */
+ H3800_ASIC1_GPIO_DIR = ASIC1_OUTPUTS; /* All outputs */
+ H3800_ASIC1_GPIO_MASK = ASIC1_OUTPUTS; /* No interrupts */
+ H3800_ASIC1_GPIO_SLEEP_MASK = ASIC1_OUTPUTS;
+ H3800_ASIC1_GPIO_SLEEP_DIR = ASIC1_OUTPUTS;
+ H3800_ASIC1_GPIO_SLEEP_OUT = GPIO1_EAR_ON_N;
+ H3800_ASIC1_GPIO_BATT_FAULT_DIR = ASIC1_OUTPUTS;
+ H3800_ASIC1_GPIO_BATT_FAULT_OUT = GPIO1_EAR_ON_N;
+
+ H3800_ASIC1_GPIO_OUT = GPIO1_IR_ON_N
+ | GPIO1_RS232_ON
+ | GPIO1_EAR_ON_N;
- init_h3600_egpio();
+ /* Set up ASIC #2 */
+ H3800_ASIC2_GPIOPIOD = GPIO2_IN_Y1_N | GPIO2_IN_X1_N;
+ H3800_ASIC2_GPOBFSTAT = GPIO2_IN_Y1_N | GPIO2_IN_X1_N;
- /*
- * Ensure those pins are outputs and driving low.
- */
- PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
- PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
+ H3800_ASIC2_GPIODIR = GPIO2_PEN_IRQ
+ | GPIO2_SD_DETECT
+ | GPIO2_EAR_IN_N
+ | GPIO2_USB_DETECT_N
+ | GPIO2_SD_CON_SLT;
- /* Configure suspend conditions */
- PGSR = 0;
- PWER = PWER_GPIO0 | PWER_RTC;
- PCFR = PCFR_OPDE;
- PSDR = 0;
+ /* TODO : Set sleep states & battery fault states */
+
+ /* Clear VPP Enable */
+ H3800_ASIC2_FlashWP_VPP_ON = 0;
+ ipaq_model_ops = h3800_model_ops;
}
-MACHINE_START(H3600, "Compaq iPAQ H3600")
- BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
- BOOT_PARAMS(0xc0000100)
- MAPIO(h3600_map_io)
- INITIRQ(sa1100_init_irq)
-MACHINE_END
-MACHINE_START(H3100, "Compaq iPAQ H3100")
- BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
- BOOT_PARAMS(0xc0000100)
- MAPIO(h3600_map_io)
- INITIRQ(sa1100_init_irq)
-MACHINE_END
MACHINE_START(H3800, "Compaq iPAQ H3800")
BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
BOOT_PARAMS(0xc0000100)
- MAPIO(h3600_map_io)
- INITIRQ(sa1100_init_irq)
+ MAPIO(h3800_map_io)
+ INITIRQ(h3800_init_irq)
MACHINE_END
+
+#endif /* CONFIG_SA1100_H3800 */
diff --git a/arch/arm/mach-sa1100/jornada720.c b/arch/arm/mach-sa1100/jornada720.c
index 3ff0f6999a2f..a73562679025 100644
--- a/arch/arm/mach-sa1100/jornada720.c
+++ b/arch/arm/mach-sa1100/jornada720.c
@@ -16,7 +16,6 @@
#include <asm/mach/serial_sa1100.h>
#include "generic.h"
-#include "sa1111.h"
#define JORTUCR_VAL 0x20000400
@@ -46,11 +45,7 @@ static int __init jornada720_init(void)
PPSR &= ~(PPC_LDD3 | PPC_LDD4);
PPDR |= PPC_LDD3 | PPC_LDD4;
- /* initialize extra IRQs */
- set_GPIO_IRQ_edge(GPIO_GPIO1, GPIO_RISING_EDGE);
- sa1111_init_irq(IRQ_GPIO1); /* chained on GPIO 1 */
-
- return 0;
+ return sa1111_init(0x40000000, IRQ_GPIO1);
}
arch_initcall(jornada720_init);
diff --git a/arch/arm/mach-sa1100/neponset.c b/arch/arm/mach-sa1100/neponset.c
index ef95e6c45f84..9d3a939de4ae 100644
--- a/arch/arm/mach-sa1100/neponset.c
+++ b/arch/arm/mach-sa1100/neponset.c
@@ -11,6 +11,7 @@
#include <linux/ioport.h>
#include <linux/serial_core.h>
#include <linux/device.h>
+#include <linux/slab.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
@@ -23,13 +24,6 @@
#include <asm/hardware/sa1111.h>
#include <asm/sizes.h>
-#include "sa1111.h"
-
-static struct device neponset_device = {
- .name = "Neponset",
- .bus_id = "nep_bus",
-};
-
/*
* Install handler for Neponset IRQ. Note that we have to loop here
* since the ETHERNET and USAR IRQs are level based, and we need to
@@ -163,6 +157,52 @@ static struct sa1100_port_fns neponset_port_fns __initdata = {
.get_mctrl = neponset_get_mctrl,
};
+/*
+ * LDM power management.
+ */
+static int neponset_suspend(struct device *dev, u32 state, u32 level)
+{
+ /*
+ * Save state.
+ */
+ if (level == SUSPEND_SAVE_STATE ||
+ level == SUSPEND_DISABLE ||
+ level == SUSPEND_POWER_DOWN) {
+ if (!dev->saved_state)
+ dev->saved_state = kmalloc(sizeof(unsigned int), GFP_KERNEL);
+ if (!dev->saved_state)
+ return -ENOMEM;
+
+ *(unsigned int *)dev->saved_state = NCR_0;
+ }
+
+ return 0;
+}
+
+static int neponset_resume(struct device *dev, u32 level)
+{
+ if (level == RESUME_RESTORE_STATE || level == RESUME_ENABLE) {
+ if (dev->saved_state) {
+ NCR_0 = *(unsigned int *)dev->saved_state;
+ kfree(dev->saved_state);
+ dev->saved_state = NULL;
+ }
+ }
+
+ return 0;
+}
+
+static struct device_driver neponset_device_driver = {
+ .suspend = neponset_suspend,
+ .resume = neponset_resume,
+};
+
+static struct device neponset_device = {
+ .name = "Neponset",
+ .bus_id = "neponset",
+ .driver = &neponset_device_driver,
+};
+
static int __init neponset_init(void)
{
int ret;
@@ -191,7 +231,7 @@ static int __init neponset_init(void)
return -ENODEV;
}
- ret = device_register(&neponset_device);
+ ret = register_sys_device(&neponset_device);
if (ret)
return ret;
@@ -213,7 +253,7 @@ static int __init neponset_init(void)
/*
* Probe and initialise the SA1111.
*/
- return sa1111_init(&neponset_device, 0x40000000, IRQ_NEPONSET_SA1111);
+ return sa1111_init(0x40000000, IRQ_NEPONSET_SA1111);
}
arch_initcall(neponset_init);
diff --git a/arch/arm/mach-sa1100/pfs168.c b/arch/arm/mach-sa1100/pfs168.c
index 2b62878b4e7c..d17c1a79e785 100644
--- a/arch/arm/mach-sa1100/pfs168.c
+++ b/arch/arm/mach-sa1100/pfs168.c
@@ -17,7 +17,6 @@
#include <asm/mach/serial_sa1100.h>
#include "generic.h"
-#include "sa1111.h"
static int __init pfs168_init(void)
@@ -36,7 +35,7 @@ static int __init pfs168_init(void)
/*
* Probe for SA1111.
*/
- return sa1111_init(NULL, 0x40000000, IRQ_GPIO25);
+ return sa1111_init(0x40000000, IRQ_GPIO25);
}
arch_initcall(pfs168_init);
diff --git a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c
index 1a7cebd8d28c..76e0da5b973e 100644
--- a/arch/arm/mach-sa1100/pm.c
+++ b/arch/arm/mach-sa1100/pm.c
@@ -30,6 +30,7 @@
#include <linux/interrupt.h>
#include <linux/sysctl.h>
#include <linux/errno.h>
+#include <linux/device.h>
#include <linux/cpufreq.h>
#include <asm/hardware.h>
@@ -193,11 +194,29 @@ static int sysctl_pm_do_suspend(void)
{
int retval;
+ /*
+ * Suspend "legacy" devices.
+ */
retval = pm_send_all(PM_SUSPEND, (void *)3);
-
if (retval == 0) {
+ /*
+ * Suspend LDM devices.
+ */
+ device_suspend(4, SUSPEND_NOTIFY);
+ device_suspend(4, SUSPEND_SAVE_STATE);
+ device_suspend(4, SUSPEND_DISABLE);
+
retval = pm_do_suspend();
+ /*
+ * Resume LDM devices.
+ */
+ device_resume(RESUME_RESTORE_STATE);
+ device_resume(RESUME_ENABLE);
+
+ /*
+ * Resume "legacy" devices.
+ */
pm_send_all(PM_RESUME, (void *)0);
}
diff --git a/arch/arm/mach-sa1100/sa1111.c b/arch/arm/mach-sa1100/sa1111.c
index 244dfdc35c59..9ded8fe5f98e 100644
--- a/arch/arm/mach-sa1100/sa1111.c
+++ b/arch/arm/mach-sa1100/sa1111.c
@@ -25,6 +25,7 @@
#include <linux/ioport.h>
#include <linux/device.h>
#include <linux/slab.h>
+#include <linux/spinlock.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
@@ -34,11 +35,132 @@
#include <asm/hardware/sa1111.h>
-#include "sa1111.h"
+/*
+ * We keep the following data for the overall SA1111. Note that the
+ * struct device and struct resource are "fake"; they should be supplied
+ * by the bus above us. However, in the interests of getting all SA1111
+ * drivers converted over to the device model, we provide this as an
+ * anchor point for all the other drivers.
+ */
+struct sa1111 {
+ struct device dev;
+ struct resource res;
+ int irq;
+ spinlock_t lock;
+ void *base;
+};
+
+/*
+ * We _really_ need to eliminate this. Its only users
+ * are the PWM and DMA checking code.
+ */
+static struct sa1111 *g_sa1111;
+
+static struct sa1111_dev usb_dev = {
+ .dev = {
+ .name = "Intel Corporation SA1111 [USB Controller]",
+ },
+ .skpcr_mask = SKPCR_UCLKEN,
+ .devid = SA1111_DEVID_USB,
+ .irq = {
+ IRQ_USBPWR,
+ IRQ_NHCIM,
+ IRQ_HCIBUFFACC,
+ IRQ_HCIRMTWKP,
+ IRQ_NHCIMFCIR,
+ IRQ_USB_PORT_RESUME
+ },
+};
-struct sa1111_device *sa1111;
+static struct sa1111_dev sac_dev = {
+ .dev = {
+ .name = "Intel Corporation SA1111 [Audio Controller]",
+ },
+ .skpcr_mask = SKPCR_I2SCLKEN | SKPCR_L3CLKEN,
+ .devid = SA1111_DEVID_SAC,
+ .irq = {
+ AUDXMTDMADONEA,
+ AUDXMTDMADONEB,
+ AUDRCVDMADONEA,
+ AUDRCVDMADONEB
+ },
+};
-EXPORT_SYMBOL(sa1111);
+static struct sa1111_dev ssp_dev = {
+ .dev = {
+ .name = "Intel Corporation SA1111 [SSP Controller]",
+ },
+ .skpcr_mask = SKPCR_SCLKEN,
+ .devid = SA1111_DEVID_SSP,
+};
+
+static struct sa1111_dev kbd_dev = {
+ .dev = {
+ .name = "Intel Corporation SA1111 [PS2]",
+ },
+ .skpcr_mask = SKPCR_PTCLKEN,
+ .devid = SA1111_DEVID_PS2,
+ .irq = {
+ IRQ_TPRXINT,
+ IRQ_TPTXINT
+ },
+};
+
+static struct sa1111_dev mse_dev = {
+ .dev = {
+ .name = "Intel Corporation SA1111 [PS2]",
+ },
+ .skpcr_mask = SKPCR_PMCLKEN,
+ .devid = SA1111_DEVID_PS2,
+ .irq = {
+ IRQ_MSRXINT,
+ IRQ_MSTXINT
+ },
+};
+
+static struct sa1111_dev int_dev = {
+ .dev = {
+ .name = "Intel Corporation SA1111 [Interrupt Controller]",
+ },
+ .skpcr_mask = 0,
+ .devid = SA1111_DEVID_INT,
+};
+
+static struct sa1111_dev pcmcia_dev = {
+ .dev = {
+ .name = "Intel Corporation SA1111 [PCMCIA Controller]",
+ },
+ .skpcr_mask = 0,
+ .devid = SA1111_DEVID_PCMCIA,
+ .irq = {
+ IRQ_S0_READY_NINT,
+ IRQ_S0_CD_VALID,
+ IRQ_S0_BVD1_STSCHG,
+ IRQ_S1_READY_NINT,
+ IRQ_S1_CD_VALID,
+ IRQ_S1_BVD1_STSCHG,
+ },
+};
+
+static struct sa1111_dev *devs[] = {
+ &usb_dev,
+ &sac_dev,
+ &ssp_dev,
+ &kbd_dev,
+ &mse_dev,
+ &int_dev,
+ &pcmcia_dev,
+};
+
+static unsigned int dev_offset[] = {
+ SA1111_USB,
+ 0x0600,
+ 0x0800,
+ SA1111_KBD,
+ SA1111_MSE,
+ SA1111_INTC,
+ 0x1800,
+};
/*
* SA1111 interrupt support. Since clearing an IRQ while there are
@@ -50,11 +172,15 @@ sa1111_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
{
unsigned int stat0, stat1, i;
- desc->chip->ack(irq);
-
stat0 = INTSTATCLR0;
stat1 = INTSTATCLR1;
+ INTSTATCLR0 = stat0;
+
+ desc->chip->ack(irq);
+
+ INTSTATCLR1 = stat1;
+
if (stat0 == 0 && stat1 == 0) {
do_bad_IRQ(irq, desc, regs);
return;
@@ -75,9 +201,8 @@ sa1111_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
#define SA1111_IRQMASK_LO(x) (1 << (x - IRQ_SA1111_START))
#define SA1111_IRQMASK_HI(x) (1 << (x - IRQ_SA1111_START - 32))
-static void sa1111_ack_lowirq(unsigned int irq)
+static void sa1111_ack_irq(unsigned int irq)
{
- INTSTATCLR0 = SA1111_IRQMASK_LO(irq);
}
static void sa1111_mask_lowirq(unsigned int irq)
@@ -133,18 +258,13 @@ static int sa1111_type_lowirq(unsigned int irq, unsigned int flags)
}
static struct irqchip sa1111_low_chip = {
- .ack = sa1111_ack_lowirq,
+ .ack = sa1111_ack_irq,
.mask = sa1111_mask_lowirq,
.unmask = sa1111_unmask_lowirq,
.rerun = sa1111_rerun_lowirq,
.type = sa1111_type_lowirq,
};
-static void sa1111_ack_highirq(unsigned int irq)
-{
- INTSTATCLR1 = SA1111_IRQMASK_HI(irq);
-}
-
static void sa1111_mask_highirq(unsigned int irq)
{
INTEN1 &= ~SA1111_IRQMASK_HI(irq);
@@ -198,34 +318,40 @@ static int sa1111_type_highirq(unsigned int irq, unsigned int flags)
}
static struct irqchip sa1111_high_chip = {
- .ack = sa1111_ack_highirq,
+ .ack = sa1111_ack_irq,
.mask = sa1111_mask_highirq,
.unmask = sa1111_unmask_highirq,
.rerun = sa1111_rerun_highirq,
.type = sa1111_type_highirq,
};
-static void __init sa1111_init_irq(int irq_nr)
+static void __init sa1111_init_irq(struct sa1111_dev *sadev)
{
unsigned int irq;
- request_mem_region(_INTTEST0, 512, "irqs");
+ /*
+ * We're guaranteed that this region hasn't been taken.
+ */
+ request_mem_region(sadev->res.start, 512, "irqs");
/* disable all IRQs */
- INTEN0 = 0;
- INTEN1 = 0;
+ sa1111_writel(0, sadev->mapbase + SA1111_INTEN0);
+ sa1111_writel(0, sadev->mapbase + SA1111_INTEN1);
+ sa1111_writel(0, sadev->mapbase + SA1111_WAKEEN0);
+ sa1111_writel(0, sadev->mapbase + SA1111_WAKEEN1);
/*
* detect on rising edge. Note: Feb 2001 Errata for SA1111
* specifies that S0ReadyInt and S1ReadyInt should be '1'.
*/
- INTPOL0 = 0;
- INTPOL1 = SA1111_IRQMASK_HI(S0_READY_NINT) |
- SA1111_IRQMASK_HI(S1_READY_NINT);
+ sa1111_writel(0, sadev->mapbase + SA1111_INTPOL0);
+ sa1111_writel(SA1111_IRQMASK_HI(IRQ_S0_READY_NINT) |
+ SA1111_IRQMASK_HI(IRQ_S1_READY_NINT),
+ sadev->mapbase + SA1111_INTPOL1);
/* clear all IRQs */
- INTSTATCLR0 = ~0;
- INTSTATCLR1 = ~0;
+ sa1111_writel(~0, sadev->mapbase + SA1111_INTSTATCLR0);
+ sa1111_writel(~0, sadev->mapbase + SA1111_INTSTATCLR1);
for (irq = IRQ_GPAIN0; irq <= SSPROR; irq++) {
set_irq_chip(irq, &sa1111_low_chip);
@@ -233,7 +359,7 @@ static void __init sa1111_init_irq(int irq_nr)
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
}
- for (irq = AUDXMTDMADONEA; irq <= S1_BVD1_STSCHG; irq++) {
+ for (irq = AUDXMTDMADONEA; irq <= IRQ_S1_BVD1_STSCHG; irq++) {
set_irq_chip(irq, &sa1111_high_chip);
set_irq_handler(irq, do_edge_IRQ);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
@@ -242,24 +368,11 @@ static void __init sa1111_init_irq(int irq_nr)
/*
* Register SA1111 interrupt
*/
- set_irq_type(irq_nr, IRQT_RISING);
- set_irq_chained_handler(irq_nr, sa1111_irq_handler);
-}
-
-static int sa1111_suspend(struct device *dev, u32 state, u32 level)
-{
- return 0;
+ set_irq_type(sadev->irq[0], IRQT_RISING);
+ set_irq_chained_handler(sadev->irq[0], sa1111_irq_handler);
}
-static int sa1111_resume(struct device *dev, u32 level)
-{
- return 0;
-}
-
-static struct device_driver sa1111_device_driver = {
- .suspend = sa1111_suspend,
- .resume = sa1111_resume,
-};
+static struct device_driver sa1111_device_driver;
/**
* sa1111_probe - probe for a single SA1111 chip.
@@ -274,30 +387,38 @@ static struct device_driver sa1111_device_driver = {
* %0 successful.
*/
static int __init
-sa1111_probe(struct device *parent, unsigned long phys_addr)
+sa1111_probe(unsigned long phys_addr, int irq)
{
- struct sa1111_device *sa;
+ struct sa1111 *sachip;
unsigned long id;
- int ret = -ENODEV;
+ unsigned int has_devs;
+ int i, ret = -ENODEV;
- sa = kmalloc(sizeof(struct sa1111_device), GFP_KERNEL);
- if (!sa)
+ sachip = kmalloc(sizeof(struct sa1111), GFP_KERNEL);
+ if (!sachip)
return -ENOMEM;
- memset(sa, 0, sizeof(struct sa1111_device));
+ memset(sachip, 0, sizeof(struct sa1111));
+
+ spin_lock_init(&sachip->lock);
- sa->resource.name = "SA1111";
- sa->resource.start = phys_addr;
- sa->resource.end = phys_addr + 0x2000;
+ strncpy(sachip->dev.name, "Intel Corporation SA1111", sizeof(sachip->dev.name));
+ snprintf(sachip->dev.bus_id, sizeof(sachip->dev.bus_id), "%8.8lx", phys_addr);
+ sachip->dev.driver = &sa1111_device_driver;
+ sachip->dev.driver_data = sachip;
- if (request_resource(&iomem_resource, &sa->resource)) {
+ sachip->res.name = sachip->dev.name;
+ sachip->res.start = phys_addr;
+ sachip->res.end = phys_addr + 0x2000;
+ sachip->irq = irq;
+
+ if (request_resource(&iomem_resource, &sachip->res)) {
ret = -EBUSY;
goto out;
}
- /* eventually ioremap... */
- sa->base = (void *)0xf4000000;
- if (!sa->base) {
+ sachip->base = ioremap(phys_addr, PAGE_SIZE * 2);
+ if (!sachip->base) {
ret = -ENOMEM;
goto release;
}
@@ -305,7 +426,7 @@ sa1111_probe(struct device *parent, unsigned long phys_addr)
/*
* Probe for the chip. Only touch the SBI registers.
*/
- id = sa1111_readl(sa->base + SA1111_SKID);
+ id = sa1111_readl(sachip->base + SA1111_SKID);
if ((id & SKID_ID_MASK) != SKID_SA1111_ID) {
printk(KERN_DEBUG "SA1111 not detected: ID = %08lx\n", id);
ret = -ENODEV;
@@ -315,12 +436,7 @@ sa1111_probe(struct device *parent, unsigned long phys_addr)
/*
* We found the chip.
*/
- strcpy(sa->dev.name, "SA1111");
- sprintf(sa->dev.bus_id, "%8.8lx", phys_addr);
- sa->dev.parent = parent;
- sa->dev.driver = &sa1111_device_driver;
-
- ret = device_register(&sa->dev);
+ ret = register_sys_device(&sachip->dev);
if (ret)
printk("sa1111 device_register failed: %d\n", ret);
@@ -328,19 +444,64 @@ sa1111_probe(struct device *parent, unsigned long phys_addr)
"silicon revision %lx, metal revision %lx\n",
(id & SKID_SIREV_MASK)>>4, (id & SKID_MTREV_MASK));
- sa1111 = sa;
+ g_sa1111 = sachip;
+
+ has_devs = ~0;
+ if (machine_is_assabet() || machine_is_jornada720() ||
+ machine_is_badge4())
+ has_devs &= ~(1 << 4);
+ else
+ has_devs &= ~(1 << 1);
+
+ for (i = 0; i < ARRAY_SIZE(devs); i++) {
+ if (!(has_devs & (1 << i)))
+ continue;
+
+ snprintf(devs[i]->dev.bus_id, sizeof(devs[i]->dev.bus_id),
+ "%4.4x", dev_offset[i]);
+
+ devs[i]->dev.parent = &sachip->dev;
+ devs[i]->dev.bus = &sa1111_bus_type;
+ devs[i]->res.start = sachip->res.start + dev_offset[i];
+ devs[i]->res.end = devs[i]->res.start + 511;
+ devs[i]->res.name = devs[i]->dev.name;
+ devs[i]->res.flags = IORESOURCE_MEM;
+ devs[i]->mapbase = sachip->base + dev_offset[i];
+
+ if (request_resource(&sachip->res, &devs[i]->res)) {
+ printk("SA1111: failed to allocate resource for %s\n",
+ devs[i]->res.name);
+ continue;
+ }
+
+ device_register(&devs[i]->dev);
+ }
return 0;
unmap:
-// iounmap(sa->base);
+ iounmap(sachip->base);
release:
- release_resource(&sa->resource);
+ release_resource(&sachip->res);
out:
- kfree(sa);
+ kfree(sachip);
return ret;
}
+static void __sa1111_remove(struct sa1111 *sachip)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(devs); i++) {
+ put_device(&devs[i]->dev);
+ release_resource(&devs[i]->res);
+ }
+
+ iounmap(sachip->base);
+ release_resource(&sachip->res);
+ kfree(sachip);
+}
+
/*
* Bring the SA1111 out of reset. This requires a set procedure:
* 1. nRESET asserted (by hardware)
@@ -355,12 +516,11 @@ sa1111_probe(struct device *parent, unsigned long phys_addr)
* SBI_SMCR
* SBI_SKID
*/
-void sa1111_wake(void)
+static void sa1111_wake(struct sa1111 *sachip)
{
- struct sa1111_device *sa = sa1111;
unsigned long flags, r;
- local_irq_save(flags);
+ spin_lock_irqsave(&sachip->lock, flags);
/*
* First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111:
@@ -373,11 +533,11 @@ void sa1111_wake(void)
/*
* Turn VCO on, and disable PLL Bypass.
*/
- r = sa1111_readl(sa->base + SA1111_SKCR);
+ r = sa1111_readl(sachip->base + SA1111_SKCR);
r &= ~SKCR_VCO_OFF;
- sa1111_writel(r, sa->base + SA1111_SKCR);
+ sa1111_writel(r, sachip->base + SA1111_SKCR);
r |= SKCR_PLL_BYPASS | SKCR_OE_EN;
- sa1111_writel(r, sa->base + SA1111_SKCR);
+ sa1111_writel(r, sachip->base + SA1111_SKCR);
/*
* Wait lock time. SA1111 manual _doesn't_
@@ -389,7 +549,7 @@ void sa1111_wake(void)
* Enable RCLK. We also ensure that RDYEN is set.
*/
r |= SKCR_RCLKEN | SKCR_RDYEN;
- sa1111_writel(r, sa->base + SA1111_SKCR);
+ sa1111_writel(r, sachip->base + SA1111_SKCR);
/*
* Wait 14 RCLK cycles for the chip to finish coming out
@@ -400,76 +560,31 @@ void sa1111_wake(void)
/*
* Ensure all clocks are initially off.
*/
- sa1111_writel(0, sa->base + SA1111_SKPCR);
+ sa1111_writel(0, sachip->base + SA1111_SKPCR);
- local_irq_restore(flags);
-}
-
-void sa1111_doze(void)
-{
- struct sa1111_device *sa = sa1111;
- unsigned long flags;
- unsigned int val;
-
- local_irq_save(flags);
-
- if (sa1111_readl(sa->base + SA1111_SKPCR) & SKPCR_UCLKEN) {
- local_irq_restore(flags);
- printk("SA1111 doze mode refused\n");
- return;
- }
-
- val = sa1111_readl(sa->base + SA1111_SKCR);
- sa1111_writel(val & ~SKCR_RCLKEN, sa->base + SA1111_SKCR);
- local_irq_restore(flags);
+ spin_unlock_irqrestore(&sachip->lock, flags);
}
/*
* Configure the SA1111 shared memory controller.
*/
-void sa1111_configure_smc(int sdram, unsigned int drac, unsigned int cas_latency)
+void
+sa1111_configure_smc(struct sa1111 *sachip, int sdram, unsigned int drac,
+ unsigned int cas_latency)
{
- struct sa1111_device *sa = sa1111;
unsigned int smcr = SMCR_DTIM | SMCR_MBGE | FInsrt(drac, SMCR_DRAC);
if (cas_latency == 3)
smcr |= SMCR_CLAT;
- sa1111_writel(smcr, sa->base + SA1111_SMCR);
+ sa1111_writel(smcr, sachip->base + SA1111_SMCR);
}
-EXPORT_SYMBOL(sa1111_wake);
-EXPORT_SYMBOL(sa1111_doze);
-
-void sa1111_enable_device(unsigned int mask)
-{
- struct sa1111_device *sa = sa1111;
- unsigned int val;
-
- preempt_disable();
- val = sa1111_readl(sa->base + SA1111_SKPCR);
- sa1111_writel(val | mask, sa->base + SA1111_SKPCR);
- preempt_enable();
-}
-
-void sa1111_disable_device(unsigned int mask)
-{
- struct sa1111_device *sa = sa1111;
- unsigned int val;
-
- preempt_disable();
- val = sa1111_readl(sa->base + SA1111_SKPCR);
- sa1111_writel(val & ~mask, sa->base + SA1111_SKPCR);
- preempt_enable();
-}
-
-EXPORT_SYMBOL(sa1111_enable_device);
-EXPORT_SYMBOL(sa1111_disable_device);
-
-/* According to the "Intel StrongARM SA-1111 Microprocessor Companion
+/*
+ * According to the "Intel StrongARM SA-1111 Microprocessor Companion
* Chip Specification Update" (June 2000), erratum #7, there is a
- * significant bug in Serial Audio Controller DMA. If the SAC is
- * accessing a region of memory above 1MB relative to the bank base,
+ * significant bug in the SA1111 SDRAM shared memory controller. If
+ * an access to a region of memory above 1MB relative to the bank base,
* it is important that address bit 10 _NOT_ be asserted. Depending
* on the configuration of the RAM, bit 10 may correspond to one
* of several different (processor-relative) address bits.
@@ -479,7 +594,9 @@ EXPORT_SYMBOL(sa1111_disable_device);
*/
int sa1111_check_dma_bug(dma_addr_t addr)
{
- unsigned int physaddr=SA1111_DMA_ADDR((unsigned int)addr);
+ struct sa1111 *sachip = g_sa1111;
+ unsigned int physaddr = SA1111_DMA_ADDR((unsigned int)addr);
+ unsigned int smcr;
/* Section 4.6 of the "Intel StrongARM SA-1111 Development Module
* User's Guide" mentions that jumpers R51 and R52 control the
@@ -494,9 +611,10 @@ int sa1111_check_dma_bug(dma_addr_t addr)
* above the start of the target bank:
*/
if (physaddr<(1<<20))
- return 0;
+ return 0;
- switch (FExtr(SBI_SMCR, SMCR_DRAC)) {
+ smcr = sa1111_readl(sachip->base + SA1111_SMCR);
+ switch (FExtr(smcr, SMCR_DRAC)) {
case 01: /* 10 row + bank address bits, A<20> must not be set */
if (physaddr & (1<<20))
return -1;
@@ -523,27 +641,26 @@ int sa1111_check_dma_bug(dma_addr_t addr)
break;
default:
printk(KERN_ERR "%s(): invalid SMCR DRAC value 0%lo\n",
- __FUNCTION__, FExtr(SBI_SMCR, SMCR_DRAC));
+ __FUNCTION__, FExtr(smcr, SMCR_DRAC));
return -1;
}
return 0;
}
-EXPORT_SYMBOL(sa1111_check_dma_bug);
-
-int sa1111_init(struct device *parent, unsigned long phys, unsigned int irq)
+int sa1111_init(unsigned long phys, unsigned int irq)
{
+ unsigned int val;
int ret;
- ret = sa1111_probe(parent, phys);
+ ret = sa1111_probe(phys, irq);
if (ret < 0)
return ret;
/*
* We found it. Wake the chip up.
*/
- sa1111_wake();
+ sa1111_wake(g_sa1111);
/*
* The SDRAM configuration of the SA1110 and the SA1111 must
@@ -552,7 +669,7 @@ int sa1111_init(struct device *parent, unsigned long phys, unsigned int irq)
* MBGNT signal, so we must have called sa1110_mb_disable()
* beforehand.
*/
- sa1111_configure_smc(1,
+ sa1111_configure_smc(g_sa1111, 1,
FExtr(MDCNFG, MDCNFG_SA1110_DRAC0),
FExtr(MDCNFG, MDCNFG_SA1110_TDL0));
@@ -560,7 +677,8 @@ int sa1111_init(struct device *parent, unsigned long phys, unsigned int irq)
* We only need to turn on DCLK whenever we want to use the
* DMA. It can otherwise be held firmly in the off position.
*/
- sa1111_enable_device(SKPCR_DCLKEN);
+ val = sa1111_readl(g_sa1111->base + SA1111_SKPCR);
+ sa1111_writel(val | SKPCR_DCLKEN, g_sa1111->base + SA1111_SKPCR);
/*
* Enable the SA1110 memory bus request and grant signals.
@@ -570,7 +688,341 @@ int sa1111_init(struct device *parent, unsigned long phys, unsigned int irq)
/*
* Initialise SA1111 IRQs
*/
- sa1111_init_irq(irq);
+ int_dev.irq[0] = irq;
+ sa1111_init_irq(&int_dev);
+
+ return 0;
+}
+
+struct sa1111_save_data {
+ unsigned int skcr;
+ unsigned int skpcr;
+ unsigned int skcdr;
+ unsigned char skaud;
+ unsigned char skpwm0;
+ unsigned char skpwm1;
+
+ /*
+ * Interrupt controller
+ */
+ unsigned int intpol0;
+ unsigned int intpol1;
+ unsigned int inten0;
+ unsigned int inten1;
+ unsigned int wakepol0;
+ unsigned int wakepol1;
+ unsigned int wakeen0;
+ unsigned int wakeen1;
+};
+
+static int sa1111_suspend(struct device *dev, u32 state, u32 level)
+{
+ struct sa1111 *sachip = dev->driver_data;
+ unsigned long flags;
+ char *base;
+
+ /*
+ * Save state.
+ */
+ if (level == SUSPEND_SAVE_STATE ||
+ level == SUSPEND_DISABLE ||
+ level == SUSPEND_POWER_DOWN) {
+ struct sa1111_save_data *save;
+
+ if (!dev->saved_state)
+ dev->saved_state = kmalloc(sizeof(struct sa1111_save_data), GFP_KERNEL);
+ if (!dev->saved_state)
+ return -ENOMEM;
+
+ save = (struct sa1111_save_data *)dev->saved_state;
+
+ spin_lock_irqsave(&sachip->lock, flags);
+ base = sachip->base;
+ save->skcr = sa1111_readl(base + SA1111_SKCR);
+ save->skpcr = sa1111_readl(base + SA1111_SKPCR);
+ save->skcdr = sa1111_readl(base + SA1111_SKCDR);
+ save->skaud = sa1111_readl(base + SA1111_SKAUD);
+ save->skpwm0 = sa1111_readl(base + SA1111_SKPWM0);
+ save->skpwm1 = sa1111_readl(base + SA1111_SKPWM1);
+
+ base = sachip->base + SA1111_INTC;
+ save->intpol0 = sa1111_readl(base + SA1111_INTPOL0);
+ save->intpol1 = sa1111_readl(base + SA1111_INTPOL1);
+ save->inten0 = sa1111_readl(base + SA1111_INTEN0);
+ save->inten1 = sa1111_readl(base + SA1111_INTEN1);
+ save->wakepol0 = sa1111_readl(base + SA1111_WAKEPOL0);
+ save->wakepol1 = sa1111_readl(base + SA1111_WAKEPOL1);
+ save->wakeen0 = sa1111_readl(base + SA1111_WAKEEN0);
+ save->wakeen1 = sa1111_readl(base + SA1111_WAKEEN1);
+ spin_unlock_irqrestore(&sachip->lock, flags);
+ }
+
+ /*
+ * Disable.
+ */
+ if (level == SUSPEND_DISABLE && state == 4) {
+ unsigned int val;
+
+ spin_lock_irqsave(&sachip->lock, flags);
+ base = sachip->base;
+
+ sa1111_writel(0, base + SA1111_SKPWM0);
+ sa1111_writel(0, base + SA1111_SKPWM1);
+ val = sa1111_readl(base + SA1111_SKCR);
+ sa1111_writel(val | SKCR_SLEEP, base + SA1111_SKCR);
+
+ spin_unlock_irqrestore(&sachip->lock, flags);
+ }
return 0;
}
+
+/*
+ * sa1111_resume - Restore the SA1111 device state.
+ * @dev: device to restore
+ * @level: resume level
+ *
+ * Restore the general state of the SA1111; clock control and
+ * interrupt controller. Other parts of the SA1111 must be
+ * restored by their respective drivers, and must be called
+ * via LDM after this function.
+ */
+static int sa1111_resume(struct device *dev, u32 level)
+{
+ struct sa1111 *sachip = dev->driver_data;
+ struct sa1111_save_data *save;
+ unsigned long flags, id;
+ char *base;
+
+ if (level != RESUME_RESTORE_STATE && level != RESUME_ENABLE)
+ return 0;
+
+ save = (struct sa1111_save_data *)dev->saved_state;
+ if (!save)
+ return 0;
+
+ dev->saved_state = NULL;
+
+ /*
+ * Ensure that the SA1111 is still here.
+ */
+ id = sa1111_readl(sachip->base + SA1111_SKID);
+ if ((id & SKID_ID_MASK) != SKID_SA1111_ID) {
+ __sa1111_remove(sachip);
+ kfree(save);
+ return 0;
+ }
+
+ spin_lock_irqsave(&sachip->lock, flags);
+ sa1111_wake(sachip);
+
+ base = sachip->base;
+ sa1111_writel(save->skcr, base + SA1111_SKCR);
+ sa1111_writel(save->skpcr, base + SA1111_SKPCR);
+ sa1111_writel(save->skcdr, base + SA1111_SKCDR);
+ sa1111_writel(save->skaud, base + SA1111_SKAUD);
+ sa1111_writel(save->skpwm0, base + SA1111_SKPWM0);
+ sa1111_writel(save->skpwm1, base + SA1111_SKPWM1);
+
+ base = sachip->base + SA1111_INTC;
+ sa1111_writel(save->intpol0, base + SA1111_INTPOL0);
+ sa1111_writel(save->intpol1, base + SA1111_INTPOL1);
+ sa1111_writel(save->inten0, base + SA1111_INTEN0);
+ sa1111_writel(save->inten1, base + SA1111_INTEN1);
+ sa1111_writel(save->wakepol0, base + SA1111_WAKEPOL0);
+ sa1111_writel(save->wakepol1, base + SA1111_WAKEPOL1);
+ sa1111_writel(save->wakeen0, base + SA1111_WAKEEN0);
+ sa1111_writel(save->wakeen1, base + SA1111_WAKEEN1);
+ spin_unlock_irqrestore(&sachip->lock, flags);
+
+ kfree(save);
+
+ return 0;
+}
+
+static struct device_driver sa1111_device_driver = {
+ .suspend = sa1111_suspend,
+ .resume = sa1111_resume,
+};
+
+/*
+ * Get the parent device driver (us) structure
+ * from a child function device
+ */
+static inline struct sa1111 *sa1111_chip_driver(struct sa1111_dev *sadev)
+{
+ return (struct sa1111 *)sadev->dev.parent->driver_data;
+}
+
+/*
+ * The bits in the opdiv field are non-linear.
+ */
+static unsigned char opdiv_table[] = { 1, 4, 2, 8 };
+
+static unsigned int __sa1111_pll_clock(struct sa1111 *sachip)
+{
+ unsigned int skcdr, fbdiv, ipdiv, opdiv;
+
+ skcdr = sa1111_readl(sachip->base + SA1111_SKCDR);
+
+ fbdiv = (skcdr & 0x007f) + 2;
+ ipdiv = ((skcdr & 0x0f80) >> 7) + 2;
+ opdiv = opdiv_table[(skcdr & 0x3000) >> 12];
+
+ return 3686400 * fbdiv / (ipdiv * opdiv);
+}
+
+/**
+ * sa1111_pll_clock - return the current PLL clock frequency.
+ * @sadev: SA1111 function block
+ *
+ * BUG: we should look at SKCR. We also blindly believe that
+ * the chip is being fed with the 3.6864MHz clock.
+ *
+ * Returns the PLL clock in Hz.
+ */
+unsigned int sa1111_pll_clock(struct sa1111_dev *sadev)
+{
+ struct sa1111 *sachip = sa1111_chip_driver(sadev);
+
+ return __sa1111_pll_clock(sachip);
+}
+
+/**
+ * sa1111_select_audio_mode - select I2S or AC link mode
+ * @sadev: SA1111 function block
+ * @mode: One of %SA1111_AUDIO_ACLINK or %SA1111_AUDIO_I2S
+ *
+ * Frob the SKCR to select AC Link mode or I2S mode for
+ * the audio block.
+ */
+void sa1111_select_audio_mode(struct sa1111_dev *sadev, int mode)
+{
+ struct sa1111 *sachip = sa1111_chip_driver(sadev);
+ unsigned long flags;
+ unsigned int val;
+
+ spin_lock_irqsave(&sachip->lock, flags);
+
+ val = sa1111_readl(sachip->base + SA1111_SKCR);
+ if (mode == SA1111_AUDIO_I2S) {
+ val &= ~SKCR_SELAC;
+ } else {
+ val |= SKCR_SELAC;
+ }
+ sa1111_writel(val, sachip->base + SA1111_SKCR);
+
+ spin_unlock_irqrestore(&sachip->lock, flags);
+}
+
+/**
+ * sa1111_set_audio_rate - set the audio sample rate
+ * @sadev: SA1111 SAC function block
+ * @rate: sample rate to select
+ */
+int sa1111_set_audio_rate(struct sa1111_dev *sadev, int rate)
+{
+ struct sa1111 *sachip = sa1111_chip_driver(sadev);
+ unsigned int div;
+
+ if (sadev->devid != SA1111_DEVID_SAC)
+ return -EINVAL;
+
+ div = (__sa1111_pll_clock(sachip) / 256 + rate / 2) / rate;
+ if (div == 0)
+ div = 1;
+ if (div > 128)
+ div = 128;
+
+ sa1111_writel(div - 1, sachip->base + SA1111_SKAUD);
+
+ return 0;
+}
+
+/**
+ * sa1111_get_audio_rate - get the audio sample rate
+ * @sadev: SA1111 SAC function block device
+ */
+int sa1111_get_audio_rate(struct sa1111_dev *sadev)
+{
+ struct sa1111 *sachip = sa1111_chip_driver(sadev);
+ unsigned long div;
+
+ if (sadev->devid != SA1111_DEVID_SAC)
+ return -EINVAL;
+
+ div = sa1111_readl(sachip->base + SA1111_SKAUD) + 1;
+
+ return __sa1111_pll_clock(sachip) / (256 * div);
+}
+
+/*
+ * Individual device operations.
+ */
+
+/**
+ * sa1111_enable_device - enable an on-chip SA1111 function block
+ * @sadev: SA1111 function block device to enable
+ */
+void sa1111_enable_device(struct sa1111_dev *sadev)
+{
+ struct sa1111 *sachip = sa1111_chip_driver(sadev);
+ unsigned long flags;
+ unsigned int val;
+
+ spin_lock_irqsave(&sachip->lock, flags);
+ val = sa1111_readl(sachip->base + SA1111_SKPCR);
+ sa1111_writel(val | sadev->skpcr_mask, sachip->base + SA1111_SKPCR);
+ spin_unlock_irqrestore(&sachip->lock, flags);
+}
+
+/**
+ * sa1111_disable_device - disable an on-chip SA1111 function block
+ * @sadev: SA1111 function block device to disable
+ */
+void sa1111_disable_device(struct sa1111_dev *sadev)
+{
+ struct sa1111 *sachip = sa1111_chip_driver(sadev);
+ unsigned long flags;
+ unsigned int val;
+
+ spin_lock_irqsave(&sachip->lock, flags);
+ val = sa1111_readl(sachip->base + SA1111_SKPCR);
+ sa1111_writel(val & ~sadev->skpcr_mask, sachip->base + SA1111_SKPCR);
+ spin_unlock_irqrestore(&sachip->lock, flags);
+}
+
+/*
+ * SA1111 "Register Access Bus."
+ *
+ * We model this as a regular bus type, and hang devices directly
+ * off this.
+ */
+static int sa1111_match(struct device *_dev, struct device_driver *_drv)
+{
+ struct sa1111_dev *dev = SA1111_DEV(_dev);
+ struct sa1111_driver *drv = SA1111_DRV(_drv);
+
+ return dev->devid == drv->devid;
+}
+
+struct bus_type sa1111_bus_type = {
+ .name = "RAB",
+ .match = sa1111_match,
+};
+
+static int sa1111_rab_bus_init(void)
+{
+ return bus_register(&sa1111_bus_type);
+}
+
+postcore_initcall(sa1111_rab_bus_init);
+
+EXPORT_SYMBOL(sa1111_check_dma_bug);
+EXPORT_SYMBOL(sa1111_select_audio_mode);
+EXPORT_SYMBOL(sa1111_set_audio_rate);
+EXPORT_SYMBOL(sa1111_get_audio_rate);
+EXPORT_SYMBOL(sa1111_enable_device);
+EXPORT_SYMBOL(sa1111_disable_device);
+EXPORT_SYMBOL(sa1111_pll_clock);
+EXPORT_SYMBOL(sa1111_bus_type);
diff --git a/arch/arm/mach-sa1100/sa1111.h b/arch/arm/mach-sa1100/sa1111.h
deleted file mode 100644
index e3a13f66dd13..000000000000
--- a/arch/arm/mach-sa1100/sa1111.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * linux/arch/arm/mach-sa1100/sa1111.h
- */
-struct device;
-
-/*
- * Probe for a SA1111 chip.
- */
-extern int
-sa1111_init(struct device *parent, unsigned long phys, unsigned int irq);
-
-/*
- * Wake up a SA1111 chip.
- */
-extern void sa1111_wake(void);
-
-/*
- * Doze the SA1111 chip.
- */
-extern void sa1111_doze(void);
diff --git a/arch/arm/mach-sa1100/stork.c b/arch/arm/mach-sa1100/stork.c
index 677be2dfb5ed..703a513a94d0 100644
--- a/arch/arm/mach-sa1100/stork.c
+++ b/arch/arm/mach-sa1100/stork.c
@@ -284,6 +284,17 @@ storkInitTSandDtoA(void)
storkClockShortToDtoA(0x0A00); /* turn on the brightness */
}
+static void stork_lcd_power(int on)
+{
+ if (on) {
+ storkSetLCDCPLD(0, 1);
+ storkSetLatchA(STORK_LCD_BACKLIGHT_INVERTER_ON);
+ } else {
+ storkSetLCDCPLD(0, 0);
+ storkClearLatchA(STORK_LCD_BACKLIGHT_INVERTER_ON);
+ }
+}
+
struct map_desc stork_io_desc[] __initdata = {
/* virtual physical length type */
{ STORK_VM_BASE_CS1, STORK_VM_OFF_CS1, 0x01000000, MT_DEVICE }, /* EGPIO 0 */
@@ -312,6 +323,8 @@ stork_map_io(void)
storkInitTSandDtoA();
+ sa1100fb_lcd_power = stork_lcd_power;
+
return 0;
}
diff --git a/arch/arm/mach-sa1100/system3.c b/arch/arm/mach-sa1100/system3.c
index 0629aa5420ce..d0dc614b0b87 100644
--- a/arch/arm/mach-sa1100/system3.c
+++ b/arch/arm/mach-sa1100/system3.c
@@ -56,7 +56,6 @@
#include <linux/serial_core.h>
#include "generic.h"
-#include "sa1111.h"
#include <asm/hardware/sa1111.h>
#define DEBUG 1
@@ -401,7 +400,7 @@ static int __init system3_init(void)
/*
* Probe for a SA1111.
*/
- ret = sa1111_init(NULL, PT_SA1111_BASE, IRQ_SYSTEM3_SA1111);
+ ret = sa1111_init(PT_SA1111_BASE, IRQ_SYSTEM3_SA1111);
if (ret < 0) {
printk( KERN_WARNING"PT Digital Board: no SA1111 found!\n" );
goto DONE;
diff --git a/arch/arm/mm/fault-common.c b/arch/arm/mm/fault-common.c
index 2feafb6d40dc..4099f44532b9 100644
--- a/arch/arm/mm/fault-common.c
+++ b/arch/arm/mm/fault-common.c
@@ -35,7 +35,7 @@
#else
/*
* "code" is actually the FSR register. Bit 11 set means the
- * isntruction was performing a write.
+ * instruction was performing a write.
*/
#define DO_COW(code) ((code) & (1 << 11))
#define READ_FAULT(code) (!DO_COW(code))
@@ -54,7 +54,7 @@ void show_pte(struct mm_struct *mm, unsigned long addr)
printk(KERN_ALERT "pgd = %p\n", mm->pgd);
pgd = pgd_offset(mm, addr);
- printk(KERN_ALERT "*pgd=%08lx", pgd_val(*pgd));
+ printk(KERN_ALERT "[%08lx] *pgd=%08lx", addr, pgd_val(*pgd));
do {
pmd_t *pmd;
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index 39e28f196918..9b8c9551fb87 100644
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -6,7 +6,7 @@
# To add an entry into this database, please see Documentation/arm/README,
# or contact rmk@arm.linux.org.uk
#
-# Last update: Sat Jul 27 09:56:53 2002
+# Last update: Sat Sep 21 13:39:13 2002
#
# machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
#
@@ -214,3 +214,31 @@ emailphone SA1100_EMAILPHONE EMAILPHONE 202
h3900 ARCH_H3900 H3900 203
pxa1 ARCH_PXA1 PXA1 204
koan369 SA1100_KOAN369 KOAN369 205
+cogent ARCH_COGENT COGENT 206
+esl_simputer ARCH_ESL_SIMPUTER ESL_SIMPUTER 207
+esl_simputer_clr ARCH_ESL_SIMPUTER_CLR ESL_SIMPUTER_CLR 208
+esl_simputer_bw ARCH_ESL_SIMPUTER_BW ESL_SIMPUTER_BW 209
+hhp_cradle ARCH_HHP_CRADLE HHP_CRADLE 210
+he500 ARCH_HE500 HE500 211
+inhandelf2 SA1100_INHANDELF2 INHANDELF2 212
+inhandftip SA1100_INHANDFTIP INHANDFTIP 213
+dnp1110 SA1100_DNP1110 DNP1110 214
+pnp1110 SA1100_PNP1110 PNP1110 215
+csb226 ARCH_CSB226 CSB226 216
+arnold SA1100_ARNOLD ARNOLD 217
+psiboard SA1100_PSIBOARD PSIBOARD 218
+jz8028 ARCH_JZ8028 JZ8028 219
+ipaq3 ARCH_IPAQ3 IPAQ3 220
+forte SA1100_FORTE FORTE 221
+acam SA1100_ACAM ACAM 222
+abox SA1100_ABOX ABOX 223
+atmel ARCH_ATMEL ATMEL 224
+sitsang ARCH_SITSANG SITSANG 225
+cpu1110lcdnet SA1100_CPU1110LCDNET CPU1110LCDNET 226
+mpl_vcma9 ARCH_MPL_VCMA9 MPL_VCMA9 227
+opus_a1 ARCH_OPUS_A1 OPUS_A1 228
+daytona ARCH_DAYTONA DAYTONA 229
+killbear SA1100_KILLBEAR KILLBEAR 230
+yoho ARCH_YOHO YOHO 231
+jasper ARCH_JASPER JASPER 232
+dsc25 ARCH_DSC25 DSC25 233
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index 6ea186b42155..ba3f45656bc7 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -3,7 +3,7 @@
* Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
*
* Common time service routines for MIPS machines. See
- * Documents/MIPS/README.txt.
+ * Documentation/mips/time.README.
*
* 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
diff --git a/drivers/base/hotplug.c b/drivers/base/hotplug.c
index 231d42cb7a18..e06e595aefd6 100644
--- a/drivers/base/hotplug.c
+++ b/drivers/base/hotplug.c
@@ -18,6 +18,7 @@
#include <linux/kmod.h>
#include <linux/interrupt.h>
#include "base.h"
+#include "fs/fs.h"
/*
* hotplugging invokes what /proc/sys/kernel/hotplug says (normally
@@ -32,14 +33,16 @@
int dev_hotplug (struct device *dev, const char *action)
{
char *argv [3], **envp, *buffer, *scratch;
+ char *dev_path;
int retval;
int i = 0;
+ int dev_length;
pr_debug ("%s\n", __FUNCTION__);
if (!dev)
return -ENODEV;
- if (!dev->bus || !dev->bus->hotplug)
+ if (!dev->bus)
return -ENODEV;
if (!hotplug_path [0])
@@ -66,6 +69,18 @@ int dev_hotplug (struct device *dev, const char *action)
return -ENOMEM;
}
+ dev_length = get_devpath_length (dev);
+ dev_length += strlen("root");
+ dev_path = kmalloc (dev_length, GFP_KERNEL);
+ if (!dev_path) {
+ kfree (buffer);
+ kfree (envp);
+ return -ENOMEM;
+ }
+ memset (dev_path, 0x00, dev_length);
+ strcpy (dev_path, "root");
+ fill_devpath (dev, dev_path, dev_length);
+
/* only one standardized param to hotplug command: the bus name */
argv [0] = hotplug_path;
argv [1] = dev->bus->name;
@@ -77,26 +92,33 @@ int dev_hotplug (struct device *dev, const char *action)
scratch = buffer;
- /* action: add, remove */
envp [i++] = scratch;
scratch += sprintf (scratch, "ACTION=%s", action) + 1;
- /* have the bus specific function set up the rest of the environment */
- retval = dev->bus->hotplug (dev, &envp[i], NUM_ENVP - i,
- scratch, BUFFER_SIZE - (scratch - buffer));
- if (retval) {
- pr_debug ("%s - hotplug() returned %d\n", __FUNCTION__, retval);
- goto exit;
+ envp [i++] = scratch;
+ scratch += sprintf (scratch, "DEVICE=%s", dev_path) + 1;
+
+ if (dev->bus->hotplug) {
+ /* have the bus specific function add its stuff */
+ retval = dev->bus->hotplug (dev, &envp[i], NUM_ENVP - i,
+ scratch,
+ BUFFER_SIZE - (scratch - buffer));
+ if (retval) {
+ pr_debug ("%s - hotplug() returned %d\n",
+ __FUNCTION__, retval);
+ goto exit;
+ }
}
pr_debug ("%s: %s %s %s %s %s %s\n", __FUNCTION__, argv [0], argv[1],
- action, envp[0], envp[1], envp[2]);
+ envp[0], envp[1], envp[2], envp[3]);
retval = call_usermodehelper (argv [0], argv, envp);
if (retval)
pr_debug ("%s - call_usermodehelper returned %d\n",
__FUNCTION__, retval);
exit:
+ kfree (dev_path);
kfree (buffer);
kfree (envp);
return retval;
diff --git a/drivers/char/toshiba.c b/drivers/char/toshiba.c
index 71b2cf809c3e..187c78b64fa3 100644
--- a/drivers/char/toshiba.c
+++ b/drivers/char/toshiba.c
@@ -84,8 +84,6 @@ static int tosh_fn = 0;
MODULE_PARM(tosh_fn, "i");
-MODULE_LICENSE("GPL");
-
static int tosh_get_info(char *, char **, off_t, int);
static int tosh_ioctl(struct inode *, struct file *, unsigned int,
@@ -517,3 +515,10 @@ void cleanup_module(void)
misc_deregister(&tosh_device);
}
#endif
+
+MODULE_LICENSE("GPL");
+MODULE_PARM_DESC(tosh_fn, "User specified Fn key detection port");
+MODULE_AUTHOR("Jonathan Buzzard <jonathan@buzzard.org.uk>");
+MODULE_DESCRIPTION("Toshiba laptop SMM driver");
+MODULE_SUPPORTED_DEVICE("toshiba");
+
diff --git a/drivers/ide/Config.help b/drivers/ide/Config.help
index 3375dee859dc..145499e8fd1d 100644
--- a/drivers/ide/Config.help
+++ b/drivers/ide/Config.help
@@ -292,7 +292,7 @@ CONFIG_IDEDMA_PCI_AUTO
motherboard uses a VIA VP2 chipset, in which case you should say N.
CONFIG_IDEDMA_IVB
- There are unclear terms is ATA-4 and ATA-5 standards how certain
+ There are unclear terms in ATA-4 and ATA-5 standards how certain
hardware (an 80c ribbon) should be detected. Different interpretations
of the standards have been released in hardware. This causes problems:
for example, a host with Ultra Mode 4 (or higher) will not run
diff --git a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c
index da5688105128..502d3c90b864 100644
--- a/drivers/input/serio/sa1111ps2.c
+++ b/drivers/input/serio/sa1111ps2.c
@@ -15,20 +15,26 @@
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
-#include <asm/hardware/sa1111.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/system.h>
+#include <asm/hardware/sa1111.h>
+
extern struct pt_regs *kbd_pt_regs;
struct ps2if {
- struct serio io;
- struct resource *res;
- unsigned long base;
- unsigned int irq;
- unsigned int skpcr_mask;
+ struct serio io;
+ struct sa1111_dev *dev;
+ unsigned long base;
+ unsigned int open;
+ spinlock_t lock;
+ unsigned int head;
+ unsigned int tail;
+ unsigned char buf[4];
};
/*
@@ -36,104 +42,150 @@ struct ps2if {
* at the most one, but we loop for safety. If there was a
* framing error, we have to manually clear the status.
*/
-static void ps2_int(int irq, void *dev_id, struct pt_regs *regs)
+static void ps2_rxint(int irq, void *dev_id, struct pt_regs *regs)
{
- struct ps2if *sa = dev_id;
+ struct ps2if *ps2if = dev_id;
unsigned int scancode, flag, status;
kbd_pt_regs = regs;
- status = sa1111_readl(sa->base + SA1111_PS2STAT);
+ status = sa1111_readl(ps2if->base + SA1111_PS2STAT);
while (status & PS2STAT_RXF) {
if (status & PS2STAT_STP)
- sa1111_writel(PS2STAT_STP, sa->base + SA1111_PS2STAT);
+ sa1111_writel(PS2STAT_STP, ps2if->base + SA1111_PS2STAT);
flag = (status & PS2STAT_STP ? SERIO_FRAME : 0) |
(status & PS2STAT_RXP ? 0 : SERIO_PARITY);
- scancode = sa1111_readl(sa->base + SA1111_PS2DATA) & 0xff;
+ scancode = sa1111_readl(ps2if->base + SA1111_PS2DATA) & 0xff;
if (hweight8(scancode) & 1)
flag ^= SERIO_PARITY;
- serio_interrupt(&sa->io, scancode, flag);
+ serio_interrupt(&ps2if->io, scancode, flag);
- status = sa1111_readl(sa->base + SA1111_PS2STAT);
+ status = sa1111_readl(ps2if->base + SA1111_PS2STAT);
}
}
/*
+ * Completion of ps2 write
+ */
+static void ps2_txint(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct ps2if *ps2if = dev_id;
+ unsigned int status;
+
+ spin_lock(&ps2if->lock);
+ status = sa1111_readl(ps2if->base + SA1111_PS2STAT);
+ if (ps2if->head == ps2if->tail) {
+ disable_irq(irq);
+ /* done */
+ } else if (status & PS2STAT_TXE) {
+ sa1111_writel(ps2if->buf[ps2if->tail], ps2if->base + SA1111_PS2DATA);
+ ps2if->tail = (ps2if->tail + 1) & (sizeof(ps2if->buf) - 1);
+ }
+ spin_unlock(&ps2if->lock);
+}
+
+/*
* Write a byte to the PS2 port. We have to wait for the
* port to indicate that the transmitter is empty.
*/
static int ps2_write(struct serio *io, unsigned char val)
{
- struct ps2if *sa = io->driver;
- unsigned int timeleft = 10000; /* timeout in 100ms */
+ struct ps2if *ps2if = io->driver;
+ unsigned long flags;
+ unsigned int head;
- while ((sa1111_readl(sa->base + SA1111_PS2STAT) & PS2STAT_TXE) == 0 &&
- timeleft--)
- udelay(10);
+ spin_lock_irqsave(&ps2if->lock, flags);
- if (timeleft)
- sa1111_writel(val, sa->base + SA1111_PS2DATA);
+ /*
+ * If the TX register is empty, we can go straight out.
+ */
+ if (sa1111_readl(ps2if->base + SA1111_PS2STAT) & PS2STAT_TXE) {
+ sa1111_writel(val, ps2if->base + SA1111_PS2DATA);
+ } else {
+ if (ps2if->head == ps2if->tail)
+ enable_irq(ps2if->dev->irq[1]);
+ head = (ps2if->head + 1) & (sizeof(ps2if->buf) - 1);
+ if (head != ps2if->tail) {
+ ps2if->buf[ps2if->head] = val;
+ ps2if->head = head;
+ }
+ }
- return timeleft ? 0 : SERIO_TIMEOUT;
+ spin_unlock_irqrestore(&ps2if->lock, flags);
+ return 0;
}
static int ps2_open(struct serio *io)
{
- struct ps2if *sa = io->driver;
+ struct ps2if *ps2if = io->driver;
int ret;
- sa1111_enable_device(sa->skpcr_mask);
+ sa1111_enable_device(ps2if->dev);
- ret = request_irq(sa->irq, ps2_int, 0, "ps2", sa);
+ ret = request_irq(ps2if->dev->irq[0], ps2_rxint, 0,
+ SA1111_DRIVER_NAME(ps2if->dev), ps2if);
if (ret) {
printk(KERN_ERR "sa1111ps2: could not allocate IRQ%d: %d\n",
- sa->irq, ret);
+ ps2if->dev->irq[0], ret);
return ret;
}
- sa1111_writel(PS2CR_ENA, sa->base + SA1111_PS2CR);
+ ret = request_irq(ps2if->dev->irq[1], ps2_txint, 0,
+ SA1111_DRIVER_NAME(ps2if->dev), ps2if);
+ if (ret) {
+ printk(KERN_ERR "sa1111ps2: could not allocate IRQ%d: %d\n",
+ ps2if->dev->irq[1], ret);
+ free_irq(ps2if->dev->irq[0], ps2if);
+ return ret;
+ }
+ ps2if->open = 1;
+
+ sa1111_writel(PS2CR_ENA, ps2if->base + SA1111_PS2CR);
return 0;
}
static void ps2_close(struct serio *io)
{
- struct ps2if *sa = io->driver;
+ struct ps2if *ps2if = io->driver;
+
+ sa1111_writel(0, ps2if->base + SA1111_PS2CR);
- sa1111_writel(0, sa->base + SA1111_PS2CR);
+ ps2if->open = 0;
- free_irq(sa->irq, sa);
+ free_irq(ps2if->dev->irq[1], ps2if);
+ free_irq(ps2if->dev->irq[0], ps2if);
- sa1111_disable_device(sa->skpcr_mask);
+ sa1111_disable_device(ps2if->dev);
}
/*
* Clear the input buffer.
*/
-static void __init ps2_clear_input(struct ps2if *sa)
+static void __init ps2_clear_input(struct ps2if *ps2if)
{
int maxread = 100;
while (maxread--) {
- if ((sa1111_readl(sa->base + SA1111_PS2DATA) & 0xff) == 0xff)
+ if ((sa1111_readl(ps2if->base + SA1111_PS2DATA) & 0xff) == 0xff)
break;
}
}
static inline unsigned int
-ps2_test_one(struct ps2if *sa, unsigned int mask)
+ps2_test_one(struct ps2if *ps2if, unsigned int mask)
{
unsigned int val;
- sa1111_writel(PS2CR_ENA | mask, sa->base + SA1111_PS2CR);
+ sa1111_writel(PS2CR_ENA | mask, ps2if->base + SA1111_PS2CR);
udelay(2);
- val = sa1111_readl(sa->base + SA1111_PS2STAT);
+ val = sa1111_readl(ps2if->base + SA1111_PS2STAT);
return val & (PS2STAT_KBC | PS2STAT_KBD);
}
@@ -141,141 +193,168 @@ ps2_test_one(struct ps2if *sa, unsigned int mask)
* Test the keyboard interface. We basically check to make sure that
* we can drive each line to the keyboard independently of each other.
*/
-static int __init ps2_test(struct ps2if *sa)
+static int __init ps2_test(struct ps2if *ps2if)
{
unsigned int stat;
int ret = 0;
- stat = ps2_test_one(sa, PS2CR_FKC);
+ stat = ps2_test_one(ps2if, PS2CR_FKC);
if (stat != PS2STAT_KBD) {
- printk("Keyboard interface test failed[1]: %02x\n", stat);
+ printk("PS/2 interface test failed[1]: %02x\n", stat);
ret = -ENODEV;
}
- stat = ps2_test_one(sa, 0);
+ stat = ps2_test_one(ps2if, 0);
if (stat != (PS2STAT_KBC | PS2STAT_KBD)) {
- printk("Keyboard interface test failed[2]: %02x\n", stat);
+ printk("PS/2 interface test failed[2]: %02x\n", stat);
ret = -ENODEV;
}
- stat = ps2_test_one(sa, PS2CR_FKD);
+ stat = ps2_test_one(ps2if, PS2CR_FKD);
if (stat != PS2STAT_KBC) {
- printk("Keyboard interface test failed[3]: %02x\n", stat);
+ printk("PS/2 interface test failed[3]: %02x\n", stat);
ret = -ENODEV;
}
- sa1111_writel(0, sa->base + SA1111_PS2CR);
+ sa1111_writel(0, ps2if->base + SA1111_PS2CR);
return ret;
}
/*
- * Initialise one PS/2 port.
+ * Add one device to this driver.
*/
-static int __init ps2_init_one(struct sa1111_device *dev, struct ps2if *sa)
+static int ps2_probe(struct device *dev)
{
+ struct sa1111_dev *sadev = SA1111_DEV(dev);
+ struct ps2if *ps2if;
int ret;
+ ps2if = kmalloc(sizeof(struct ps2if), GFP_KERNEL);
+ if (!ps2if) {
+ return -ENOMEM;
+ }
+
+ memset(ps2if, 0, sizeof(struct ps2if));
+
+ ps2if->io.type = SERIO_8042;
+ ps2if->io.write = ps2_write;
+ ps2if->io.open = ps2_open;
+ ps2if->io.close = ps2_close;
+ ps2if->io.name = dev->name;
+ ps2if->io.phys = dev->bus_id;
+ ps2if->io.driver = ps2if;
+ ps2if->dev = sadev;
+ dev->driver_data = ps2if;
+
+ spin_lock_init(&ps2if->lock);
+
/*
* Request the physical region for this PS2 port.
*/
- sa->res = request_mem_region(_SA1111(sa->base), 512, "ps2");
- if (!sa->res)
- return -EBUSY;
+ if (!request_mem_region(sadev->res.start,
+ sadev->res.end - sadev->res.start + 1,
+ SA1111_DRIVER_NAME(sadev))) {
+ ret = -EBUSY;
+ goto free;
+ }
/*
- * Convert the chip offset to virtual address.
+ * Our parent device has already mapped the region.
*/
- sa->base += (unsigned long)dev->base;
+ ps2if->base = (unsigned long)sadev->mapbase;
- sa1111_enable_device(sa->skpcr_mask);
+ sa1111_enable_device(ps2if->dev);
/* Incoming clock is 8MHz */
- sa1111_writel(0, sa->base + SA1111_PS2CLKDIV);
- sa1111_writel(127, sa->base + SA1111_PS2PRECNT);
+ sa1111_writel(0, ps2if->base + SA1111_PS2CLKDIV);
+ sa1111_writel(127, ps2if->base + SA1111_PS2PRECNT);
/*
* Flush any pending input.
*/
- ps2_clear_input(sa);
+ ps2_clear_input(ps2if);
/*
* Test the keyboard interface.
*/
- ret = ps2_test(sa);
+ ret = ps2_test(ps2if);
if (ret)
goto out;
/*
* Flush any pending input.
*/
- ps2_clear_input(sa);
- sa1111_disable_device(sa->skpcr_mask);
+ ps2_clear_input(ps2if);
- serio_register_port(&sa->io);
+ sa1111_disable_device(ps2if->dev);
+ serio_register_port(&ps2if->io);
return 0;
out:
- sa1111_disable_device(sa->skpcr_mask);
- release_resource(sa->res);
+ sa1111_disable_device(ps2if->dev);
+ release_mem_region(sadev->res.start,
+ sadev->res.end - sadev->res.start + 1);
+ free:
+ dev->driver_data = NULL;
+ kfree(ps2if);
return ret;
}
/*
- * Remove one PS/2 port.
+ * Remove one device from this driver.
*/
-static void __exit ps2_remove_one(struct ps2if *sa)
+static int ps2_remove(struct device *dev)
{
- serio_unregister_port(&sa->io);
- release_resource(sa->res);
+ struct ps2if *ps2if = dev->driver_data;
+ struct sa1111_dev *sadev = SA1111_DEV(dev);
+
+ serio_unregister_port(&ps2if->io);
+ release_mem_region(sadev->res.start,
+ sadev->res.end - sadev->res.start + 1);
+ kfree(ps2if);
+
+ dev->driver_data = NULL;
+
+ return 0;
}
-static struct ps2if ps2_kbd_port =
+/*
+ * We should probably do something here, but what?
+ */
+static int ps2_suspend(struct device *dev, u32 state, u32 level)
{
- io: {
- type: SERIO_8042,
- write: ps2_write,
- open: ps2_open,
- close: ps2_close,
- name: "SA1111 PS/2 kbd port",
- phys: "sa1111/serio0",
- driver: &ps2_kbd_port,
- },
- base: SA1111_KBD,
- irq: IRQ_TPRXINT,
- skpcr_mask: SKPCR_PTCLKEN,
-};
+ return 0;
+}
-static struct ps2if ps2_mse_port =
+static int ps2_resume(struct device *dev, u32 level)
{
- io: {
- type: SERIO_8042,
- write: ps2_write,
- open: ps2_open,
- close: ps2_close,
- name: "SA1111 PS/2 mouse port",
- phys: "sa1111/serio1",
- driver: &ps2_mse_port,
+ return 0;
+}
+
+/*
+ * Our device driver structure
+ */
+static struct sa1111_driver ps2_driver = {
+ .drv = {
+ .name = "SA1111 PS2",
+ .bus = &sa1111_bus_type,
+ .probe = ps2_probe,
+ .remove = ps2_remove,
+ .suspend = ps2_suspend,
+ .resume = ps2_resume,
},
- base: SA1111_MSE,
- irq: IRQ_MSRXINT,
- skpcr_mask: SKPCR_PMCLKEN,
+ .devid = SA1111_DEVID_PS2,
};
static int __init ps2_init(void)
{
- int ret = -ENODEV;
-
- if (sa1111) {
- ret = ps2_init_one(sa1111, &ps2_kbd_port);
- }
-
- return ret;
+ return driver_register(&ps2_driver.drv);
}
static void __exit ps2_exit(void)
{
- ps2_remove_one(&ps2_kbd_port);
+ remove_driver(&ps2_driver.drv);
}
module_init(ps2_init);
diff --git a/drivers/mtd/nand/nand_ecc.c b/drivers/mtd/nand/nand_ecc.c
index 419352a59a9a..c4723d6b9a91 100644
--- a/drivers/mtd/nand/nand_ecc.c
+++ b/drivers/mtd/nand/nand_ecc.c
@@ -209,3 +209,5 @@ EXPORT_SYMBOL(nand_calculate_ecc);
EXPORT_SYMBOL(nand_correct_data);
MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Steven J. Hill <sjhill@cotw.com>");
+MODULE_DESCRIPTION("Generic NAND ECC support");
diff --git a/drivers/net/3c505.c b/drivers/net/3c505.c
index 95a37439b60e..e943a37d1b78 100644
--- a/drivers/net/3c505.c
+++ b/drivers/net/3c505.c
@@ -1396,7 +1396,7 @@ static int __init elp_sense(struct net_device *dev)
int timeout;
int addr = dev->base_addr;
const char *name = dev->name;
- unsigned long flags;
+ unsigned long flags;
byte orig_HSR;
if (!request_region(addr, ELP_IO_EXTENT, "3c505"))
diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c
index f96a49fb451f..277913d5810a 100644
--- a/drivers/net/3c509.c
+++ b/drivers/net/3c509.c
@@ -47,8 +47,8 @@
- ethtool support
v1.18b 1Mar2002 Zwane Mwaikambo <zwane@commfireservices.com>
- Power Management support
- v1.18c 1Mar2002 David Ruggiero <jdr@farfalle.com>
- - Full duplex support
+ v1.18c 1Mar2002 David Ruggiero <jdr@farfalle.com>
+ - Full duplex support
*/
#define DRV_NAME "3c509"
@@ -500,10 +500,10 @@ no_pnp:
memcpy(dev->dev_addr, phys_addr, sizeof(phys_addr));
dev->base_addr = ioaddr;
dev->irq = irq;
-
+
if (dev->mem_start & 0x05) { /* xcvr codes 1/3/4/12 */
dev->if_port = (dev->mem_start & 0x0f);
- } else { /* xcvr codes 0/8 */
+ } else { /* xcvr codes 0/8 */
/* use eeprom value, but save user's full-duplex selection */
dev->if_port = (if_port | (dev->mem_start & 0x08) );
}
diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c
index 4e73982ef6cc..1f5f873109fd 100644
--- a/drivers/net/arcnet/arcnet.c
+++ b/drivers/net/arcnet/arcnet.c
@@ -186,7 +186,7 @@ void cleanup_module(void)
void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb, char *desc)
{
int i;
- unsigned long flags;
+ unsigned long flags;
save_flags(flags);
cli();
@@ -212,7 +212,7 @@ void arcnet_dump_packet(struct net_device *dev, int bufnum, char *desc)
{
struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
int i, length;
- unsigned long flags;
+ unsigned long flags;
static uint8_t buf[512];
save_flags(flags);
diff --git a/drivers/net/at1700.c b/drivers/net/at1700.c
index 0798fde4d70d..8369c74f3a9e 100644
--- a/drivers/net/at1700.c
+++ b/drivers/net/at1700.c
@@ -808,7 +808,7 @@ set_rx_mode(struct net_device *dev)
int ioaddr = dev->base_addr;
struct net_local *lp = (struct net_local *)dev->priv;
unsigned char mc_filter[8]; /* Multicast hash filter */
- unsigned long flags;
+ unsigned long flags;
int i;
if (dev->flags & IFF_PROMISC) {
diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c
index 04d444580d09..1d96f745d377 100644
--- a/drivers/net/hamradio/scc.c
+++ b/drivers/net/hamradio/scc.c
@@ -2129,7 +2129,7 @@ static int __init scc_init_driver (void)
static void __exit scc_cleanup_driver(void)
{
- unsigned long flags;
+ unsigned long flags;
io_port ctrl;
int k;
struct scc_channel *scc;
diff --git a/drivers/net/ni65.c b/drivers/net/ni65.c
index d8d0b8e7f0ce..89567b878bbe 100644
--- a/drivers/net/ni65.c
+++ b/drivers/net/ni65.c
@@ -1108,7 +1108,7 @@ static int ni65_send_packet(struct sk_buff *skb, struct net_device *dev)
{
short len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
struct tmd *tmdp;
- unsigned long flags;
+ unsigned long flags;
#ifdef XMT_VIA_SKB
if( (unsigned long) (skb->data + skb->len) > 0x1000000) {
diff --git a/drivers/net/pcmcia/aironet4500_cs.c b/drivers/net/pcmcia/aironet4500_cs.c
index ee55cc72461a..b73062178a1a 100644
--- a/drivers/net/pcmcia/aironet4500_cs.c
+++ b/drivers/net/pcmcia/aironet4500_cs.c
@@ -347,7 +347,7 @@ static dev_link_t *awc_attach(void)
static void awc_detach(dev_link_t *link)
{
dev_link_t **linkp;
- unsigned long flags;
+ unsigned long flags;
int i=0;
DEBUG(0, "awc_detach(0x%p)\n", link);
diff --git a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c
index 6b67bce267b8..46c165dc05c2 100644
--- a/drivers/net/skfp/skfddi.c
+++ b/drivers/net/skfp/skfddi.c
@@ -188,6 +188,7 @@ static struct pci_device_id skfddi_pci_tbl[] __initdata = {
};
MODULE_DEVICE_TABLE(pci, skfddi_pci_tbl);
MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mirko Lindner <mlindner@syskonnect.de>");
// Define module-wide (static) variables
diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c
index 44a90557395f..964fe65f670f 100644
--- a/drivers/net/tc35815.c
+++ b/drivers/net/tc35815.c
@@ -40,7 +40,7 @@ static const char *version =
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
#include <linux/string.h>
#include <asm/system.h>
#include <asm/bitops.h>
diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c
index 9eaf6ccdd952..ea19b98b2613 100644
--- a/drivers/net/tokenring/olympic.c
+++ b/drivers/net/tokenring/olympic.c
@@ -128,7 +128,7 @@ static char *open_min_error[] = {"No error", "Function Failure", "Signal Lost",
/* Module paramters */
MODULE_AUTHOR("Mike Phillips <mikep@linuxtr.net>") ;
-MODULE_DESCRIPTION("Olympic PCI/Cardbus Chipset Driver \n") ;
+MODULE_DESCRIPTION("Olympic PCI/Cardbus Chipset Driver") ;
/* Ring Speed 0,4,16,100
* 0 = Autosense
diff --git a/drivers/net/wan/lmc/lmc_var.h b/drivers/net/wan/lmc/lmc_var.h
index ee022f373917..41d9bdb08d1a 100644
--- a/drivers/net/wan/lmc/lmc_var.h
+++ b/drivers/net/wan/lmc/lmc_var.h
@@ -87,7 +87,7 @@ typedef struct lmc___ctl lmc_ctl_t;
lmc_delay(); \
LMC_CSR_WRITE((sc), csr_9, 0x30000); \
lmc_delay(); \
- n--; }} while(0);
+ n--; }} while(0)
struct lmc_regfile_t {
lmc_csrptr_t csr_busmode; /* CSR0 */
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 43aea3183d77..1a428abefc59 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -90,7 +90,7 @@ static void __init quirk_triton(struct pci_dev *dev)
* VIA Apollo KT133 needs PCI latency patch
* Made according to a windows driver based patch by George E. Breese
* see PCI Latency Adjust on http://www.viahardware.com/download/viatweak.shtm
- * Also see http://home.tiscalinet.de/au-ja/review-kt133a-1-en.html for
+ * Also see http://www.au-ja.org/review-kt133a-1-en.phtml for
* the info on which Mr Breese based his work.
*
* Updated based on further information from the site and also on
diff --git a/drivers/pcmcia/Config.in b/drivers/pcmcia/Config.in
index 56866d225c48..4f8bfb546424 100644
--- a/drivers/pcmcia/Config.in
+++ b/drivers/pcmcia/Config.in
@@ -20,6 +20,7 @@ if [ "$CONFIG_PCMCIA" != "n" ]; then
fi
if [ "$CONFIG_ARM" = "y" ]; then
dep_tristate ' SA1100 support' CONFIG_PCMCIA_SA1100 $CONFIG_ARCH_SA1100 $CONFIG_PCMCIA
+ dep_tristate ' SA1111 support' CONFIG_PCMCIA_SA1111 $CONFIG_PCMCIA_SA1100 $CONFIG_SA1111 $CONFIG_PCMCIA
fi
fi
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
index 497523e5f7b1..734b5a5cec43 100644
--- a/drivers/pcmcia/Makefile
+++ b/drivers/pcmcia/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_I82092) += i82092.o
obj-$(CONFIG_TCIC) += tcic.o
obj-$(CONFIG_HD64465_PCMCIA) += hd64465_ss.o
obj-$(CONFIG_PCMCIA_SA1100) += sa1100_cs.o
+obj-$(CONFIG_PCMCIA_SA1111) += sa1111_cs.o
yenta_socket-objs := pci_socket.o yenta.o
@@ -21,26 +22,29 @@ pcmcia_core-objs-y := cistpl.o rsrc_mgr.o bulkmem.o cs.o
pcmcia_core-objs-$(CONFIG_CARDBUS) += cardbus.o
pcmcia_core-objs := $(pcmcia_core-objs-y)
+sa1111_cs-objs-y := sa1111_generic.o
+sa1111_cs-objs-$(CONFIG_SA1100_ADSBITSY) += sa1100_adsbitsy.o
+sa1111_cs-objs-$(CONFIG_ASSABET_NEPONSET) += sa1100_neponset.o
+sa1111_cs-objs-$(CONFIG_SA1100_BADGE4) += sa1100_badge4.o
+sa1111_cs-objs-$(CONFIG_SA1100_GRAPHICSMASTER) += sa1100_graphicsmaster.o
+sa1111_cs-objs-$(CONFIG_SA1100_JORNADA720) += sa1100_jornada720.o
+sa1111_cs-objs-$(CONFIG_SA1100_PFS168) += sa1100_pfs168.o
+sa1111_cs-objs-$(CONFIG_SA1100_PT_SYSTEM3) += sa1100_system3.o
+sa1111_cs-objs-$(CONFIG_SA1100_XP860) += sa1100_xp860.o
+sa1111_cs-objs := $(sa1111_cs-objs-y)
+
sa1100_cs-objs-y := sa1100_generic.o
-sa1100_cs-objs-$(CONFIG_SA1100_ADSBITSY) += sa1100_adsbitsy.o sa1111_generic.o
sa1100_cs-objs-$(CONFIG_SA1100_ASSABET) += sa1100_assabet.o
-sa1100_cs-objs-$(CONFIG_ASSABET_NEPONSET) += sa1100_neponset.o sa1111_generic.o
-sa1100_cs-objs-$(CONFIG_SA1100_BADGE4) += sa1100_badge4.o sa1111_generic.o
sa1100_cs-objs-$(CONFIG_SA1100_CERF) += sa1100_cerf.o
sa1100_cs-objs-$(CONFIG_SA1100_FLEXANET) += sa1100_flexanet.o
sa1100_cs-objs-$(CONFIG_SA1100_FREEBIRD) += sa1100_freebird.o
-sa1100_cs-objs-$(CONFIG_SA1100_GRAPHICSMASTER) += sa1100_graphicsmaster.o sa1111_generic.o
sa1100_cs-objs-$(CONFIG_SA1100_GRAPHICSCLIENT) += sa1100_graphicsclient.o
sa1100_cs-objs-$(CONFIG_SA1100_H3600) += sa1100_h3600.o
-sa1100_cs-objs-$(CONFIG_SA1100_JORNADA720) += sa1100_jornada720.o sa1111_generic.o
sa1100_cs-objs-$(CONFIG_SA1100_PANGOLIN) += sa1100_pangolin.o
-sa1100_cs-objs-$(CONFIG_SA1100_PFS168) += sa1100_pfs168.o sa1111_generic.o
-sa1100_cs-objs-$(CONFIG_SA1100_PT_SYSTEM3) += sa1100_system3.o sa1111_generic.o
sa1100_cs-objs-$(CONFIG_SA1100_SHANNON) += sa1100_shannon.o
sa1100_cs-objs-$(CONFIG_SA1100_SIMPAD) += sa1100_simpad.o
sa1100_cs-objs-$(CONFIG_SA1100_STORK) += sa1100_stork.o
sa1100_cs-objs-$(CONFIG_SA1100_TRIZEPS) += sa1100_trizeps.o
-sa1100_cs-objs-$(CONFIG_SA1100_XP860) += sa1100_xp860.o sa1111_generic.o
sa1100_cs-objs-$(CONFIG_SA1100_YOPY) += sa1100_yopy.o
sa1100_cs-objs := $(sa1100_cs-objs-y)
diff --git a/drivers/pcmcia/sa1100_adsbitsy.c b/drivers/pcmcia/sa1100_adsbitsy.c
index 17d87ab2e2a4..202524e4c354 100644
--- a/drivers/pcmcia/sa1100_adsbitsy.c
+++ b/drivers/pcmcia/sa1100_adsbitsy.c
@@ -14,6 +14,7 @@
#include <linux/init.h>
#include <asm/hardware.h>
+#include <asm/mach-types.h>
#include "sa1100_generic.h"
#include "sa1111_generic.h"
diff --git a/drivers/pcmcia/sa1100_badge4.c b/drivers/pcmcia/sa1100_badge4.c
index 546ec5d95102..77174645d6c1 100644
--- a/drivers/pcmcia/sa1100_badge4.c
+++ b/drivers/pcmcia/sa1100_badge4.c
@@ -19,6 +19,7 @@
#include <linux/init.h>
#include <asm/hardware.h>
+#include <asm/mach-types.h>
#include <asm/arch/badge4.h>
#include <asm/hardware/sa1111.h>
diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c
index 12dc9270e402..47f364fbc97b 100644
--- a/drivers/pcmcia/sa1100_generic.c
+++ b/drivers/pcmcia/sa1100_generic.c
@@ -110,12 +110,11 @@ sa1100_pcmcia_default_mecr_timing(unsigned int sock, unsigned int cpu_speed,
* Call board specific BS value calculation to allow boards
* to tweak the BS values.
*/
-static int sa1100_pcmcia_set_mecr(int sock)
+static int sa1100_pcmcia_set_mecr(int sock, unsigned int cpu_clock)
{
struct sa1100_pcmcia_socket *skt;
u32 mecr;
- int clock;
- long flags;
+ unsigned long flags;
unsigned int bs;
if (sock < 0 || sock > SA1100_PCMCIA_MAX_SOCK)
@@ -125,8 +124,7 @@ static int sa1100_pcmcia_set_mecr(int sock)
local_irq_save(flags);
- clock = cpufreq_get(0);
- bs = pcmcia_low_level->socket_get_timing(sock, clock, skt->speed_io);
+ bs = pcmcia_low_level->socket_get_timing(sock, cpu_clock, skt->speed_io);
mecr = MECR;
MECR_FAST_SET(mecr, sock, 0);
@@ -652,7 +650,7 @@ sa1100_pcmcia_set_io_map(unsigned int sock, struct pccard_io_map *map)
if ( map->speed == 0)
map->speed = SA1100_PCMCIA_IO_ACCESS;
- sa1100_pcmcia_set_mecr( sock );
+ sa1100_pcmcia_set_mecr(sock, cpufreq_get(0));
}
if (map->stop == 1)
@@ -741,7 +739,7 @@ sa1100_pcmcia_set_mem_map(unsigned int sock, struct pccard_mem_map *map)
map->speed = SA1100_PCMCIA_5V_MEM_ACCESS;
}
- sa1100_pcmcia_set_mecr( sock );
+ sa1100_pcmcia_set_mecr(sock, cpufreq_get(0));
}
@@ -885,9 +883,8 @@ static void sa1100_pcmcia_update_mecr(unsigned int clock)
{
unsigned int sock;
- for (sock = 0; sock < SA1100_PCMCIA_MAX_SOCK; ++sock) {
- sa1100_pcmcia_set_mecr(sock);
- }
+ for (sock = 0; sock < SA1100_PCMCIA_MAX_SOCK; ++sock)
+ sa1100_pcmcia_set_mecr(sock, clock);
}
/* sa1100_pcmcia_notifier()
@@ -904,31 +901,31 @@ static int
sa1100_pcmcia_notifier(struct notifier_block *nb, unsigned long val,
void *data)
{
- struct cpufreq_info *ci = data;
-
- switch (val) {
- case CPUFREQ_PRECHANGE:
- if (ci->new_freq > ci->old_freq) {
- DEBUG(2, "%s(): new frequency %u.%uMHz > %u.%uMHz, pre-updating\n",
- __FUNCTION__,
- ci->new_freq / 1000, (ci->new_freq / 100) % 10,
- ci->old_freq / 1000, (ci->old_freq / 100) % 10);
- sa1100_pcmcia_update_mecr(ci->new_freq);
- }
- break;
-
- case CPUFREQ_POSTCHANGE:
- if (ci->new_freq < ci->old_freq) {
- DEBUG(2, "%s(): new frequency %u.%uMHz < %u.%uMHz, post-updating\n",
- __FUNCTION__,
- ci->new_freq / 1000, (ci->new_freq / 100) % 10,
- ci->old_freq / 1000, (ci->old_freq / 100) % 10);
- sa1100_pcmcia_update_mecr(ci->new_freq);
- }
- break;
- }
+ struct cpufreq_freqs *freqs = data;
+
+ switch (val) {
+ case CPUFREQ_PRECHANGE:
+ if (freqs->new > freqs->old) {
+ DEBUG(2, "%s(): new frequency %u.%uMHz > %u.%uMHz, "
+ "pre-updating\n", __FUNCTION__,
+ freqs->new / 1000, (freqs->new / 100) % 10,
+ freqs->old / 1000, (freqs->old / 100) % 10);
+ sa1100_pcmcia_update_mecr(freqs->new);
+ }
+ break;
+
+ case CPUFREQ_POSTCHANGE:
+ if (freqs->new < freqs->old) {
+ DEBUG(2, "%s(): new frequency %u.%uMHz < %u.%uMHz, "
+ "post-updating\n", __FUNCTION__,
+ freqs->new / 1000, (freqs->new / 100) % 10,
+ freqs->old / 1000, (freqs->old / 100) % 10);
+ sa1100_pcmcia_update_mecr(freqs->new);
+ }
+ break;
+ }
- return 0;
+ return 0;
}
static struct notifier_block sa1100_pcmcia_notifier_block = {
@@ -946,7 +943,7 @@ int sa1100_register_pcmcia(struct pcmcia_low_level *ops)
struct pcmcia_init pcmcia_init;
struct pcmcia_state state[SA1100_PCMCIA_MAX_SOCK];
struct pcmcia_state_array state_array;
- unsigned int i;
+ unsigned int i, cpu_clock;
int ret;
/*
@@ -986,6 +983,8 @@ int sa1100_register_pcmcia(struct pcmcia_low_level *ops)
goto shutdown;
}
+ cpu_clock = cpufreq_get(0);
+
/*
* We initialize the MECR to default values here, because we are
* not guaranteed to see a SetIOMap operation at runtime.
@@ -1019,7 +1018,7 @@ int sa1100_register_pcmcia(struct pcmcia_low_level *ops)
goto out_err;
}
- sa1100_pcmcia_set_mecr( i );
+ sa1100_pcmcia_set_mecr(i, cpu_clock);
}
@@ -1110,7 +1109,7 @@ static int __init sa1100_pcmcia_init(void)
servinfo_t info;
int ret, i;
- printk(KERN_INFO "SA-1100 PCMCIA (CS release %s)\n", CS_RELEASE);
+ printk(KERN_INFO "SA11x0 PCMCIA (CS release %s)\n", CS_RELEASE);
CardServices(GetCardServicesInfo, &info);
if (info.Revision != CS_RELEASE_CODE) {
@@ -1127,7 +1126,8 @@ static int __init sa1100_pcmcia_init(void)
}
#ifdef CONFIG_CPU_FREQ
- ret = cpufreq_register_notifier(&sa1100_pcmcia_notifier_block);
+ ret = cpufreq_register_notifier(&sa1100_pcmcia_notifier_block,
+ CPUFREQ_TRANSITION_NOTIFIER);
if (ret < 0) {
printk(KERN_ERR "Unable to register CPU frequency change "
"notifier (%d)\n", ret);
@@ -1135,15 +1135,9 @@ static int __init sa1100_pcmcia_init(void)
}
#endif
-#ifdef CONFIG_SA1100_ADSBITSY
- pcmcia_adsbitsy_init();
-#endif
#ifdef CONFIG_SA1100_ASSABET
pcmcia_assabet_init();
#endif
-#ifdef CONFIG_SA1100_BADGE4
- pcmcia_badge4_init();
-#endif
#ifdef CONFIG_SA1100_CERF
pcmcia_cerf_init();
#endif
@@ -1156,24 +1150,9 @@ static int __init sa1100_pcmcia_init(void)
#ifdef CONFIG_SA1100_GRAPHICSCLIENT
pcmcia_gcplus_init();
#endif
-#ifdef CONFIG_SA1100_GRAPHICSMASTER
- pcmcia_graphicsmaster_init();
-#endif
-#ifdef CONFIG_SA1100_JORNADA720
- pcmcia_jornada720_init();
-#endif
-#ifdef CONFIG_ASSABET_NEPONSET
- pcmcia_neponset_init();
-#endif
#ifdef CONFIG_SA1100_PANGOLIN
pcmcia_pangolin_init();
#endif
-#ifdef CONFIG_SA1100_PFS168
- pcmcia_pfs_init();
-#endif
-#ifdef CONFIG_SA1100_PT_SYSTEM3
- pcmcia_system3_init();
-#endif
#ifdef CONFIG_SA1100_SHANNON
pcmcia_shannon_init();
#endif
@@ -1186,9 +1165,6 @@ static int __init sa1100_pcmcia_init(void)
#ifdef CONFIG_SA1100_TRIZEPS
pcmcia_trizeps_init();
#endif
-#ifdef CONFIG_SA1100_XP860
- pcmcia_xp860_init();
-#endif
#ifdef CONFIG_SA1100_YOPY
pcmcia_yopy_init();
#endif
@@ -1203,15 +1179,9 @@ static int __init sa1100_pcmcia_init(void)
*/
static void __exit sa1100_pcmcia_exit(void)
{
-#ifdef CONFIG_SA1100_ADSBITSY
- pcmcia_adsbitsy_exit();
-#endif
#ifdef CONFIG_SA1100_ASSABET
pcmcia_assabet_exit();
#endif
-#ifdef CONFIG_SA1100_BADGE4
- pcmcia_badge4_exit();
-#endif
#ifdef CONFIG_SA1100_CERF
pcmcia_cerf_exit();
#endif
@@ -1224,21 +1194,9 @@ static void __exit sa1100_pcmcia_exit(void)
#ifdef CONFIG_SA1100_GRAPHICSCLIENT
pcmcia_gcplus_exit();
#endif
-#ifdef CONFIG_SA1100_GRAPHICSMASTER
- pcmcia_graphicsmaster_exit();
-#endif
-#ifdef CONFIG_SA1100_JORNADA720
- pcmcia_jornada720_exit();
-#endif
-#ifdef CONFIG_ASSABET_NEPONSET
- pcmcia_neponset_exit();
-#endif
#ifdef CONFIG_SA1100_PANGOLIN
pcmcia_pangolin_exit();
#endif
-#ifdef CONFIG_SA1100_PFS168
- pcmcia_pfs_exit();
-#endif
#ifdef CONFIG_SA1100_SHANNON
pcmcia_shannon_exit();
#endif
@@ -1248,9 +1206,6 @@ static void __exit sa1100_pcmcia_exit(void)
#ifdef CONFIG_SA1100_STORK
pcmcia_stork_exit();
#endif
-#ifdef CONFIG_SA1100_XP860
- pcmcia_xp860_exit();
-#endif
#ifdef CONFIG_SA1100_YOPY
pcmcia_yopy_exit();
#endif
@@ -1261,7 +1216,7 @@ static void __exit sa1100_pcmcia_exit(void)
}
#ifdef CONFIG_CPU_FREQ
- cpufreq_unregister_notifier(&sa1100_pcmcia_notifier_block);
+ cpufreq_unregister_notifier(&sa1100_pcmcia_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
#endif
}
diff --git a/drivers/pcmcia/sa1100_graphicsmaster.c b/drivers/pcmcia/sa1100_graphicsmaster.c
index 8aeafa167cff..9552dfa55816 100644
--- a/drivers/pcmcia/sa1100_graphicsmaster.c
+++ b/drivers/pcmcia/sa1100_graphicsmaster.c
@@ -13,6 +13,7 @@
#include <linux/init.h>
#include <asm/hardware.h>
+#include <asm/mach-types.h>
#include "sa1100_generic.h"
#include "sa1111_generic.h"
diff --git a/drivers/pcmcia/sa1100_jornada720.c b/drivers/pcmcia/sa1100_jornada720.c
index a5d07781929a..d15f51eedba6 100644
--- a/drivers/pcmcia/sa1100_jornada720.c
+++ b/drivers/pcmcia/sa1100_jornada720.c
@@ -9,6 +9,7 @@
#include <linux/init.h>
#include <asm/hardware.h>
+#include <asm/mach-types.h>
#include "sa1100_generic.h"
#include "sa1111_generic.h"
diff --git a/drivers/pcmcia/sa1100_neponset.c b/drivers/pcmcia/sa1100_neponset.c
index d8e09192bacc..12d6c5c662f9 100644
--- a/drivers/pcmcia/sa1100_neponset.c
+++ b/drivers/pcmcia/sa1100_neponset.c
@@ -10,21 +10,50 @@
#include <linux/init.h>
#include <asm/hardware.h>
-#include <asm/arch/assabet.h>
+#include <asm/mach-types.h>
+#include <asm/arch/neponset.h>
#include <asm/hardware/sa1111.h>
#include "sa1100_generic.h"
#include "sa1111_generic.h"
+/*
+ * Neponset uses the Maxim MAX1600, with the following connections:
+ *
+ * MAX1600 Neponset
+ *
+ * A0VCC SA-1111 GPIO A<1>
+ * A1VCC SA-1111 GPIO A<0>
+ * A0VPP CPLD NCR A0VPP
+ * A1VPP CPLD NCR A1VPP
+ * B0VCC SA-1111 GPIO A<2>
+ * B1VCC SA-1111 GPIO A<3>
+ * B0VPP ground (slot B is CF)
+ * B1VPP ground (slot B is CF)
+ *
+ * VX VCC (5V)
+ * VY VCC3_3 (3.3V)
+ * 12INA 12V
+ * 12INB ground (slot B is CF)
+ *
+ * The MAX1600 CODE pin is tied to ground, placing the device in
+ * "Standard Intel code" mode. Refer to the Maxim data sheet for
+ * the corresponding truth table.
+ */
+
static int neponset_pcmcia_init(struct pcmcia_init *init)
{
- /* Set GPIO_A<3:0> to be outputs for PCMCIA/CF power controller: */
- PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
-
- /* MAX1600 to standby mode: */
- PA_DWR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
NCR_0 &= ~(NCR_A0VPP | NCR_A1VPP);
+ /*
+ * Set GPIO_A<3:0> to be outputs for the MAX1600,
+ * and switch to standby mode.
+ */
+ PA_DDR = 0;
+ PA_SDR = 0;
+ PA_DWR = 0;
+ PA_SSR = 0;
+
return sa1111_pcmcia_init(init);
}
@@ -35,29 +64,6 @@ neponset_pcmcia_configure_socket(const struct pcmcia_configure *conf)
unsigned int ncr_set, pa_dwr_set;
int ret;
- /* Neponset uses the Maxim MAX1600, with the following connections:
-
- * MAX1600 Neponset
- *
- * A0VCC SA-1111 GPIO A<1>
- * A1VCC SA-1111 GPIO A<0>
- * A0VPP CPLD NCR A0VPP
- * A1VPP CPLD NCR A1VPP
- * B0VCC SA-1111 GPIO A<2>
- * B1VCC SA-1111 GPIO A<3>
- * B0VPP ground (slot B is CF)
- * B1VPP ground (slot B is CF)
- *
- * VX VCC (5V)
- * VY VCC3_3 (3.3V)
- * 12INA 12V
- * 12INB ground (slot B is CF)
- *
- * The MAX1600 CODE pin is tied to ground, placing the device in
- * "Standard Intel code" mode. Refer to the Maxim data sheet for
- * the corresponding truth table.
- */
-
switch (conf->sock) {
case 0:
pa_dwr_mask = GPIO_GPIO0 | GPIO_GPIO1;
@@ -135,13 +141,13 @@ int __init pcmcia_neponset_init(void)
{
int ret = -ENODEV;
- if (machine_is_assabet() && sa1111)
+ if (machine_is_assabet())
ret = sa1100_register_pcmcia(&neponset_pcmcia_ops);
return ret;
}
-void __exit pcmcia_neponset_exit(void)
+void __devexit pcmcia_neponset_exit(void)
{
sa1100_unregister_pcmcia(&neponset_pcmcia_ops);
}
diff --git a/drivers/pcmcia/sa1100_pfs168.c b/drivers/pcmcia/sa1100_pfs168.c
index af028d61b682..511afebb38a3 100644
--- a/drivers/pcmcia/sa1100_pfs168.c
+++ b/drivers/pcmcia/sa1100_pfs168.c
@@ -7,10 +7,11 @@
*/
#include <linux/kernel.h>
#include <linux/sched.h>
+#include <linux/delay.h>
#include <linux/init.h>
-#include <asm/delay.h>
#include <asm/hardware.h>
+#include <asm/mach-types.h>
#include <asm/irq.h>
#include "sa1100_generic.h"
diff --git a/drivers/pcmcia/sa1100_system3.c b/drivers/pcmcia/sa1100_system3.c
index fc4bed07c4a3..2ab0d4537d0d 100644
--- a/drivers/pcmcia/sa1100_system3.c
+++ b/drivers/pcmcia/sa1100_system3.c
@@ -31,6 +31,7 @@
#include <linux/ioport.h>
#include <asm/hardware.h>
+#include <asm/mach-types.h>
#include <asm/irq.h>
#include <asm/hardware/sa1111.h>
diff --git a/drivers/pcmcia/sa1100_xp860.c b/drivers/pcmcia/sa1100_xp860.c
index 84c315a97cdd..69d3f3ddaacc 100644
--- a/drivers/pcmcia/sa1100_xp860.c
+++ b/drivers/pcmcia/sa1100_xp860.c
@@ -10,6 +10,7 @@
#include <linux/init.h>
#include <asm/hardware.h>
+#include <asm/mach-types.h>
#include <asm/irq.h>
#include "sa1100_generic.h"
diff --git a/drivers/pcmcia/sa1111_generic.c b/drivers/pcmcia/sa1111_generic.c
index ef5a8b0bf153..9bf1a6c392d4 100644
--- a/drivers/pcmcia/sa1111_generic.c
+++ b/drivers/pcmcia/sa1111_generic.c
@@ -5,10 +5,12 @@
* basically means we handle everything except controlling the
* power. Power is machine specific...
*/
+#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/ioport.h>
#include <linux/device.h>
+#include <linux/init.h>
#include <asm/hardware.h>
#include <asm/hardware/sa1111.h>
@@ -21,19 +23,18 @@ static struct irqs {
int irq;
const char *str;
} irqs[] = {
- { S0_CD_VALID, "SA1111 PCMCIA card detect" },
- { S0_BVD1_STSCHG, "SA1111 PCMCIA BVD1" },
- { S1_CD_VALID, "SA1111 CF card detect" },
- { S1_BVD1_STSCHG, "SA1111 CF BVD1" },
+ { IRQ_S0_CD_VALID, "SA1111 PCMCIA card detect" },
+ { IRQ_S0_BVD1_STSCHG, "SA1111 PCMCIA BVD1" },
+ { IRQ_S1_CD_VALID, "SA1111 CF card detect" },
+ { IRQ_S1_BVD1_STSCHG, "SA1111 CF BVD1" },
};
+static struct sa1111_dev *pcmcia;
+
int sa1111_pcmcia_init(struct pcmcia_init *init)
{
int i, ret;
- if (!request_mem_region(_PCCR, 512, "PCMCIA"))
- return -1;
-
for (i = ret = 0; i < ARRAY_SIZE(irqs); i++) {
set_irq_type(irqs[i].irq, IRQT_FALLING);
ret = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT,
@@ -47,8 +48,6 @@ int sa1111_pcmcia_init(struct pcmcia_init *init)
irqs[i].irq, ret);
while (i--)
free_irq(irqs[i].irq, NULL);
-
- release_mem_region(_PCCR, 16);
}
return ret ? -1 : 2;
@@ -61,8 +60,6 @@ int sa1111_pcmcia_shutdown(void)
for (i = 0; i < ARRAY_SIZE(irqs); i++)
free_irq(irqs[i].irq, NULL);
- release_mem_region(_PCCR, 512);
-
return 0;
}
@@ -73,7 +70,7 @@ int sa1111_pcmcia_socket_state(struct pcmcia_state_array *state)
if (state->size < 2)
return -1;
- status = PCSR;
+ status = sa1111_readl(pcmcia->mapbase + SA1111_PCSR);
state->state[0].detect = status & PCSR_S0_DETECT ? 0 : 1;
state->state[0].ready = status & PCSR_S0_READY ? 1 : 0;
@@ -99,8 +96,8 @@ int sa1111_pcmcia_get_irq_info(struct pcmcia_irq_info *info)
int ret = 0;
switch (info->sock) {
- case 0: info->irq = S0_READY_NINT; break;
- case 1: info->irq = S1_READY_NINT; break;
+ case 0: info->irq = IRQ_S0_READY_NINT; break;
+ case 1: info->irq = IRQ_S1_READY_NINT; break;
default: ret = 1;
}
@@ -109,7 +106,7 @@ int sa1111_pcmcia_get_irq_info(struct pcmcia_irq_info *info)
int sa1111_pcmcia_configure_socket(const struct pcmcia_configure *conf)
{
- unsigned int rst, flt, wait, pse, irq, pccr_mask;
+ unsigned int rst, flt, wait, pse, irq, pccr_mask, val;
unsigned long flags;
switch (conf->sock) {
@@ -118,7 +115,7 @@ int sa1111_pcmcia_configure_socket(const struct pcmcia_configure *conf)
flt = PCCR_S0_FLT;
wait = PCCR_S0_PWAITEN;
pse = PCCR_S0_PSE;
- irq = S0_READY_NINT;
+ irq = IRQ_S0_READY_NINT;
break;
case 1:
@@ -126,7 +123,7 @@ int sa1111_pcmcia_configure_socket(const struct pcmcia_configure *conf)
flt = PCCR_S1_FLT;
wait = PCCR_S1_PWAITEN;
pse = PCCR_S1_PSE;
- irq = S1_READY_NINT;
+ irq = IRQ_S1_READY_NINT;
break;
default:
@@ -159,7 +156,9 @@ int sa1111_pcmcia_configure_socket(const struct pcmcia_configure *conf)
pccr_mask |= flt;
local_irq_save(flags);
- PCCR = (PCCR & ~(pse | flt | wait | rst)) | pccr_mask;
+ val = sa1111_readl(pcmcia->mapbase + SA1111_PCCR);
+ val = (val & ~(pse | flt | wait | rst)) | pccr_mask;
+ sa1111_writel(val, pcmcia->mapbase + SA1111_PCCR);
local_irq_restore(flags);
if (conf->irq)
@@ -179,3 +178,130 @@ int sa1111_pcmcia_socket_suspend(int sock)
{
return 0;
}
+
+static int pcmcia_probe(struct device *dev)
+{
+ struct sa1111_dev *sadev = SA1111_DEV(dev);
+ unsigned long flags;
+ char *base;
+
+ local_irq_save(flags);
+ if (pcmcia) {
+ local_irq_restore(flags);
+ return -EBUSY;
+ }
+
+ pcmcia = sadev;
+ local_irq_restore(flags);
+
+ if (!request_mem_region(sadev->res.start, 512,
+ SA1111_DRIVER_NAME(sadev)))
+ return -EBUSY;
+
+ base = sadev->mapbase;
+
+ /*
+ * Initialise the suspend state.
+ */
+ sa1111_writel(PCSSR_S0_SLEEP | PCSSR_S1_SLEEP, base + SA1111_PCSSR);
+ sa1111_writel(PCCR_S0_FLT | PCCR_S1_FLT, base + SA1111_PCCR);
+
+#ifdef CONFIG_SA1100_ADSBITSY
+ pcmcia_adsbitsy_init();
+#endif
+#ifdef CONFIG_SA1100_BADGE4
+ pcmcia_badge4_init();
+#endif
+#ifdef CONFIG_SA1100_GRAPHICSMASTER
+ pcmcia_graphicsmaster_init();
+#endif
+#ifdef CONFIG_SA1100_JORNADA720
+ pcmcia_jornada720_init();
+#endif
+#ifdef CONFIG_ASSABET_NEPONSET
+ pcmcia_neponset_init();
+#endif
+#ifdef CONFIG_SA1100_PFS168
+ pcmcia_pfs_init();
+#endif
+#ifdef CONFIG_SA1100_PT_SYSTEM3
+ pcmcia_system3_init();
+#endif
+#ifdef CONFIG_SA1100_XP860
+ pcmcia_xp860_init();
+#endif
+ return 0;
+}
+
+static int __devexit pcmcia_remove(struct device *dev)
+{
+ struct sa1111_dev *sadev = SA1111_DEV(dev);
+
+#ifdef CONFIG_SA1100_ADSBITSY
+ pcmcia_adsbitsy_exit();
+#endif
+#ifdef CONFIG_SA1100_BADGE4
+ pcmcia_badge4_exit();
+#endif
+#ifdef CONFIG_SA1100_GRAPHICSMASTER
+ pcmcia_graphicsmaster_exit();
+#endif
+#ifdef CONFIG_SA1100_JORNADA720
+ pcmcia_jornada720_exit();
+#endif
+#ifdef CONFIG_ASSABET_NEPONSET
+ pcmcia_neponset_exit();
+#endif
+#ifdef CONFIG_SA1100_PFS168
+ pcmcia_pfs_exit();
+#endif
+#ifdef CONFIG_SA1100_PT_SYSTEM3
+ pcmcia_system3_exit();
+#endif
+#ifdef CONFIG_SA1100_XP860
+ pcmcia_xp860_exit();
+#endif
+
+ release_mem_region(sadev->res.start, 512);
+ pcmcia = NULL;
+
+ return 0;
+}
+
+static int pcmcia_suspend(struct device *dev, u32 state, u32 level)
+{
+ return 0;
+}
+
+static int pcmcia_resume(struct device *dev, u32 level)
+{
+ return 0;
+}
+
+static struct sa1111_driver pcmcia_driver = {
+ .drv = {
+ .name = "SA1111 PCMCIA",
+ .bus = &sa1111_bus_type,
+ .probe = pcmcia_probe,
+ .remove = __devexit_p(pcmcia_remove),
+ .suspend = pcmcia_suspend,
+ .resume = pcmcia_resume,
+ },
+ .devid = SA1111_DEVID_PCMCIA,
+};
+
+static int __init sa1111_drv_pcmcia_init(void)
+{
+ return driver_register(&pcmcia_driver.drv);
+}
+
+static void __exit sa1111_drv_pcmcia_exit(void)
+{
+ remove_driver(&pcmcia_driver.drv);
+}
+
+module_init(sa1111_drv_pcmcia_init);
+module_exit(sa1111_drv_pcmcia_exit);
+
+MODULE_DESCRIPTION("SA1111 PCMCIA card socket driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tc/lk201-map.map b/drivers/tc/lk201-map.map
index a52acf7f9e20..2c636b4b7823 100644
--- a/drivers/tc/lk201-map.map
+++ b/drivers/tc/lk201-map.map
@@ -3,8 +3,8 @@ keymaps 0-2,4-5,8,12
# Change the above line into
# keymaps 0-2,4-6,8,12
# in case you want the entries
-# altgr control keycode 83 = Boot
-# altgr control keycode 111 = Boot
+# altgr control keycode 83 = Boot
+# altgr control keycode 111 = Boot
# below.
#
# In fact AltGr is used very little, and one more keymap can
diff --git a/drivers/tc/lk201-remap.c b/drivers/tc/lk201-remap.c
index 713fe9bafa51..d39098c2720e 100644
--- a/drivers/tc/lk201-remap.c
+++ b/drivers/tc/lk201-remap.c
@@ -1,17 +1,17 @@
/*
* Keyboard mappings for DEC LK201/401/501 keyboards
- *
+ *
* 17.05.99 Michael Engel (engel@unix-ag.org)
*
* DEC US keyboards generate keycodes in the range 0x55 - 0xfb
*
- * This conflicts with Linux scancode conventions which define
+ * This conflicts with Linux scancode conventions which define
* 0x00-0x7f as "normal" and 0x80-0xff as "shifted" scancodes, so we
* have to remap the keycodes to 0x00-0x7f with the scancodeRemap
* array. The generated scancode is simply the number of the key counted
* from the left upper to the right lower corner of the keyboard ...
*
- * These scancodes are then being remapped (I hope ;-)) with the
+ * These scancodes are then being remapped (I hope ;-)) with the
* lk501*map[] arrays which define scancode -> Linux code mapping
*
* Oh man is this horrible ;-)
@@ -91,7 +91,7 @@ unsigned char scancodeRemap[256] = {
/* ----- */
/* 60 */ 0, 0, 0, 0,
/* ----- F6 F7 F8 F9 */
-/* 64 */ 0x06, 0x07, 0x08, 0x09,
+/* 64 */ 0x06, 0x07, 0x08, 0x09,
/* ----- F10 */
/* 68 */ 0x0a, 0, 0, 0,
/* ----- */
diff --git a/drivers/tc/zs.h b/drivers/tc/zs.h
index cc9570b86520..7ce5a9b6ebb9 100644
--- a/drivers/tc/zs.h
+++ b/drivers/tc/zs.h
@@ -38,7 +38,7 @@ struct serial_struct {
/*
* Definitions for ZILOG_struct (and serial_struct) flags field
*/
-#define ZILOG_HUP_NOTIFY 0x0001 /* Notify getty on hangups and closes
+#define ZILOG_HUP_NOTIFY 0x0001 /* Notify getty on hangups and closes
on the callout port */
#define ZILOG_FOURPORT 0x0002 /* Set OU1, OUT2 per AST Fourport settings */
#define ZILOG_SAK 0x0004 /* Secure Attention Key (Orange book) */
@@ -74,7 +74,7 @@ struct serial_struct {
#ifdef __KERNEL__
/*
* This is our internal structure for each serial port's state.
- *
+ *
* Many fields are paralleled by the structure used by the serial_struct
* structure.
*
diff --git a/drivers/usb/class/bluetty.c b/drivers/usb/class/bluetty.c
index b2c097676307..e4e02db81f75 100644
--- a/drivers/usb/class/bluetty.c
+++ b/drivers/usb/class/bluetty.c
@@ -1006,9 +1006,7 @@ static void bluetooth_write_bulk_callback (struct urb *urb)
}
/* wake up our little function to let the tty layer know that something happened */
- queue_task(&bluetooth->tqueue, &tq_immediate);
- mark_bh(IMMEDIATE_BH);
- return;
+ schedule_task(&bluetooth->tqueue);
}
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 022ef711e81a..a048f123abd2 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -272,8 +272,7 @@ static void acm_write_bulk(struct urb *urb)
if (urb->status)
dbg("nonzero write bulk status received: %d", urb->status);
- queue_task(&acm->tqueue, &tq_immediate);
- mark_bh(IMMEDIATE_BH);
+ schedule_task(&acm->tqueue);
}
static void acm_softint(void *private)
diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile
index 87c3989fc246..a3be2618435a 100644
--- a/drivers/usb/core/Makefile
+++ b/drivers/usb/core/Makefile
@@ -5,7 +5,7 @@
export-objs := usb.o hcd.o hcd-pci.o urb.o message.o file.o buffer.o
usbcore-objs := usb.o usb-debug.o hub.o hcd.o urb.o message.o \
- config.o file.o buffer.o
+ config.o file.o buffer.o driverfs.o
ifeq ($(CONFIG_PCI),y)
usbcore-objs += hcd-pci.o
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index f4d58277aba0..c95b6e019606 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -1067,6 +1067,10 @@ static int proc_ioctl (struct dev_state *ps, void *arg)
/* disconnect kernel driver from interface, leaving it unbound. */
case USBDEVFS_DISCONNECT:
/* this function is voodoo. */
+ /* which function ... usb_device_remove()?
+ * FIXME either the module lock (BKL) should be involved
+ * here too, or the 'default' case below is broken
+ */
driver = ifp->driver;
if (driver) {
dbg ("disconnect '%s' from dev %d interface %d",
@@ -1081,26 +1085,28 @@ static int proc_ioctl (struct dev_state *ps, void *arg)
retval = usb_device_probe (&ifp->dev);
break;
- /* talk directly to the interface's driver */
- default:
- lock_kernel(); /* against module unload */
- driver = ifp->driver;
- if (driver == 0 || driver->ioctl == 0) {
+ /* talk directly to the interface's driver */
+ default:
+ /* BKL used here to protect against changing the binding
+ * of this driver to this device, as well as unloading its
+ * driver module.
+ */
+ lock_kernel ();
+ driver = ifp->driver;
+ if (driver == 0 || driver->ioctl == 0) {
unlock_kernel();
retval = -ENOSYS;
} else {
- if (ifp->driver->owner) {
- __MOD_INC_USE_COUNT(ifp->driver->owner);
- unlock_kernel();
- }
- /* ifno might usefully be passed ... */
- retval = driver->ioctl (ps->dev, ctrl.ioctl_code, buf);
- /* size = min_t(int, size, retval)? */
- if (ifp->driver->owner) {
- __MOD_DEC_USE_COUNT(ifp->driver->owner);
- } else {
+ if (driver->owner
+ && !try_inc_mod_count (driver->owner)) {
unlock_kernel();
+ retval = -ENOSYS;
+ break;
}
+ unlock_kernel ();
+ retval = driver->ioctl (ifp, ctrl.ioctl_code, buf);
+ if (driver->owner)
+ __MOD_DEC_USE_COUNT (driver->owner);
}
if (retval == -ENOIOCTLCMD)
diff --git a/drivers/usb/core/driverfs.c b/drivers/usb/core/driverfs.c
new file mode 100644
index 000000000000..37cca33513eb
--- /dev/null
+++ b/drivers/usb/core/driverfs.c
@@ -0,0 +1,177 @@
+/*
+ * drivers/usb/core/driverfs.c
+ *
+ * (C) Copyright 2002 David Brownell
+ * (C) Copyright 2002 Greg Kroah-Hartman
+ * (C) Copyright 2002 IBM Corp.
+ *
+ * All of the driverfs file attributes for usb devices and interfaces.
+ *
+ */
+
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+
+#ifdef CONFIG_USB_DEBUG
+ #define DEBUG
+#else
+ #undef DEBUG
+#endif
+#include <linux/usb.h>
+
+#include "usb.h"
+
+/* Active configuration fields */
+#define usb_actconfig_attr(field, format_string) \
+static ssize_t \
+show_##field (struct device *dev, char *buf, size_t count, loff_t off) \
+{ \
+ struct usb_device *udev; \
+ \
+ if (off) \
+ return 0; \
+ \
+ udev = to_usb_device (dev); \
+ return sprintf (buf, format_string, udev->actconfig->field); \
+} \
+static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL);
+
+usb_actconfig_attr (bNumInterfaces, "%2d\n")
+usb_actconfig_attr (bConfigurationValue, "%2d\n")
+usb_actconfig_attr (bmAttributes, "%2x\n")
+usb_actconfig_attr (MaxPower, "%3dmA\n")
+
+/* String fields */
+static ssize_t show_product (struct device *dev, char *buf, size_t count, loff_t off)
+{
+ struct usb_device *udev;
+ int len;
+
+ if (off)
+ return 0;
+ udev = to_usb_device (dev);
+
+ len = usb_string(udev, udev->descriptor.iProduct, buf, PAGE_SIZE);
+ if (len < 0)
+ return 0;
+ buf[len] = '\n';
+ buf[len+1] = 0;
+ return len+1;
+}
+static DEVICE_ATTR(product,S_IRUGO,show_product,NULL);
+
+static ssize_t
+show_manufacturer (struct device *dev, char *buf, size_t count, loff_t off)
+{
+ struct usb_device *udev;
+ int len;
+
+ if (off)
+ return 0;
+ udev = to_usb_device (dev);
+
+ len = usb_string(udev, udev->descriptor.iManufacturer, buf, PAGE_SIZE);
+ if (len < 0)
+ return 0;
+ buf[len] = '\n';
+ buf[len+1] = 0;
+ return len+1;
+}
+static DEVICE_ATTR(manufacturer,S_IRUGO,show_manufacturer,NULL);
+
+static ssize_t
+show_serial (struct device *dev, char *buf, size_t count, loff_t off)
+{
+ struct usb_device *udev;
+ int len;
+
+ if (off)
+ return 0;
+ udev = to_usb_device (dev);
+
+ len = usb_string(udev, udev->descriptor.iSerialNumber, buf, PAGE_SIZE);
+ if (len < 0)
+ return 0;
+ buf[len] = '\n';
+ buf[len+1] = 0;
+ return len+1;
+}
+static DEVICE_ATTR(serial,S_IRUGO,show_serial,NULL);
+
+/* Descriptor fields */
+#define usb_descriptor_attr(field, format_string) \
+static ssize_t \
+show_##field (struct device *dev, char *buf, size_t count, loff_t off) \
+{ \
+ struct usb_device *udev; \
+ \
+ if (off) \
+ return 0; \
+ \
+ udev = to_usb_device (dev); \
+ return sprintf (buf, format_string, udev->descriptor.field); \
+} \
+static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL);
+
+usb_descriptor_attr (idVendor, "%04x\n")
+usb_descriptor_attr (idProduct, "%04x\n")
+usb_descriptor_attr (bcdDevice, "%04x\n")
+usb_descriptor_attr (bDeviceClass, "%02x\n")
+usb_descriptor_attr (bDeviceSubClass, "%02x\n")
+usb_descriptor_attr (bDeviceProtocol, "%02x\n")
+
+
+void usb_create_driverfs_dev_files (struct usb_device *udev)
+{
+ struct device *dev = &udev->dev;
+
+ device_create_file (dev, &dev_attr_bNumInterfaces);
+ device_create_file (dev, &dev_attr_bConfigurationValue);
+ device_create_file (dev, &dev_attr_bmAttributes);
+ device_create_file (dev, &dev_attr_MaxPower);
+ device_create_file (dev, &dev_attr_idVendor);
+ device_create_file (dev, &dev_attr_idProduct);
+ device_create_file (dev, &dev_attr_bcdDevice);
+ device_create_file (dev, &dev_attr_bDeviceClass);
+ device_create_file (dev, &dev_attr_bDeviceSubClass);
+ device_create_file (dev, &dev_attr_bDeviceProtocol);
+
+ if (udev->descriptor.iManufacturer)
+ device_create_file (dev, &dev_attr_manufacturer);
+ if (udev->descriptor.iProduct)
+ device_create_file (dev, &dev_attr_product);
+ if (udev->descriptor.iSerialNumber)
+ device_create_file (dev, &dev_attr_serial);
+}
+
+/* Interface fields */
+#define usb_intf_attr(field, format_string) \
+static ssize_t \
+show_##field (struct device *dev, char *buf, size_t count, loff_t off) \
+{ \
+ struct usb_interface *intf; \
+ int alt; \
+ \
+ if (off) \
+ return 0; \
+ \
+ intf = to_usb_interface (dev); \
+ alt = intf->act_altsetting; \
+ \
+ return sprintf (buf, format_string, intf->altsetting[alt].field); \
+} \
+static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL);
+
+usb_intf_attr (bAlternateSetting, "%2d\n")
+usb_intf_attr (bInterfaceClass, "%02x\n")
+usb_intf_attr (bInterfaceSubClass, "%02x\n")
+usb_intf_attr (bInterfaceProtocol, "%02x\n")
+
+void usb_create_driverfs_intf_files (struct usb_interface *intf)
+{
+ device_create_file (&intf->dev, &dev_attr_bAlternateSetting);
+ device_create_file (&intf->dev, &dev_attr_bInterfaceClass);
+ device_create_file (&intf->dev, &dev_attr_bInterfaceSubClass);
+ device_create_file (&intf->dev, &dev_attr_bInterfaceProtocol);
+}
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index e73c157c943e..afd6d7ae9965 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1024,6 +1024,11 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags)
*/
urb = usb_get_urb (urb);
if (urb->dev == hcd->self.root_hub) {
+ /* NOTE: requirement on hub callers (usbfs and the hub
+ * driver, for now) that URBs' urb->transfer_buffer be
+ * valid and usb_buffer_{sync,unmap}() not be needed, since
+ * they could clobber root hub response data.
+ */
urb->transfer_flags |= URB_NO_DMA_MAP;
return rh_urb_enqueue (hcd, urb);
}
@@ -1132,11 +1137,11 @@ static int hcd_unlink_urb (struct urb *urb)
goto done;
}
- /* For non-periodic transfers, any status except -EINPROGRESS means
- * the HCD has already started to unlink this URB from the hardware.
- * In that case, there's no more work to do.
+ /* Except for interrupt transfers, any status except -EINPROGRESS
+ * means the HCD already started to unlink this URB from the hardware.
+ * So there's no more work to do.
*
- * For periodic transfers, this is the only way to trigger unlinking
+ * For interrupt transfers, this is the only way to trigger unlinking
* from the hardware. Since we (currently) overload urb->status to
* tell the driver to unlink, error status might get clobbered ...
* unless that transfer hasn't yet restarted. One such case is when
@@ -1144,13 +1149,10 @@ static int hcd_unlink_urb (struct urb *urb)
*
* FIXME use an URB_UNLINKED flag to match URB_TIMEOUT_KILLED
*/
- switch (usb_pipetype (urb->pipe)) {
- case PIPE_CONTROL:
- case PIPE_BULK:
- if (urb->status != -EINPROGRESS) {
- retval = -EINVAL;
- goto done;
- }
+ if (urb->status != -EINPROGRESS
+ && usb_pipetype (urb->pipe) != PIPE_INTERRUPT) {
+ retval = -EINVAL;
+ goto done;
}
/* maybe set up to block on completion notification */
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 650df33243a2..faaf25f59db9 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -537,7 +537,7 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
dev_set_drvdata (&intf->dev, hub);
if (usb_hub_configure(hub, endpoint) >= 0) {
- strcpy (intf->dev.name, "Hub/Port Status Changes");
+ strcpy (intf->dev.name, "Hub");
return 0;
}
@@ -547,8 +547,11 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
return -ENODEV;
}
-static int hub_ioctl(struct usb_device *hub, unsigned int code, void *user_data)
+static int
+hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)
{
+ struct usb_device *hub = interface_to_usbdev (intf);
+
/* assert ifno == 0 (part of hub spec) */
switch (code) {
case USBDEVFS_HUB_PORTINFO: {
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 91ac190c9569..8a6622cc611f 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -2,6 +2,7 @@
* message.c - synchronous message handling
*/
+#include <linux/pci.h> /* for scatterlist macros */
#include <linux/usb.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -123,6 +124,9 @@ int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe,
* Don't use this function from within an interrupt context, like a
* bottom half handler. If you need an asynchronous message, or need to send
* a message from within interrupt context, use usb_submit_urb()
+ * If a thread in your driver uses this call, make sure your disconnect()
+ * method can wait for it to complete. Since you don't have a handle on
+ * the URB used, you can't cancel the request.
*/
int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype,
__u16 value, __u16 index, void *data, __u16 size, int timeout)
@@ -170,6 +174,9 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u
* Don't use this function from within an interrupt context, like a
* bottom half handler. If you need an asynchronous message, or need to
* send a message from within interrupt context, use usb_submit_urb()
+ * If a thread in your driver uses this call, make sure your disconnect()
+ * method can wait for it to complete. Since you don't have a handle on
+ * the URB used, you can't cancel the request.
*/
int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
void *data, int len, int *actual_length, int timeout)
@@ -189,6 +196,321 @@ int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
return usb_start_wait_urb(urb,timeout,actual_length);
}
+/*-------------------------------------------------------------------*/
+
+static void sg_clean (struct usb_sg_request *io)
+{
+ if (io->urbs) {
+ while (io->entries--)
+ usb_free_urb (io->urbs [io->entries]);
+ kfree (io->urbs);
+ io->urbs = 0;
+ }
+ usb_buffer_unmap_sg (io->dev, io->pipe, io->sg, io->nents);
+ io->dev = 0;
+}
+
+static void sg_complete (struct urb *urb)
+{
+ struct usb_sg_request *io = (struct usb_sg_request *) urb->context;
+ unsigned long flags;
+
+ spin_lock_irqsave (&io->lock, flags);
+
+ /* In 2.5 we require hcds' endpoint queues not to progress after fault
+ * reports, until the competion callback (this!) returns. That lets
+ * device driver code (like this routine) unlink queued urbs first,
+ * if it needs to, since the HC won't work on them at all. So it's
+ * not possible for page N+1 to overwrite page N, and so on.
+ */
+ if (io->status && urb->actual_length) {
+ err ("driver for bus %s dev %s ep %d-%s corrupted data!",
+ io->dev->bus->bus_name, io->dev->devpath,
+ usb_pipeendpoint (urb->pipe),
+ usb_pipein (urb->pipe) ? "in" : "out");
+ // BUG ();
+ }
+
+ if (urb->status && urb->status != -ECONNRESET) {
+ int i, found, status;
+
+ io->status = urb->status;
+
+ /* the previous urbs, and this one, completed already.
+ * unlink the later ones so they won't rx/tx bad data,
+ *
+ * FIXME don't bother unlinking urbs that haven't yet been
+ * submitted; those non-error cases shouldn't be syslogged
+ */
+ for (i = 0, found = 0; i < io->entries; i++) {
+ if (found) {
+ status = usb_unlink_urb (io->urbs [i]);
+ if (status && status != -EINPROGRESS)
+ err ("sg_complete, unlink --> %d",
+ status);
+ } else if (urb == io->urbs [i])
+ found = 1;
+ }
+ }
+
+ /* on the last completion, signal usb_sg_wait() */
+ io->bytes += urb->actual_length;
+ io->count--;
+ if (!io->count)
+ complete (&io->complete);
+
+ spin_unlock_irqrestore (&io->lock, flags);
+}
+
+
+/**
+ * usb_sg_init - initializes scatterlist-based bulk/interrupt I/O request
+ * @io: request block being initialized. until usb_sg_wait() returns,
+ * treat this as a pointer to an opaque block of memory,
+ * @dev: the usb device that will send or receive the data
+ * @pipe: endpoint "pipe" used to transfer the data
+ * @period: polling rate for interrupt endpoints, in frames or
+ * (for high speed endpoints) microframes; ignored for bulk
+ * @sg: scatterlist entries
+ * @nents: how many entries in the scatterlist
+ * @length: how many bytes to send from the scatterlist, or zero to
+ * send every byte identified in the list.
+ * @mem_flags: SLAB_* flags affecting memory allocations in this call
+ *
+ * Returns zero for success, else a negative errno value. This initializes a
+ * scatter/gather request, allocating resources such as I/O mappings and urb
+ * memory (except maybe memory used by USB controller drivers).
+ *
+ * The request must be issued using usb_sg_wait(), which waits for the I/O to
+ * complete (or to be canceled) and then cleans up all resources allocated by
+ * usb_sg_init().
+ *
+ * The request may be canceled with usb_sg_cancel(), either before or after
+ * usb_sg_wait() is called.
+ *
+ * NOTE:
+ *
+ * At this writing, don't use the interrupt transfer mode, since the old old
+ * "automagic resubmit" mode hasn't yet been removed. It should be removed
+ * by the time 2.5 finalizes.
+ */
+int usb_sg_init (
+ struct usb_sg_request *io,
+ struct usb_device *dev,
+ unsigned pipe,
+ unsigned period,
+ struct scatterlist *sg,
+ int nents,
+ size_t length,
+ int mem_flags
+)
+{
+ int i;
+ int urb_flags;
+
+ if (!io || !dev || !sg
+ || usb_pipecontrol (pipe)
+ || usb_pipeisoc (pipe)
+ || nents <= 0)
+ return -EINVAL;
+
+ spin_lock_init (&io->lock);
+ io->dev = dev;
+ io->pipe = pipe;
+ io->sg = sg;
+ io->nents = nents;
+
+ /* initialize all the urbs we'll use */
+ io->entries = usb_buffer_map_sg (dev, pipe, sg, nents);
+ if (io->entries <= 0)
+ return io->entries;
+
+ io->count = 0;
+ io->urbs = kmalloc (io->entries * sizeof *io->urbs, mem_flags);
+ if (!io->urbs)
+ goto nomem;
+
+ urb_flags = USB_ASYNC_UNLINK | URB_NO_DMA_MAP | URB_NO_INTERRUPT;
+ if (usb_pipein (pipe))
+ urb_flags |= URB_SHORT_NOT_OK;
+
+ for (i = 0; i < io->entries; i++, io->count = i) {
+ unsigned len;
+
+ io->urbs [i] = usb_alloc_urb (0, mem_flags);
+ if (!io->urbs [i]) {
+ io->entries = i;
+ goto nomem;
+ }
+
+ io->urbs [i]->dev = dev;
+ io->urbs [i]->pipe = pipe;
+ io->urbs [i]->interval = period;
+ io->urbs [i]->transfer_flags = urb_flags;
+
+ io->urbs [i]->complete = sg_complete;
+ io->urbs [i]->context = io;
+ io->urbs [i]->status = -EINPROGRESS;
+ io->urbs [i]->actual_length = 0;
+
+ io->urbs [i]->transfer_dma = sg_dma_address (sg + i);
+ len = sg_dma_len (sg + i);
+ if (length) {
+ len = min_t (unsigned, len, length);
+ length -= len;
+ if (length == 0)
+ io->entries = i + 1;
+ }
+ io->urbs [i]->transfer_buffer_length = len;
+ }
+ io->urbs [--i]->transfer_flags &= ~URB_NO_INTERRUPT;
+
+ /* transaction state */
+ io->status = 0;
+ io->bytes = 0;
+ init_completion (&io->complete);
+ return 0;
+
+nomem:
+ sg_clean (io);
+ return -ENOMEM;
+}
+
+
+/**
+ * usb_sg_wait - synchronously execute scatter/gather request
+ * @io: request block handle, as initialized with usb_sg_init().
+ * some fields become accessible when this call returns.
+ * Context: !in_interrupt ()
+ *
+ * This function blocks until the specified I/O operation completes. It
+ * leverages the grouping of the related I/O requests to get good transfer
+ * rates, by queueing the requests. At higher speeds, such queuing can
+ * significantly improve USB throughput.
+ *
+ * There are three kinds of completion for this function.
+ * (1) success, where io->status is zero. The number of io->bytes
+ * transferred is as requested.
+ * (2) error, where io->status is a negative errno value. The number
+ * of io->bytes transferred before the error is usually less
+ * than requested, and can be nonzero.
+ * (3) cancelation, a type of error with status -ECONNRESET that
+ * is initiated by usb_sg_cancel().
+ *
+ * When this function returns, all memory allocated through usb_sg_init() or
+ * this call will have been freed. The request block parameter may still be
+ * passed to usb_sg_cancel(), or it may be freed. It could also be
+ * reinitialized and then reused.
+ *
+ * Data Transfer Rates:
+ *
+ * Bulk transfers are valid for full or high speed endpoints.
+ * The best full speed data rate is 19 packets of 64 bytes each
+ * per frame, or 1216 bytes per millisecond.
+ * The best high speed data rate is 13 packets of 512 bytes each
+ * per microframe, or 52 KBytes per millisecond.
+ *
+ * The reason to use interrupt transfers through this API would most likely
+ * be to reserve high speed bandwidth, where up to 24 KBytes per millisecond
+ * could be transferred. That capability is less useful for low or full
+ * speed interrupt endpoints, which allow at most one packet per millisecond,
+ * of at most 8 or 64 bytes (respectively).
+ */
+void usb_sg_wait (struct usb_sg_request *io)
+{
+ int i;
+ unsigned long flags;
+
+ /* queue the urbs. */
+ spin_lock_irqsave (&io->lock, flags);
+ for (i = 0; i < io->entries && !io->status; i++) {
+ int retval;
+
+ retval = usb_submit_urb (io->urbs [i], SLAB_ATOMIC);
+
+ /* after we submit, let completions or cancelations fire;
+ * we handshake using io->status.
+ */
+ spin_unlock_irqrestore (&io->lock, flags);
+ switch (retval) {
+ /* maybe we retrying will recover */
+ case -ENXIO: // hc didn't queue this one
+ case -EAGAIN:
+ case -ENOMEM:
+ retval = 0;
+ i--;
+ // FIXME: should it usb_sg_cancel() on INTERRUPT?
+ // how about imposing a backoff?
+ set_current_state (TASK_UNINTERRUPTIBLE);
+ schedule ();
+ break;
+
+ /* no error? continue immediately.
+ *
+ * NOTE: to work better with UHCI (4K I/O buffer may
+ * need 3K of TDs) it may be good to limit how many
+ * URBs are queued at once; N milliseconds?
+ */
+ case 0:
+ cpu_relax ();
+ break;
+
+ /* fail any uncompleted urbs */
+ default:
+ io->urbs [i]->status = retval;
+ dbg ("usb_sg_msg, submit --> %d", retval);
+ usb_sg_cancel (io);
+ }
+ spin_lock_irqsave (&io->lock, flags);
+ if (retval && io->status == -ECONNRESET)
+ io->status = retval;
+ }
+ spin_unlock_irqrestore (&io->lock, flags);
+
+ /* OK, yes, this could be packaged as non-blocking.
+ * So could the submit loop above ... but it's easier to
+ * solve neither problem than to solve both!
+ */
+ wait_for_completion (&io->complete);
+
+ sg_clean (io);
+}
+
+/**
+ * usb_sg_cancel - stop scatter/gather i/o issued by usb_sg_wait()
+ * @io: request block, initialized with usb_sg_init()
+ *
+ * This stops a request after it has been started by usb_sg_wait().
+ * It can also prevents one initialized by usb_sg_init() from starting,
+ * so that call just frees resources allocated to the request.
+ */
+void usb_sg_cancel (struct usb_sg_request *io)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave (&io->lock, flags);
+
+ /* shut everything down, if it didn't already */
+ if (!io->status) {
+ int i;
+
+ io->status = -ECONNRESET;
+ for (i = 0; i < io->entries; i++) {
+ int retval;
+
+ if (!io->urbs [i]->dev)
+ continue;
+ retval = usb_unlink_urb (io->urbs [i]);
+ if (retval && retval != -EINPROGRESS)
+ warn ("usb_sg_cancel, unlink --> %d", retval);
+ // FIXME don't warn on "not yet submitted" error
+ }
+ }
+ spin_unlock_irqrestore (&io->lock, flags);
+}
+
+/*-------------------------------------------------------------------*/
+
/**
* usb_get_descriptor - issues a generic GET_DESCRIPTOR request
* @dev: the device whose descriptor is being retrieved
@@ -659,6 +981,11 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
// synchronous request completion model
EXPORT_SYMBOL(usb_control_msg);
EXPORT_SYMBOL(usb_bulk_msg);
+
+EXPORT_SYMBOL(usb_sg_init);
+EXPORT_SYMBOL(usb_sg_cancel);
+EXPORT_SYMBOL(usb_sg_wait);
+
// synchronous control message convenience routines
EXPORT_SYMBOL(usb_get_descriptor);
EXPORT_SYMBOL(usb_get_device_descriptor);
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index bc500771036b..30a2ba8585b1 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -232,22 +232,19 @@ int usb_submit_urb(struct urb *urb, int mem_flags)
return -EMSGSIZE;
}
- /* "high bandwidth" mode, 1-3 packets/uframe? */
- if (dev->speed == USB_SPEED_HIGH) {
- int mult;
- switch (temp) {
- case PIPE_ISOCHRONOUS:
- case PIPE_INTERRUPT:
- mult = 1 + ((max >> 11) & 0x03);
+ /* periodic transfers limit size per frame/uframe,
+ * but drivers only control those sizes for ISO.
+ * while we're checking, initialize return status.
+ */
+ if (temp == PIPE_ISOCHRONOUS) {
+ int n, len;
+
+ /* "high bandwidth" mode, 1-3 packets/uframe? */
+ if (dev->speed == USB_SPEED_HIGH) {
+ int mult = 1 + ((max >> 11) & 0x03);
max &= 0x03ff;
max *= mult;
}
- }
-
- /* periodic transfers limit size per frame/uframe */
- switch (temp) {
- case PIPE_ISOCHRONOUS: {
- int n, len;
if (urb->number_of_packets <= 0)
return -EINVAL;
@@ -255,13 +252,9 @@ int usb_submit_urb(struct urb *urb, int mem_flags)
len = urb->iso_frame_desc [n].length;
if (len < 0 || len > max)
return -EMSGSIZE;
+ urb->iso_frame_desc [n].status = -EXDEV;
+ urb->iso_frame_desc [n].actual_length = 0;
}
-
- }
- break;
- case PIPE_INTERRUPT:
- if (urb->transfer_buffer_length > max)
- return -EMSGSIZE;
}
/* the I/O buffer must be mapped/unmapped, except when length=0 */
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 57d6faaa621c..2040bf15e8a8 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -42,6 +42,7 @@
#include <linux/usb.h>
#include "hcd.h"
+#include "usb.h"
extern int usb_hub_init(void);
extern void usb_hub_cleanup(void);
@@ -123,6 +124,8 @@ int usb_device_remove(struct device *dev)
if (driver->owner) {
m = try_inc_mod_count(driver->owner);
if (m == 0) {
+ // FIXME this happens even when we just rmmod
+ // drivers that aren't in active use...
err("Dieing driver still bound to device.\n");
return -EIO;
}
@@ -524,9 +527,8 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp,
if (!dev)
return -ENODEV;
- /* check for generic driver, we do not call do hotplug calls for it */
if (dev->driver == &usb_generic_driver)
- return -ENODEV;
+ return 0;
intf = to_usb_interface(dev);
if (!intf)
@@ -629,98 +631,6 @@ static int usb_hotplug (struct device *dev, char **envp,
#endif /* CONFIG_HOTPLUG */
-/* driverfs files */
-
-/* devices have one current configuration, with one
- * or more interfaces that are used concurrently
- */
-static ssize_t
-show_config (struct device *dev, char *buf, size_t count, loff_t off)
-{
- struct usb_device *udev;
-
- if (off)
- return 0;
- udev = to_usb_device (dev);
- return sprintf (buf, "%u\n", udev->actconfig->bConfigurationValue);
-}
-
-static DEVICE_ATTR(configuration,S_IRUGO,show_config,NULL);
-
-/* interfaces have one current setting; alternates
- * can have different endpoints and class info.
- */
-static ssize_t
-show_altsetting (struct device *dev, char *buf, size_t count, loff_t off)
-{
- struct usb_interface *interface;
-
- if (off)
- return 0;
- interface = to_usb_interface (dev);
- return sprintf (buf, "%u\n", interface->altsetting->bAlternateSetting);
-}
-static DEVICE_ATTR(altsetting,S_IRUGO,show_altsetting,NULL);
-
-/* product driverfs file */
-static ssize_t show_product (struct device *dev, char *buf, size_t count, loff_t off)
-{
- struct usb_device *udev;
- int len;
-
- if (off)
- return 0;
- udev = to_usb_device (dev);
-
- len = usb_string(udev, udev->descriptor.iProduct, buf, PAGE_SIZE);
- if (len < 0)
- return 0;
- buf[len] = '\n';
- buf[len+1] = 0;
- return len+1;
-}
-static DEVICE_ATTR(product,S_IRUGO,show_product,NULL);
-
-/* manufacturer driverfs file */
-static ssize_t
-show_manufacturer (struct device *dev, char *buf, size_t count, loff_t off)
-{
- struct usb_device *udev;
- int len;
-
- if (off)
- return 0;
- udev = to_usb_device (dev);
-
- len = usb_string(udev, udev->descriptor.iManufacturer, buf, PAGE_SIZE);
- if (len < 0)
- return 0;
- buf[len] = '\n';
- buf[len+1] = 0;
- return len+1;
-}
-static DEVICE_ATTR(manufacturer,S_IRUGO,show_manufacturer,NULL);
-
-/* serial number driverfs file */
-static ssize_t
-show_serial (struct device *dev, char *buf, size_t count, loff_t off)
-{
- struct usb_device *udev;
- int len;
-
- if (off)
- return 0;
- udev = to_usb_device (dev);
-
- len = usb_string(udev, udev->descriptor.iSerialNumber, buf, PAGE_SIZE);
- if (len < 0)
- return 0;
- buf[len] = '\n';
- buf[len+1] = 0;
- return len+1;
-}
-static DEVICE_ATTR(serial,S_IRUGO,show_serial,NULL);
-
/**
* usb_alloc_dev - allocate a usb device structure (usbcore-internal)
* @parent: hub to which device is connected
@@ -1133,13 +1043,7 @@ int usb_new_device(struct usb_device *dev, struct device *parent)
return err;
/* add the USB device specific driverfs files */
- device_create_file (&dev->dev, &dev_attr_configuration);
- if (dev->descriptor.iManufacturer)
- device_create_file (&dev->dev, &dev_attr_manufacturer);
- if (dev->descriptor.iProduct)
- device_create_file (&dev->dev, &dev_attr_product);
- if (dev->descriptor.iSerialNumber)
- device_create_file (&dev->dev, &dev_attr_serial);
+ usb_create_driverfs_dev_files (dev);
/* Register all of the interfaces for this device with the driver core.
* Remember, interfaces get bound to drivers, not devices. */
@@ -1169,7 +1073,7 @@ int usb_new_device(struct usb_device *dev, struct device *parent)
}
dbg ("%s - registering %s", __FUNCTION__, interface->dev.bus_id);
device_register (&interface->dev);
- device_create_file (&interface->dev, &dev_attr_altsetting);
+ usb_create_driverfs_intf_files (interface);
}
/* add a /proc/bus/usb entry */
@@ -1194,6 +1098,8 @@ int usb_new_device(struct usb_device *dev, struct device *parent)
* avoid behaviors like using "DMA bounce buffers", or tying down I/O mapping
* hardware for long idle periods. The implementation varies between
* platforms, depending on details of how DMA will work to this device.
+ * Using these buffers also helps prevent cacheline sharing problems on
+ * architectures where CPU caches are not DMA-coherent.
*
* When the buffer is no longer used, free it with usb_buffer_free().
*/
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
new file mode 100644
index 000000000000..09f459f67acd
--- /dev/null
+++ b/drivers/usb/core/usb.h
@@ -0,0 +1,5 @@
+/* Functions local to drivers/usb/core/ */
+
+extern void usb_create_driverfs_dev_files (struct usb_device *dev);
+extern void usb_create_driverfs_intf_files (struct usb_interface *intf);
+
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index f19a5fdd9fd6..ed92a80f66d0 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -749,7 +749,7 @@ static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
default:
spin_lock_irqsave (&ehci->lock, flags);
if (ehci->reclaim) {
- dbg ("dq %p: reclaim = %p, %s",
+ vdbg ("dq %p: reclaim = %p, %s",
qh, ehci->reclaim, RUN_CONTEXT);
if (qh == ehci->reclaim) {
/* unlinking qh for another queued urb? */
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index 0fd8b3bdae38..c24ed3b70c2f 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -255,23 +255,23 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
struct urb *urb = qtd->urb;
u32 token = 0;
+ /* hc's on-chip qh overlay cache can overwrite our idea of
+ * next qtd ptrs, if we appended a qtd while the queue was
+ * advancing. (because we don't use dummy qtds.)
+ */
+ if (cpu_to_le32 (qtd->qtd_dma) == qh->hw_current
+ && qtd->hw_next != qh->hw_qtd_next) {
+ qh->hw_alt_next = qtd->hw_alt_next;
+ qh->hw_qtd_next = qtd->hw_next;
+ COUNT (ehci->stats.qpatch);
+ }
+
/* clean up any state from previous QTD ...*/
if (last) {
if (likely (last->urb != urb)) {
ehci_urb_done (ehci, last->urb);
count++;
}
-
- /* qh overlays can have HC's old cached copies of
- * next qtd ptrs, if an URB was queued afterwards.
- */
- if (cpu_to_le32 (last->qtd_dma) == qh->hw_current
- && last->hw_next != qh->hw_qtd_next) {
- qh->hw_alt_next = last->hw_alt_next;
- qh->hw_qtd_next = last->hw_next;
- COUNT (ehci->stats.qpatch);
- }
-
ehci_qtd_free (ehci, last);
last = 0;
}
@@ -529,7 +529,8 @@ qh_urb_transaction (
}
/* by default, enable interrupt on urb completion */
- if (likely (!(urb->transfer_flags & URB_NO_INTERRUPT)))
+// ... do it always, unless we switch over to dummy qtds
+// if (likely (!(urb->transfer_flags & URB_NO_INTERRUPT)))
qtd->hw_token |= __constant_cpu_to_le32 (QTD_IOC);
return head;
@@ -785,7 +786,6 @@ static struct ehci_qh *qh_append_tds (
/* append to tds already queued to this qh? */
if (unlikely (!list_empty (&qh->qtd_list) && qtd)) {
struct ehci_qtd *last_qtd;
- int short_rx = 0;
u32 hw_next;
/* update the last qtd's "next" pointer */
@@ -800,23 +800,16 @@ static struct ehci_qh *qh_append_tds (
&& (epnum & 0x10)) {
// only the last QTD for now
last_qtd->hw_alt_next = hw_next;
- short_rx = 1;
}
- /* Adjust any old copies in qh overlay too.
- * Interrupt code must cope with case of HC having it
- * cached, and clobbering these updates.
- * ... complicates getting rid of extra interrupts!
- * (Or: use dummy td, so cache always stays valid.)
+ /* qh_completions() may need to patch the qh overlay if
+ * the hc was advancing this queue while we appended.
+ * we know it can: last_qtd->hw_token has IOC set.
+ *
+ * or: use a dummy td (so the overlay gets the next td
+ * only when we set its active bit); fewer irqs.
*/
- if (qh->hw_current == cpu_to_le32 (last_qtd->qtd_dma)) {
- wmb ();
- qh->hw_qtd_next = hw_next;
- if (short_rx)
- qh->hw_alt_next = hw_next
- | (qh->hw_alt_next & 0x1e);
- vdbg ("queue to qh %p, patch", qh);
- }
+ wmb ();
/* no URB queued */
} else {
diff --git a/drivers/usb/host/hc_sl811.c b/drivers/usb/host/hc_sl811.c
index 3df1c3e5c98c..bd4d561a3c9c 100644
--- a/drivers/usb/host/hc_sl811.c
+++ b/drivers/usb/host/hc_sl811.c
@@ -28,7 +28,7 @@
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/sched.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/smp_lock.h>
@@ -1158,6 +1158,7 @@ static hci_t *__devinit hc_alloc_hci (void)
bus = usb_alloc_bus (&hci_device_operations);
if (!bus) {
kfree (hci);
+ kfree (ps);
return NULL;
}
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index cd1b3a64e48a..b0d080387a33 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -193,12 +193,6 @@ static int ohci_urb_enqueue (
break;
case PIPE_ISOCHRONOUS: /* number of packets from URB */
size = urb->number_of_packets;
- if (size <= 0)
- return -EINVAL;
- for (i = 0; i < urb->number_of_packets; i++) {
- urb->iso_frame_desc [i].actual_length = 0;
- urb->iso_frame_desc [i].status = -EXDEV;
- }
break;
}
diff --git a/drivers/usb/host/ohci-mem.c b/drivers/usb/host/ohci-mem.c
index 51322551606b..bde7dfef56e5 100644
--- a/drivers/usb/host/ohci-mem.c
+++ b/drivers/usb/host/ohci-mem.c
@@ -48,10 +48,10 @@ dma_to_ed_td (struct hash_list_t * entry, dma_addr_t dma)
struct hash_t * scan = entry->head;
while (scan && scan->dma != dma)
scan = scan->next;
- return scan->virt;
+ return scan ? scan->virt : 0;
}
-static struct td *
+static inline struct td *
dma_to_td (struct ohci_hcd *hc, dma_addr_t td_dma)
{
td_dma &= TD_MASK;
@@ -62,7 +62,7 @@ dma_to_td (struct ohci_hcd *hc, dma_addr_t td_dma)
// FIXME: when updating the hashtables this way, mem_flags is unusable...
/* Add a hash entry for a TD/ED; return true on success */
-static int
+static inline int
hash_add_ed_td (
struct hash_list_t *entry,
void *virt,
@@ -97,7 +97,7 @@ hash_add_td (struct ohci_hcd *hc, struct td *td, int mem_flags)
}
-static void
+static inline void
hash_free_ed_td (struct hash_list_t *entry, void *virt)
{
struct hash_t *scan, *prev;
diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
index 2b5e3e17e266..8385033e3891 100644
--- a/drivers/usb/host/ohci-q.c
+++ b/drivers/usb/host/ohci-q.c
@@ -854,6 +854,11 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci)
int cc;
td = dma_to_td (ohci, td_dma);
+ if (!td) {
+ err ("%s bad entry %8x",
+ ohci->hcd.self.bus_name, td_dma);
+ break;
+ }
td->hwINFO |= cpu_to_le32 (TD_DONE);
cc = TD_CC_GET (le32_to_cpup (&td->hwINFO));
diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c
index f7b44577a7a0..a6a34619d4fd 100644
--- a/drivers/usb/host/ohci-sa1111.c
+++ b/drivers/usb/host/ohci-sa1111.c
@@ -25,7 +25,7 @@
/*-------------------------------------------------------------------------*/
-static void sa1111_start_hc(void)
+static void sa1111_start_hc(struct sa1111_dev *dev)
{
unsigned int usb_rst = 0;
@@ -48,31 +48,35 @@ static void sa1111_start_hc(void)
* Configure the power sense and control lines. Place the USB
* host controller in reset.
*/
- USB_RESET = usb_rst | USB_RESET_FORCEIFRESET | USB_RESET_FORCEHCRESET;
+ sa1111_writel(usb_rst | USB_RESET_FORCEIFRESET | USB_RESET_FORCEHCRESET,
+ dev->mapbase + SA1111_USB_RESET);
/*
* Now, carefully enable the USB clock, and take
* the USB host controller out of reset.
*/
- SKPCR |= SKPCR_UCLKEN;
+ sa1111_enable_device(dev);
udelay(11);
- USB_RESET = usb_rst;
+ sa1111_writel(usb_rst, dev->mapbase + SA1111_USB_RESET);
}
-static void sa1111_stop_hc(void)
+static void sa1111_stop_hc(struct sa1111_dev *dev)
{
+ unsigned int usb_rst;
printk(KERN_DEBUG __FILE__
": stopping SA-1111 OHCI USB Controller\n");
/*
* Put the USB host controller into reset.
*/
- USB_RESET |= USB_RESET_FORCEIFRESET | USB_RESET_FORCEHCRESET;
+ usb_rst = sa1111_readl(dev->mapbase + SA1111_USB_RESET);
+ sa1111_writel(usb_rst | USB_RESET_FORCEIFRESET | USB_RESET_FORCEHCRESET,
+ dev->mapbase + SA1111_USB_RESET);
/*
* Stop the USB clock.
*/
- SKPCR &= ~SKPCR_UCLKEN;
+ sa1111_disable_device(dev);
#ifdef CONFIG_SA1100_BADGE4
if (machine_is_badge4()) {
@@ -86,9 +90,9 @@ static void sa1111_stop_hc(void)
/*-------------------------------------------------------------------------*/
#if 0
-static void dump_hci_status(const char *label)
+static void dump_hci_status(struct usb_hcd *hcd, const char *label)
{
- unsigned long status = USB_STATUS;
+ unsigned long status = sa1111_readl(hcd->regs + SA1111_USB_STATUS);
dbg ("%s USB_STATUS = { %s%s%s%s%s}", label,
((status & USB_STATUS_IRQHCIRMTWKUP) ? "IRQHCIRMTWKUP " : ""),
@@ -101,11 +105,14 @@ static void dump_hci_status(const char *label)
static void usb_hcd_sa1111_hcim_irq (int irq, void *__hcd, struct pt_regs * r)
{
- //dump_hci_status("irq");
+ struct usb_hcd *hcd = __hcd;
+// unsigned long status = sa1111_readl(hcd->regs + SA1111_USB_STATUS);
+
+ //dump_hci_status(hcd, "irq");
#if 0
/* may work better this way -- need to investigate further */
- if (USB_STATUS & USB_STATUS_NIRQHCIM) {
+ if (status & USB_STATUS_NIRQHCIM) {
//dbg ("not normal HC interrupt; ignoring");
return;
}
@@ -116,7 +123,7 @@ static void usb_hcd_sa1111_hcim_irq (int irq, void *__hcd, struct pt_regs * r)
/*-------------------------------------------------------------------------*/
-void usb_hcd_sa1111_remove (struct usb_hcd *);
+void usb_hcd_sa1111_remove (struct usb_hcd *, struct sa1111_dev *);
/* configure so an HC device and id are always provided */
/* always called with process context; sleeping is OK */
@@ -132,21 +139,20 @@ void usb_hcd_sa1111_remove (struct usb_hcd *);
*
* Store this function in the HCD's struct pci_driver as probe().
*/
-int usb_hcd_sa1111_probe (const struct hc_driver *driver, struct usb_hcd **hcd_out)
+int usb_hcd_sa1111_probe (const struct hc_driver *driver,
+ struct usb_hcd **hcd_out,
+ struct sa1111_dev *dev)
{
int retval;
struct usb_hcd *hcd = 0;
- if (!sa1111)
- return -ENODEV;
-
- if (!request_mem_region(_USB_OHCI_OP_BASE,
- _USB_EXTENT, hcd_name)) {
+ if (!request_mem_region(dev->res.start,
+ dev->res.end - dev->res.start + 1, hcd_name)) {
dbg("request_mem_region failed");
return -EBUSY;
}
- sa1111_start_hc();
+ sa1111_start_hc(dev);
hcd = driver->hcd_alloc ();
if (hcd == NULL){
@@ -157,9 +163,10 @@ int usb_hcd_sa1111_probe (const struct hc_driver *driver, struct usb_hcd **hcd_o
hcd->driver = (struct hc_driver *) driver;
hcd->description = driver->description;
- hcd->irq = NIRQHCIM;
- hcd->regs = (void *) &USB_OHCI_OP_BASE;
+ hcd->irq = dev->irq[1];
+ hcd->regs = dev->mapbase;
hcd->pdev = SA1111_FAKE_PCIDEV;
+ hcd->parent = &dev->dev;
retval = hcd_buffer_create (hcd);
if (retval != 0) {
@@ -167,8 +174,8 @@ int usb_hcd_sa1111_probe (const struct hc_driver *driver, struct usb_hcd **hcd_o
goto err1;
}
- set_irq_type(NIRQHCIM, IRQT_RISING);
- retval = request_irq (NIRQHCIM, usb_hcd_sa1111_hcim_irq, SA_INTERRUPT,
+ set_irq_type(hcd->irq, IRQT_RISING);
+ retval = request_irq (hcd->irq, usb_hcd_sa1111_hcim_irq, SA_INTERRUPT,
hcd->description, hcd);
if (retval != 0) {
dbg("request_irq failed");
@@ -191,7 +198,7 @@ int usb_hcd_sa1111_probe (const struct hc_driver *driver, struct usb_hcd **hcd_o
if ((retval = driver->start (hcd)) < 0)
{
- usb_hcd_sa1111_remove(hcd);
+ usb_hcd_sa1111_remove(hcd, dev);
return retval;
}
@@ -202,8 +209,8 @@ int usb_hcd_sa1111_probe (const struct hc_driver *driver, struct usb_hcd **hcd_o
hcd_buffer_destroy (hcd);
if (hcd) driver->hcd_free(hcd);
err1:
- sa1111_stop_hc();
- release_mem_region(_USB_OHCI_OP_BASE, _USB_EXTENT);
+ sa1111_stop_hc(dev);
+ release_mem_region(dev->res.start, dev->res.end - dev->res.start + 1);
return retval;
}
@@ -221,7 +228,7 @@ int usb_hcd_sa1111_probe (const struct hc_driver *driver, struct usb_hcd **hcd_o
* context, normally "rmmod", "apmd", or something similar.
*
*/
-void usb_hcd_sa1111_remove (struct usb_hcd *hcd)
+void usb_hcd_sa1111_remove (struct usb_hcd *hcd, struct sa1111_dev *dev)
{
struct usb_device *hub;
void *base;
@@ -244,13 +251,13 @@ void usb_hcd_sa1111_remove (struct usb_hcd *hcd)
usb_deregister_bus (&hcd->self);
if (atomic_read (&hcd->self.refcnt) != 1)
- err (__FUNCTION__ ": %s, count != 1", hcd->self.bus_name);
+ err ("%s: %s, count != 1", __FUNCTION__, hcd->self.bus_name);
base = hcd->regs;
hcd->driver->hcd_free (hcd);
- sa1111_stop_hc();
- release_mem_region(_USB_OHCI_OP_BASE, _USB_EXTENT);
+ sa1111_stop_hc(dev);
+ release_mem_region(dev->res.start, dev->res.end - dev->res.start + 1);
}
/*-------------------------------------------------------------------------*/
@@ -275,7 +282,7 @@ ohci_sa1111_start (struct usb_hcd *hcd)
}
ohci->regs = hcd->regs;
- ohci->parent_dev = &sa1111->dev;
+ ohci->parent_dev = hcd->parent;
if (hc_reset (ohci) < 0) {
ohci_stop (hcd);
@@ -342,26 +349,67 @@ static const struct hc_driver ohci_sa1111_hc_driver = {
/*-------------------------------------------------------------------------*/
-/* Only one SA-1111 ever exists. */
-static struct usb_hcd *the_sa1111_hcd;
+static int ohci_hcd_sa1111_drv_probe(struct device *_dev)
+{
+ struct sa1111_dev *dev = SA1111_DEV(_dev);
+ struct usb_hcd *hcd = NULL;
+ int ret;
+
+ ret = usb_hcd_sa1111_probe(&ohci_sa1111_hc_driver, &hcd, dev);
+
+ if (ret == 0)
+ dev->dev.driver_data = hcd;
+
+ return ret;
+}
+
+static int ohci_hcd_sa1111_drv_remove(struct device *_dev)
+{
+ struct sa1111_dev *dev = SA1111_DEV(_dev);
+ struct usb_hcd *hcd = dev->dev.driver_data;
+
+ usb_hcd_sa1111_remove(hcd, dev);
+
+ dev->dev.driver_data = NULL;
-static int __init ohci_hcd_sa1111_init (void)
+ return 0;
+}
+
+static int ohci_hcd_sa1111_drv_suspend(struct device *dev, u32 state, u32 level)
+{
+ return 0;
+}
+
+static int ohci_hcd_sa1111_drv_resume(struct device *dev, u32 level)
+{
+ return 0;
+}
+
+static struct sa1111_driver ohci_hcd_sa1111_driver = {
+ .drv = {
+ .name = "SA1111 OHCI",
+ .bus = &sa1111_bus_type,
+ .probe = ohci_hcd_sa1111_drv_probe,
+ .remove = ohci_hcd_sa1111_drv_remove,
+ .suspend = ohci_hcd_sa1111_drv_suspend,
+ .resume = ohci_hcd_sa1111_drv_resume,
+ },
+ .devid = SA1111_DEVID_USB,
+};
+
+static int __init ohci_hcd_sa1111_init (void)
{
dbg (DRIVER_INFO " (SA-1111)");
dbg ("block sizes: ed %d td %d",
sizeof (struct ed), sizeof (struct td));
- the_sa1111_hcd = 0;
- return usb_hcd_sa1111_probe(&ohci_sa1111_hc_driver, &the_sa1111_hcd);
+ return driver_register(&ohci_hcd_sa1111_driver.drv);
}
-module_init (ohci_hcd_sa1111_init);
-
-static void __exit ohci_hcd_sa1111_cleanup (void)
-{
- if (the_sa1111_hcd) {
- usb_hcd_sa1111_remove(the_sa1111_hcd);
- the_sa1111_hcd = 0;
- }
+static void __exit ohci_hcd_sa1111_cleanup (void)
+{
+ remove_driver(&ohci_hcd_sa1111_driver.drv);
}
+
+module_init (ohci_hcd_sa1111_init);
module_exit (ohci_hcd_sa1111_cleanup);
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index 2bed78c39ab2..c728a7420d16 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -437,9 +437,7 @@ static void cyberjack_write_bulk_callback (struct urb *urb)
/* Throw away data. No better idea what to do with it. */
priv->wrfilled=0;
priv->wrsent=0;
- queue_task(&port->tqueue, &tq_immediate);
- mark_bh(IMMEDIATE_BH);
- return;
+ goto exit;
}
dbg("%s - priv->wrsent=%d", __FUNCTION__,priv->wrsent);
@@ -453,16 +451,10 @@ static void cyberjack_write_bulk_callback (struct urb *urb)
priv->wrfilled=0;
priv->wrsent=0;
}
-
- queue_task(&port->tqueue, &tq_immediate);
- mark_bh(IMMEDIATE_BH);
- return;
}
- queue_task(&port->tqueue, &tq_immediate);
- mark_bh(IMMEDIATE_BH);
-
- return;
+exit:
+ schedule_task(&port->tqueue);
}
static int __init cyberjack_init (void)
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
index 12bf572660e6..8db192f94e94 100644
--- a/drivers/usb/serial/empeg.c
+++ b/drivers/usb/serial/empeg.c
@@ -362,11 +362,7 @@ static void empeg_write_bulk_callback (struct urb *urb)
return;
}
- queue_task(&port->tqueue, &tq_immediate);
- mark_bh(IMMEDIATE_BH);
-
- return;
-
+ schedule_task(&port->tqueue);
}
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 1707de33b2de..8f5e0887f228 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -484,10 +484,8 @@ static void ftdi_sio_write_bulk_callback (struct urb *urb)
dbg("nonzero write bulk status received: %d", urb->status);
return;
}
- queue_task(&port->tqueue, &tq_immediate);
- mark_bh(IMMEDIATE_BH);
- return;
+ schedule_task(&port->tqueue);
} /* ftdi_sio_write_bulk_callback */
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index d4eda82398b2..2999a4a7b550 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -465,10 +465,8 @@ static void ipaq_write_bulk_callback(struct urb *urb)
priv->active = 0;
spin_unlock_irqrestore(&write_list_lock, flags);
}
- queue_task(&port->tqueue, &tq_immediate);
- mark_bh(IMMEDIATE_BH);
-
- return;
+
+ schedule_task(&port->tqueue);
}
static int ipaq_write_room(struct usb_serial_port *port)
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
index d576176aa492..bda8a7866b4f 100644
--- a/drivers/usb/serial/ir-usb.c
+++ b/drivers/usb/serial/ir-usb.c
@@ -426,10 +426,7 @@ static void ir_write_bulk_callback (struct urb *urb)
urb->actual_length,
urb->transfer_buffer);
- queue_task(&port->tqueue, &tq_immediate);
- mark_bh(IMMEDIATE_BH);
-
- return;
+ schedule_task(&port->tqueue);
}
static void ir_read_bulk_callback (struct urb *urb)
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index b7a94800bf62..6a052412725c 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -447,10 +447,8 @@ static void usa2x_outdat_callback(struct urb *urb)
p_priv = (struct keyspan_port_private *)(port->private);
dbg ("%s - urb %d", __FUNCTION__, urb == p_priv->out_urbs[1]);
- if (port->open_count) {
- queue_task(&port->tqueue, &tq_immediate);
- mark_bh(IMMEDIATE_BH);
- }
+ if (port->open_count)
+ schedule_task(&port->tqueue);
}
static void usa26_inack_callback(struct urb *urb)
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index 1974edc727e7..776806b5b2ca 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -577,10 +577,7 @@ static void klsi_105_write_bulk_callback ( struct urb *urb)
}
/* from generic_write_bulk_callback */
- queue_task(&port->tqueue, &tq_immediate);
- mark_bh(IMMEDIATE_BH);
-
- return;
+ schedule_task(&port->tqueue);
} /* klsi_105_write_bulk_completion_callback */
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index 9fe49a3b591f..d01271a7f06a 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -507,8 +507,7 @@ static void mct_u232_write_bulk_callback (struct urb *urb)
} else {
/* from generic_write_bulk_callback */
- queue_task(&port->tqueue, &tq_immediate);
- mark_bh(IMMEDIATE_BH);
+ schedule_task(&port->tqueue);
}
return;
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
index 6fbad950b224..e675964d592b 100644
--- a/drivers/usb/serial/omninet.c
+++ b/drivers/usb/serial/omninet.c
@@ -359,12 +359,9 @@ static void omninet_write_bulk_callback (struct urb *urb)
return;
}
- queue_task(&port->tqueue, &tq_immediate);
- mark_bh(IMMEDIATE_BH);
+ schedule_task(&port->tqueue);
// dbg("omninet_write_bulk_callback, tty %0x\n", tty);
-
- return;
}
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 45251e51d95f..3f1a2b50ecf9 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -705,10 +705,7 @@ static void pl2303_write_bulk_callback (struct urb *urb)
return;
}
- queue_task(&port->tqueue, &tq_immediate);
- mark_bh(IMMEDIATE_BH);
-
- return;
+ schedule_task(&port->tqueue);
}
diff --git a/drivers/usb/serial/usbserial.c b/drivers/usb/serial/usbserial.c
index b0b3ca548d0b..84bfbf783ba9 100644
--- a/drivers/usb/serial/usbserial.c
+++ b/drivers/usb/serial/usbserial.c
@@ -1092,10 +1092,7 @@ static void generic_write_bulk_callback (struct urb *urb)
usb_serial_port_softint((void *)port);
- queue_task(&port->tqueue, &tq_immediate);
- mark_bh(IMMEDIATE_BH);
-
- return;
+ schedule_task(&port->tqueue);
}
static void generic_shutdown (struct usb_serial *serial)
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index 1e6bb41459b8..11af1da8bfcc 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -182,9 +182,10 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M500_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M505_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M515_ID) },
+ { USB_DEVICE(PALM_VENDOR_ID, PALM_I705_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M125_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M130_ID) },
- { USB_DEVICE(PALM_VENDOR_ID, PALM_I705_ID) },
+ { USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE_ID) },
{ USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID) },
{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID) },
{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_S360_ID) },
@@ -202,9 +203,10 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M500_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M505_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M515_ID) },
+ { USB_DEVICE(PALM_VENDOR_ID, PALM_I705_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M125_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M130_ID) },
- { USB_DEVICE(PALM_VENDOR_ID, PALM_I705_ID) },
+ { USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE_ID) },
{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_3_5_ID) },
{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID) },
{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_S360_ID) },
@@ -458,10 +460,7 @@ static void visor_write_bulk_callback (struct urb *urb)
/* free up the transfer buffer, as usb_free_urb() does not do this */
kfree (urb->transfer_buffer);
- queue_task(&port->tqueue, &tq_immediate);
- mark_bh(IMMEDIATE_BH);
-
- return;
+ schedule_task(&port->tqueue);
}
diff --git a/drivers/usb/serial/visor.h b/drivers/usb/serial/visor.h
index 6fa7809a6ab2..2e1c0abba230 100644
--- a/drivers/usb/serial/visor.h
+++ b/drivers/usb/serial/visor.h
@@ -27,6 +27,7 @@
#define PALM_I705_ID 0x0020
#define PALM_M125_ID 0x0040
#define PALM_M130_ID 0x0050
+#define PALM_ZIRE_ID 0x0070
#define SONY_VENDOR_ID 0x054C
#define SONY_CLIE_3_5_ID 0x0038
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index cadff24042e0..67c931eed0d2 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -918,10 +918,7 @@ static void whiteheat_write_callback(struct urb *urb)
usb_serial_port_softint((void *)port);
- queue_task(&port->tqueue, &tq_immediate);
- mark_bh(IMMEDIATE_BH);
-
- return;
+ schedule_task(&port->tqueue);
}
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index 76de10367593..19071ba8bf86 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -530,6 +530,8 @@ int usb_stor_clear_halt(struct us_data *us, int pipe)
if (result < 0)
return result;
+ printk(KERN_ERR "usb_stor_clear_halt() WORKED!\n");
+
/* reset the toggles and endpoint flags */
usb_endpoint_running(us->pusb_dev, usb_pipeendpoint(pipe),
usb_pipeout(pipe));
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
index 6a2683bba658..17b1c02cb38a 100644
--- a/drivers/video/sa1100fb.c
+++ b/drivers/video/sa1100fb.c
@@ -209,17 +209,17 @@ extern void (*sa1100fb_lcd_power)(int on);
* IMHO this looks wrong. In 8BPP, length should be 8.
*/
static struct sa1100fb_rgb rgb_8 = {
- red: { offset: 0, length: 4, },
- green: { offset: 0, length: 4, },
- blue: { offset: 0, length: 4, },
- transp: { offset: 0, length: 0, },
+ .red = { .offset = 0, .length = 4, },
+ .green = { .offset = 0, .length = 4, },
+ .blue = { .offset = 0, .length = 4, },
+ .transp = { .offset = 0, .length = 0, },
};
static struct sa1100fb_rgb def_rgb_16 = {
- red: { offset: 11, length: 5, },
- green: { offset: 5, length: 6, },
- blue: { offset: 0, length: 5, },
- transp: { offset: 0, length: 0, },
+ .red = { .offset = 11, .length = 5, },
+ .green = { .offset = 5, .length = 6, },
+ .blue = { .offset = 0, .length = 5, },
+ .transp = { .offset = 0, .length = 0, },
};
#ifdef CONFIG_SA1100_ASSABET
@@ -230,155 +230,151 @@ static struct sa1100fb_rgb def_rgb_16 = {
* instead (def_rgb_16).
*/
static struct sa1100fb_mach_info lq039q2ds54_info __initdata = {
- pixclock: 171521, bpp: 16,
- xres: 320, yres: 240,
+ .pixclock = 171521, .bpp = 16,
+ .xres = 320, .yres = 240,
- hsync_len: 5, vsync_len: 1,
- left_margin: 61, upper_margin: 3,
- right_margin: 9, lower_margin: 0,
+ .hsync_len = 5, .vsync_len = 1,
+ .left_margin = 61, .upper_margin = 3,
+ .right_margin = 9, .lower_margin = 0,
- sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
- lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
+ .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
+ .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
};
#else
static struct sa1100fb_mach_info pal_info __initdata = {
- pixclock: 67797, bpp: 16,
- xres: 640, yres: 512,
+ .pixclock = 67797, .bpp = 16,
+ .xres = 640, .yres = 512,
- hsync_len: 64, vsync_len: 6,
- left_margin: 125, upper_margin: 70,
- right_margin: 115, lower_margin: 36,
+ .hsync_len = 64, .vsync_len = 6,
+ .left_margin = 125, .upper_margin = 70,
+ .right_margin = 115, .lower_margin = 36,
- sync: 0,
-
- lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
- lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(512),
+ .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
+ .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(512),
};
#endif
#endif
#ifdef CONFIG_SA1100_H3800
static struct sa1100fb_mach_info h3800_info __initdata = {
- pixclock: 174757, bpp: 16,
- xres: 320, yres: 240,
+ .pixclock = 174757, .bpp = 16,
+ .xres = 320, .yres = 240,
- hsync_len: 3, vsync_len: 3,
- left_margin: 12, upper_margin: 10,
- right_margin: 17, lower_margin: 1,
+ .hsync_len = 3, .vsync_len = 3,
+ .left_margin = 12, .upper_margin = 10,
+ .right_margin = 17, .lower_margin = 1,
- sync: 0, cmap_static: 1,
+ .cmap_static = 1,
- lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
- lccr3: LCCR3_ACBsDiv(2) | LCCR3_PixRsEdg | LCCR3_OutEnH |
- LCCR3_ACBsCntOff,
+ .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
+ .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
};
#endif
#ifdef CONFIG_SA1100_H3600
static struct sa1100fb_mach_info h3600_info __initdata = {
- pixclock: 174757, bpp: 16,
- xres: 320, yres: 240,
+ .pixclock = 174757, .bpp = 16,
+ .xres = 320, .yres = 240,
- hsync_len: 3, vsync_len: 3,
- left_margin: 12, upper_margin: 10,
- right_margin: 17, lower_margin: 1,
+ .hsync_len = 3, .vsync_len = 3,
+ .left_margin = 12, .upper_margin = 10,
+ .right_margin = 17, .lower_margin = 1,
- sync: 0, cmap_static: 1,
+ .cmap_static = 1,
- lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
- lccr3: LCCR3_ACBsDiv(2) | LCCR3_PixRsEdg | LCCR3_OutEnH |
- LCCR3_ACBsCntOff,
+ .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
+ .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
};
static struct sa1100fb_rgb h3600_rgb_16 = {
- red: { offset: 12, length: 4, },
- green: { offset: 7, length: 4, },
- blue: { offset: 1, length: 4, },
- transp: { offset: 0, length: 0, },
+ .red = { .offset = 12, .length = 4, },
+ .green = { .offset = 7, .length = 4, },
+ .blue = { .offset = 1, .length = 4, },
+ .transp = { .offset = 0, .length = 0, },
};
#endif
#ifdef CONFIG_SA1100_H3100
static struct sa1100fb_mach_info h3100_info __initdata = {
- pixclock: 406977, bpp: 4,
- xres: 320, yres: 240,
+ .pixclock = 406977, .bpp = 4,
+ .xres = 320, .yres = 240,
- hsync_len: 26, vsync_len: 41,
- left_margin: 4, upper_margin: 0,
- right_margin: 4, lower_margin: 0,
+ .hsync_len = 26, .vsync_len = 41,
+ .left_margin = 4, .upper_margin = 0,
+ .right_margin = 4, .lower_margin = 0,
- sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- cmap_greyscale: 1,
- cmap_inverse: 1,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .cmap_greyscale = 1,
+ .cmap_inverse = 1,
- lccr0: LCCR0_Mono | LCCR0_4PixMono | LCCR0_Sngl | LCCR0_Pas,
- lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
+ .lccr0 = LCCR0_Mono | LCCR0_4PixMono | LCCR0_Sngl | LCCR0_Pas,
+ .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
};
#endif
#ifdef CONFIG_SA1100_BRUTUS
static struct sa1100fb_mach_info brutus_info __initdata = {
- pixclock: 0, bpp: 8,
- xres: 320, yres: 240,
+ .pixclock = 0, .bpp = 8,
+ .xres = 320, .yres = 240,
- hsync_len: 3, vsync_len: 1,
- left_margin: 41, upper_margin: 0,
- right_margin: 101, lower_margin: 0,
+ .hsync_len = 3, .vsync_len = 1,
+ .left_margin = 41, .upper_margin = 0,
+ .right_margin = 101, .lower_margin = 0,
- sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Pas,
- lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2) |
- LCCR3_PixClkDiv(44),
+ .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Pas,
+ .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2) |
+ LCCR3_PixClkDiv(44),
};
#endif
#ifdef CONFIG_SA1100_CERF
static struct sa1100fb_mach_info cerf_info __initdata = {
#if defined(CONFIG_CERF_LCD_72_A)
- pixclock: 171521, bpp: 8,
- xres: 640, yres: 480,
- lccr0: LCCR0_Color | LCCR0_Dual | LCCR0_Pas,
- lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2) |
- LCCR3_PixClkDiv(38),
+ .pixclock = 171521, .bpp = 8,
+ .xres = 640, .yres = 480,
+ .lccr0 = LCCR0_Color | LCCR0_Dual | LCCR0_Pas,
+ .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2) |
+ LCCR3_PixClkDiv(38),
#elif defined(CONFIG_CERF_LCD_57_A)
- pixclock: 171521, bpp: 8,
- xres: 320, yres: 240,
- lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Pas,
- lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2) |
- LCCR3_PixClkDiv(38),
+ .pixclock = 171521, .bpp = 8,
+ .xres = 320, .yres = 240,
+ .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Pas,
+ .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2) |
+ LCCR3_PixClkDiv(38),
#elif defined(CONFIG_CERF_LCD_38_A)
- pixclock: 171521, bpp: 8,
- xres: 240, yres: 320,
- lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Pas,
- lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(56) |
- LCCR3_PixClkDiv(38),
+ .pixclock = 171521, .bpp = 8,
+ .xres = 240, .yres = 320,
+ .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Pas,
+ .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(56) |
+ LCCR3_PixClkDiv(38),
#elif defined(CONFIG_CERF_LCD_38_B)
- pixclock: 171521, bpp: 4,
- xres: 320, yres: 240,
- lccr0: LCCR0_Mono | LCCR0_4PixMono | LCCR0_Sngl | LCCR0_Pas,
- lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(56) |
- LCCR3_PixClkDiv(38),
+ .pixclock = 171521, .bpp = 4,
+ .xres = 320, .yres = 240,
+ .lccr0 = LCCR0_Mono | LCCR0_4PixMono | LCCR0_Sngl | LCCR0_Pas,
+ .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(56) |
+ LCCR3_PixClkDiv(38),
#else
#error "Must have a CerfBoard LCD form factor selected"
#endif
- hsync_len: 5, vsync_len: 1,
- left_margin: 61, upper_margin: 3,
- right_margin: 9, lower_margin: 0,
+ .hsync_len = 5, .vsync_len = 1,
+ .left_margin = 61, .upper_margin = 3,
+ .right_margin = 9, .lower_margin = 0,
- sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
};
#if 0
static struct sa1100fb_rgb cerf_rgb_16 = {
- red: { offset: 8, length: 4, },
- green: { offset: 4, length: 4, },
- blue: { offset: 0, length: 4, },
- transp: { offset: 0, length: 0, },
+ .red = { .offset = 8, .length = 4, },
+ .green = { .offset = 4, .length = 4, },
+ .blue = { .offset = 0, .length = 4, },
+ .transp = { .offset = 0, .length = 0, },
};
#endif
#endif
@@ -386,56 +382,54 @@ static struct sa1100fb_rgb cerf_rgb_16 = {
#ifdef CONFIG_SA1100_FREEBIRD
#warning Please check this carefully
static struct sa1100fb_mach_info freebird_info __initdata = {
- pixclock: 171521, bpp: 16,
- xres: 240, yres: 320,
+ .pixclock = 171521, .bpp = 16,
+ .xres = 240, .yres = 320,
- hsync_len: 3, vsync_len: 2,
- left_margin: 2, upper_margin: 0,
- right_margin: 2, lower_margin: 0,
+ .hsync_len = 3, .vsync_len = 2,
+ .left_margin = 2, .upper_margin = 0,
+ .right_margin = 2, .lower_margin = 0,
- sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Pas,
- lccr3: LCCR3_OutEnH | LCCR3_PixFlEdg | LCCR3_ACBsDiv(2),
+ .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Pas,
+ .lccr3 = LCCR3_OutEnH | LCCR3_PixFlEdg | LCCR3_ACBsDiv(2),
};
static struct sa1100fb_rgb freebird_rgb_16 = {
- red: { offset: 8, length: 4, },
- green: { offset: 4, length: 4, },
- blue: { offset: 0, length: 4, },
- transp: { offset: 12, length: 4, },
+ .red = { .offset = 8, .length = 4, },
+ .green = { .offset = 4, .length = 4, },
+ .blue = { .offset = 0, .length = 4, },
+ .transp = { .offset = 12, .length = 4, },
};
#endif
#ifdef CONFIG_SA1100_GRAPHICSCLIENT
static struct sa1100fb_mach_info graphicsclient_info __initdata = {
- pixclock: 53500, bpp: 8,
- xres: 640, yres: 480,
-
- hsync_len: 9, vsync_len: 9,
- left_margin: 54, upper_margin: 24,
- right_margin: 54, lower_margin: 32,
+ .pixclock = 53500, .bpp = 8,
+ .xres = 640, .yres = 480,
- sync: 0,
+ .hsync_len = 9, .vsync_len = 9,
+ .left_margin = 54, .upper_margin = 24,
+ .right_margin = 54, .lower_margin = 32,
- lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
- lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
+ .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
+ .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
};
#endif
#ifdef CONFIG_SA1100_HUW_WEBPANEL
static struct sa1100fb_mach_info huw_webpanel_info __initdata = {
- pixclock: 0, bpp: 8,
- xres: 640, yres: 480,
+ .pixclock = 0, .bpp = 8,
+ .xres = 640, .yres = 480,
- hsync_len: 3, vsync_len: 1,
- left_margin: 41, upper_margin: 0,
- right_margin: 101, lower_margin: 0,
+ .hsync_len = 3, .vsync_len = 1,
+ .left_margin = 41, .upper_margin = 0,
+ .right_margin = 101, .lower_margin = 0,
- sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- lccr0: LCCR0_Color | LCCR0_Dual | LCCR0_Pas,
- lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2) | 8,
+ .lccr0 = LCCR0_Color | LCCR0_Dual | LCCR0_Pas,
+ .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2) | 8,
#error FIXME
/*
* FIXME: please get rid of the '| 8' in preference to an
@@ -446,99 +440,94 @@ static struct sa1100fb_mach_info huw_webpanel_info __initdata = {
#ifdef LART_GREY_LCD
static struct sa1100fb_mach_info lart_grey_info __initdata = {
- pixclock: 150000, bpp: 4,
- xres: 320, yres: 240,
+ .pixclock = 150000, .bpp = 4,
+ .xres = 320, .yres = 240,
- hsync_len: 1, vsync_len: 1,
- left_margin: 4, upper_margin: 0,
- right_margin: 2, lower_margin: 0,
+ .hsync_len = 1, .vsync_len = 1,
+ .left_margin = 4, .upper_margin = 0,
+ .right_margin = 2, .lower_margin = 0,
- cmap_greyscale: 1,
- sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .cmap_greyscale = 1,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- lccr0: LCCR0_Mono | LCCR0_Sngl | LCCR0_Pas | LCCR0_4PixMono,
- lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(512),
+ .lccr0 = LCCR0_Mono | LCCR0_Sngl | LCCR0_Pas | LCCR0_4PixMono,
+ .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(512),
};
#endif
#ifdef LART_COLOR_LCD
static struct sa1100fb_mach_info lart_color_info __initdata = {
- pixclock: 150000, bpp: 16,
- xres: 320, yres: 240,
+ .pixclock = 150000, .bpp = 16,
+ .xres = 320, .yres = 240,
- hsync_len: 2, vsync_len: 3,
- left_margin: 69, upper_margin: 14,
- right_margin: 8, lower_margin: 4,
+ .hsync_len = 2, .vsync_len = 3,
+ .left_margin = 69, .upper_margin = 14,
+ .right_margin = 8, .lower_margin = 4,
- sync: 0,
-
- lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
- lccr3: LCCR3_OutEnH | LCCR3_PixFlEdg | LCCR3_ACBsDiv(512),
+ .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
+ .lccr3 = LCCR3_OutEnH | LCCR3_PixFlEdg | LCCR3_ACBsDiv(512),
};
#endif
#ifdef LART_VIDEO_OUT
static struct sa1100fb_mach_info lart_video_info __initdata = {
- pixclock: 39721, bpp: 16,
- xres: 640, yres: 480,
+ .pixclock = 39721, .bpp = 16,
+ .xres = 640, .yres = 480,
- hsync_len: 95, vsync_len: 2,
- left_margin: 40, upper_margin: 32,
- right_margin: 24, lower_margin: 11,
+ .hsync_len = 95, .vsync_len = 2,
+ .left_margin = 40, .upper_margin = 32,
+ .right_margin = 24, .lower_margin = 11,
- sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
- lccr3: LCCR3_OutEnL | LCCR3_PixFlEdg | LCCR3_ACBsDiv(512),
+ .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
+ .lccr3 = LCCR3_OutEnL | LCCR3_PixFlEdg | LCCR3_ACBsDiv(512),
};
#endif
#ifdef LART_KIT01_LCD
-static struct sa1100fb_mach_info lart_kit01_info __initdata =
-{
- pixclock: 63291, bpp: 16,
- xres: 640, yres: 480,
+static struct sa1100fb_mach_info lart_kit01_info __initdata = {
+ .pixclock = 63291, .bpp = 16,
+ .xres = 640, .yres = 480,
- hsync_len: 64, vsync_len: 3,
- left_margin: 122, upper_margin: 45,
- right_margin: 10, lower_margin: 10,
+ .hsync_len = 64, .vsync_len = 3,
+ .left_margin = 122, .upper_margin = 45,
+ .right_margin = 10, .lower_margin = 10,
- sync: 0,
-
- lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
- lccr3: LCCR3_OutEnH | LCCR3_PixFlEdg
+ .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
+ .lccr3 = LCCR3_OutEnH | LCCR3_PixFlEdg
};
#endif
#ifdef CONFIG_SA1100_SHANNON
static struct sa1100fb_mach_info shannon_info __initdata = {
- pixclock: 152500, bpp: 8,
- xres: 640, yres: 480,
+ .pixclock = 152500, .bpp = 8,
+ .xres = 640, .yres = 480,
- hsync_len: 4, vsync_len: 3,
- left_margin: 2, upper_margin: 0,
- right_margin: 1, lower_margin: 0,
+ .hsync_len = 4, .vsync_len = 3,
+ .left_margin = 2, .upper_margin = 0,
+ .right_margin = 1, .lower_margin = 0,
- sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- lccr0: LCCR0_Color | LCCR0_Dual | LCCR0_Pas,
- lccr3: LCCR3_ACBsDiv(512),
+ .lccr0 = LCCR0_Color | LCCR0_Dual | LCCR0_Pas,
+ .lccr3 = LCCR3_ACBsDiv(512),
};
#endif
#ifdef CONFIG_SA1100_OMNIMETER
static struct sa1100fb_mach_info omnimeter_info __initdata = {
- pixclock: 0, bpp: 4,
- xres: 480, yres: 320,
+ .pixclock = 0, .bpp = 4,
+ .xres = 480, .yres = 320,
- hsync_len: 1, vsync_len: 1,
- left_margin: 10, upper_margin: 0,
- right_margin: 10, lower_margin: 0,
+ .hsync_len = 1, .vsync_len = 1,
+ .left_margin = 10, .upper_margin = 0,
+ .right_margin = 10, .lower_margin = 0,
- cmap_greyscale: 1,
- sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .cmap_greyscale = 1,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- lccr0: LCCR0_Mono | LCCR0_Sngl | LCCR0_Pas | LCCR0_8PixMono,
- lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(255) |
- LCCR3_PixClkDiv(44),
+ .lccr0 = LCCR0_Mono | LCCR0_Sngl | LCCR0_Pas | LCCR0_8PixMono,
+ .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(255) |
+ LCCR3_PixClkDiv(44),
#error FIXME: fix pixclock, ACBsDiv
/*
* FIXME: I think ACBsDiv is wrong above - should it be 512 (disabled)?
@@ -549,17 +538,17 @@ static struct sa1100fb_mach_info omnimeter_info __initdata = {
#ifdef CONFIG_SA1100_PANGOLIN
static struct sa1100fb_mach_info pangolin_info __initdata = {
- pixclock: 341521, bpp: 16,
- xres: 800, yres: 600,
+ .pixclock = 341521, .bpp = 16,
+ .xres = 800, .yres = 600,
- hsync_len: 64, vsync_len: 7,
- left_margin: 160, upper_margin: 7,
- right_margin: 24, lower_margin: 1,
+ .hsync_len = 64, .vsync_len = 7,
+ .left_margin = 160, .upper_margin = 7,
+ .right_margin = 24, .lower_margin = 1,
- sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
- lccr3: LCCR3_OutEnH | LCCR3_PixFlEdg | LCCR3_ACBsCntOff,
+ .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
+ .lccr3 = LCCR3_OutEnH | LCCR3_PixFlEdg | LCCR3_ACBsCntOff,
};
#endif
@@ -571,49 +560,47 @@ static struct sa1100fb_mach_info pangolin_info __initdata = {
* NB likely to be increased to ease bus timings wrt pcmcia interface
*/
static struct sa1100fb_mach_info stork_tft_info __initdata = {
- pixclock: 28935, bpp: 16,
- xres: 640, yres: 480,
-
- hsync_len: 64, vsync_len: 2,
- left_margin: 48, upper_margin: 12,
- right_margin: 48, lower_margin: 31,
+ .pixclock = 28935, .bpp = 16,
+ .xres = 640, .yres = 480,
- sync: 0,
+ .hsync_len = 64, .vsync_len = 2,
+ .left_margin = 48, .upper_margin = 12,
+ .right_margin = 48, .lower_margin = 31,
- lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
- lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg,
+ .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
+ .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsCntOff,
};
static struct sa1100fb_rgb stork_tft_rgb_16 = {
- red: { offset: 11, length: 5, },
- green: { offset: 5, length: 6, },
- blue: { offset: 0, length: 5, },
- transp: { offset: 0, length: 0, },
+ .red = { .offset = 11, .length = 5, },
+ .green = { .offset = 5, .length = 6, },
+ .blue = { .offset = 0, .length = 5, },
+ .transp = { .offset = 0, .length = 0, },
};
#else /* Kyocera DSTN */
static struct sa1100fb_mach_info stork_dstn_info __initdata = {
- pixclock: 0, bpp: 16,
- xres: 640, yres: 480,
+ .pixclock = 0, .bpp = 16,
+ .xres = 640, .yres = 480,
- hsync_len: 2, vsync_len: 2,
- left_margin: 2, upper_margin: 0,
- right_margin: 2, lower_margin: 0,
+ .hsync_len = 2, .vsync_len = 2,
+ .left_margin = 2, .upper_margin = 0,
+ .right_margin = 2, .lower_margin = 0,
- sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT ,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT ,
- lccr0: LCCR0_Color | LCCR0_Dual | LCCR0_Pas,
+ .lccr0 = LCCR0_Color | LCCR0_Dual | LCCR0_Pas,
#error Fixme
- lccr3: 0xff00 |
+ .lccr3 = 0xff00 |
0x18 /* ought to be 0x14 but DMA isn't up to that as yet */
};
static struct sa1100fb_rgb stork_dstn_rgb_16 = {
- red: { offset: 8, length: 4, },
- green: { offset: 4, length: 4, },
- blue: { offset: 0, length: 4, },
- transp: { offset: 0, length: 0, },
+ .red = { .offset = 8, .length = 4, },
+ .green = { .offset = 4, .length = 4, },
+ .blue = { .offset = 0, .length = 4, },
+ .transp = { .offset = 0, .length = 0, },
};
#endif
#endif
@@ -630,34 +617,31 @@ static struct sa1100fb_rgb stork_dstn_rgb_16 = {
* =>4.32Mhz => 231481E-12s
*/
static struct sa1100fb_mach_info system3_info __initdata = {
- pixclock: 231481, bpp: 8,
- xres: 640, yres: 480,
+ .pixclock = 231481, .bpp = 8,
+ .xres = 640, .yres = 480,
- hsync_len: 2, vsync_len: 2,
- left_margin: 2, upper_margin: 0,
- right_margin: 2, lower_margin: 0,
+ .hsync_len = 2, .vsync_len = 2,
+ .left_margin = 2, .upper_margin = 0,
+ .right_margin = 2, .lower_margin = 0,
- sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- lccr0: LCCR0_Color | LCCR0_Dual | LCCR0_Pas,
- lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(512) |
- LCCR3_ACBsCntOff,
+ .lccr0 = LCCR0_Color | LCCR0_Dual | LCCR0_Pas,
+ .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(512),
};
#endif
#ifdef CONFIG_SA1100_XP860
static struct sa1100fb_mach_info xp860_info __initdata = {
- pixclock: 0, bpp: 8,
- xres: 1024, yres: 768,
-
- hsync_len: 3, vsync_len: 3,
- left_margin: 3, upper_margin: 2,
- right_margin: 2, lower_margin: 1,
+ .pixclock = 0, .bpp = 8,
+ .xres = 1024, .yres = 768,
- sync: 0,
+ .hsync_len = 3, .vsync_len = 3,
+ .left_margin = 3, .upper_margin = 2,
+ .right_margin = 2, .lower_margin = 1,
- lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
- lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_PixClkDiv(6),
+ .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
+ .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_PixClkDiv(6),
};
#endif
@@ -808,33 +792,7 @@ static inline void sa1100fb_schedule_task(struct sa1100fb_info *fbi, u_int state
local_irq_restore(flags);
}
-/*
- * Get the VAR structure pointer for the specified console
- */
-static inline struct fb_var_screeninfo *get_con_var(struct fb_info *info, int con)
-{
- return (con == info->currcon || con == -1) ? &info->var : &fb_display[con].var;
-}
-
-/*
- * Get the DISPLAY structure pointer for the specified console
- */
-static inline struct display *get_con_display(struct fb_info *info, int con)
-{
- struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
- return (con < 0) ? fbi->fb.disp : &fb_display[con];
-}
-
-/*
- * Get the CMAP pointer for the specified console
- */
-static inline struct fb_cmap *get_con_cmap(struct fb_info *info, int con)
-{
- return (con == info->currcon || con == -1) ? &info->cmap : &fb_display[con].cmap;
-}
-
-static inline u_int
-chan_to_field(u_int chan, struct fb_bitfield *bf)
+static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
{
chan &= 0xffff;
chan >>= 16 - bf->length;
@@ -844,8 +802,7 @@ chan_to_field(u_int chan, struct fb_bitfield *bf)
/*
* Convert bits-per-pixel to a hardware palette PBS value.
*/
-static inline u_int
-palette_pbs(struct fb_var_screeninfo *var)
+static inline u_int palette_pbs(struct fb_var_screeninfo *var)
{
int ret = 0;
switch (var->bits_per_pixel) {
@@ -888,8 +845,7 @@ sa1100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int trans, struct fb_info *info)
{
struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
- struct display *disp = get_con_display(info, info->currcon);
- u_int val;
+ unsigned int val;
int ret = 1;
/*
@@ -898,7 +854,7 @@ sa1100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
* is what you poke into the framebuffer to produce the
* colour you requested.
*/
- if (disp->inverse) {
+ if (fbi->cmap_inverse) {
red = 0xffff - red;
green = 0xffff - green;
blue = 0xffff - blue;
@@ -912,7 +868,7 @@ sa1100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
red = green = blue = (19595 * red + 38470 * green +
7471 * blue) >> 16;
- switch (fbi->fb.disp->visual) {
+ switch (fbi->fb.fix.visual) {
case FB_VISUAL_TRUECOLOR:
/*
* 12 or 16-bit True Colour. We encode the RGB value
@@ -942,38 +898,29 @@ sa1100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
/*
* sa1100fb_display_dma_period()
* Calculate the minimum period (in picoseconds) between two DMA
- * requests for the LCD controller.
+ * requests for the LCD controller. If we hit this, it means we're
+ * doing nothing but LCD DMA.
*/
-static unsigned int
-sa1100fb_display_dma_period(struct fb_var_screeninfo *var)
+static unsigned int sa1100fb_display_dma_period(struct fb_var_screeninfo *var)
{
- unsigned int mem_bits_per_pixel;
-
- mem_bits_per_pixel = var->bits_per_pixel;
- if (mem_bits_per_pixel == 12)
- mem_bits_per_pixel = 16;
-
/*
* Period = pixclock * bits_per_byte * bytes_per_transfer
* / memory_bits_per_pixel;
*/
- return var->pixclock * 8 * 16 / mem_bits_per_pixel;
+ return var->pixclock * 8 * 16 / var->bits_per_pixel;
}
/*
- * sa1100fb_decode_var():
- * Get the video params out of 'var'. If a value doesn't fit, round it up,
- * if it's too big, return -EINVAL.
- *
- * Suggestion: Round up in the following order: bits_per_pixel, xres,
+ * sa1100fb_check_var():
+ * Round up in the following order: bits_per_pixel, xres,
* yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale,
* bitfields, horizontal timing, vertical timing.
*/
static int
-sa1100fb_validate_var(struct fb_var_screeninfo *var,
- struct sa1100fb_info *fbi)
+sa1100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
- int ret = -EINVAL;
+ struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
+ int rgbidx;
if (var->xres < MIN_XRES)
var->xres = MIN_XRES;
@@ -983,42 +930,60 @@ sa1100fb_validate_var(struct fb_var_screeninfo *var,
var->xres = fbi->max_xres;
if (var->yres > fbi->max_yres)
var->yres = fbi->max_yres;
- var->xres_virtual =
- var->xres_virtual < var->xres ? var->xres : var->xres_virtual;
- var->yres_virtual =
- var->yres_virtual < var->yres ? var->yres : var->yres_virtual;
+ var->xres_virtual = max(var->xres_virtual, var->xres);
+ var->yres_virtual = max(var->yres_virtual, var->yres);
DPRINTK("var->bits_per_pixel=%d\n", var->bits_per_pixel);
switch (var->bits_per_pixel) {
#ifdef FBCON_HAS_CFB4
- case 4: ret = 0; break;
+ case 4:
+ rgbidx = RGB_8;
+ break;
#endif
#ifdef FBCON_HAS_CFB8
- case 8: ret = 0; break;
+ case 8:
+ rgbidx = RGB_8;
+ break;
#endif
#ifdef FBCON_HAS_CFB16
- case 16: ret = 0; break;
+ case 16:
+ rgbidx = RGB_16;
+ break;
#endif
default:
- break;
+ return -EINVAL;
}
+ /*
+ * Copy the RGB parameters for this display
+ * from the machine specific parameters.
+ */
+ var->red = fbi->rgb[rgbidx]->red;
+ var->green = fbi->rgb[rgbidx]->green;
+ var->blue = fbi->rgb[rgbidx]->blue;
+ var->transp = fbi->rgb[rgbidx]->transp;
+
+ DPRINTK("RGBT length = %d:%d:%d:%d\n",
+ var->red.length, var->green.length, var->blue.length,
+ var->transp.length);
+
+ DPRINTK("RGBT offset = %d:%d:%d:%d\n",
+ var->red.offset, var->green.offset, var->blue.offset,
+ var->transp.offset);
+
#ifdef CONFIG_CPU_FREQ
printk(KERN_DEBUG "dma period = %d ps, clock = %d kHz\n",
sa1100fb_display_dma_period(var),
cpufreq_get(smp_processor_id()));
#endif
- return ret;
+ return 0;
}
static inline void sa1100fb_set_truecolor(u_int is_true_color)
{
- DPRINTK("true_color = %d\n", is_true_color);
-
if (machine_is_assabet()) {
-#if 1
- // phase 4 or newer Assabet's
+#if 1 // phase 4 or newer Assabet's
if (is_true_color)
ASSABET_BCR_set(ASSABET_BCR_LCD_12RGB);
else
@@ -1033,10 +998,30 @@ static inline void sa1100fb_set_truecolor(u_int is_true_color)
}
}
-static void
-sa1100fb_hw_set_var(struct fb_var_screeninfo *var, struct sa1100fb_info *fbi)
+/*
+ * sa1100fb_set_par():
+ * Set the user defined part of the display for the specified console
+ */
+static int sa1100fb_set_par(struct fb_info *info)
{
- u_long palette_mem_size;
+ struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
+ struct fb_var_screeninfo *var = &info->var;
+ unsigned long palette_mem_size;
+
+ DPRINTK("set_par\n");
+
+ if (var->bits_per_pixel == 16)
+ fbi->fb.fix.visual = FB_VISUAL_TRUECOLOR;
+ else if (!fbi->cmap_static)
+ fbi->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
+ else {
+ /*
+ * Some people have weird ideas about wanting static
+ * pseudocolor maps. I suspect their user space
+ * applications are broken.
+ */
+ fbi->fb.fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
+ }
fbi->palette_size = var->bits_per_pixel == 8 ? 256 : 16;
@@ -1047,10 +1032,10 @@ sa1100fb_hw_set_var(struct fb_var_screeninfo *var, struct sa1100fb_info *fbi)
fbi->palette_cpu = (u16 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size);
fbi->palette_dma = fbi->map_dma + PAGE_SIZE - palette_mem_size;
- fb_set_cmap(&fbi->fb.cmap, 1, &fbi->fb);
-
- /* Set board control register to handle new color depth */
- sa1100fb_set_truecolor(var->bits_per_pixel >= 16);
+ /*
+ * Set (any) board control register to handle new color depth
+ */
+ sa1100fb_set_truecolor(fbi->fb.fix.visual == FB_VISUAL_TRUECOLOR);
#ifdef CONFIG_SA1100_OMNIMETER
#error Do we have to do this here? We already do it at init time.
@@ -1060,9 +1045,7 @@ sa1100fb_hw_set_var(struct fb_var_screeninfo *var, struct sa1100fb_info *fbi)
sa1100fb_activate_var(var, fbi);
- fbi->palette_cpu[0] = (fbi->palette_cpu[0] &
- 0xcfff) | palette_pbs(var);
-
+ return 0;
}
/*
@@ -1072,197 +1055,38 @@ sa1100fb_hw_set_var(struct fb_var_screeninfo *var, struct sa1100fb_info *fbi)
static int
sa1100fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
{
- struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
- struct fb_var_screeninfo *dvar = get_con_var(&fbi->fb, con);
- struct display *display = get_con_display(&fbi->fb, con);
- int err, chgvar = 0, rgbidx;
-
- DPRINTK("set_var\n");
+ int ret, act;
- /*
- * Decode var contents into a par structure, adjusting any
- * out of range values.
- */
- err = sa1100fb_validate_var(var, fbi);
- if (err)
- return err;
+ act = var->activate & FB_ACTIVATE_MASK;
- if (var->activate & FB_ACTIVATE_TEST)
- return 0;
+ ret = gen_set_var(var, con, info);
- if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW)
- return -EINVAL;
+ if (ret == 0 && act & FB_ACTIVATE_NOW) {
+ struct display *display = (con < 0) ? info->disp : fb_display + con;
- if (dvar->xres != var->xres)
- chgvar = 1;
- if (dvar->yres != var->yres)
- chgvar = 1;
- if (dvar->xres_virtual != var->xres_virtual)
- chgvar = 1;
- if (dvar->yres_virtual != var->yres_virtual)
- chgvar = 1;
- if (dvar->bits_per_pixel != var->bits_per_pixel)
- chgvar = 1;
- if (con < 0)
- chgvar = 0;
-
- switch (var->bits_per_pixel) {
-#ifdef FBCON_HAS_CFB4
- case 4:
- if (fbi->cmap_static)
- display->visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
- else
- display->visual = FB_VISUAL_PSEUDOCOLOR;
- display->line_length = var->xres / 2;
- display->dispsw = &fbcon_cfb4;
- rgbidx = RGB_8;
- break;
-#endif
-#ifdef FBCON_HAS_CFB8
- case 8:
- if (fbi->cmap_static)
- display->visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
- else
- display->visual = FB_VISUAL_PSEUDOCOLOR;
- display->line_length = var->xres;
- display->dispsw = &fbcon_cfb8;
- rgbidx = RGB_8;
- break;
-#endif
-#ifdef FBCON_HAS_CFB16
- case 16:
- display->visual = FB_VISUAL_TRUECOLOR;
- display->line_length = var->xres * 2;
- display->dispsw = &fbcon_cfb16;
- display->dispsw_data = fbi->fb.pseudo_palette;
- rgbidx = RGB_16;
- break;
-#endif
- default:
- rgbidx = 0;
- display->dispsw = &fbcon_dummy;
- break;
+ /*
+ * fbcon assumes too much.
+ */
+ display->can_soft_blank = 1;
}
- display->next_line = display->line_length;
- display->type = fbi->fb.fix.type;
- display->type_aux = fbi->fb.fix.type_aux;
- display->ypanstep = fbi->fb.fix.ypanstep;
- display->ywrapstep = fbi->fb.fix.ywrapstep;
- display->can_soft_blank = 1;
- display->inverse = fbi->cmap_inverse;
-
- *dvar = *var;
- dvar->activate &= ~FB_ACTIVATE_ALL;
-
- /*
- * Copy the RGB parameters for this display
- * from the machine specific parameters.
- */
- dvar->red = fbi->rgb[rgbidx]->red;
- dvar->green = fbi->rgb[rgbidx]->green;
- dvar->blue = fbi->rgb[rgbidx]->blue;
- dvar->transp = fbi->rgb[rgbidx]->transp;
-
- DPRINTK("RGBT length = %d:%d:%d:%d\n",
- dvar->red.length, dvar->green.length, dvar->blue.length,
- dvar->transp.length);
-
- DPRINTK("RGBT offset = %d:%d:%d:%d\n",
- dvar->red.offset, dvar->green.offset, dvar->blue.offset,
- dvar->transp.offset);
-
- /*
- * Update the old var. The fbcon drivers still use this.
- * Once they are using fbi->fb.var, this can be dropped.
- */
- display->var = *dvar;
-
- /*
- * If we are setting all the virtual consoles, also set the
- * defaults used to create new consoles.
- */
- if (var->activate & FB_ACTIVATE_ALL)
- fbi->fb.disp->var = *dvar;
-
- /*
- * If the console has changed and the console has defined
- * a changevar function, call that function.
- */
- if (chgvar && info && fbi->fb.changevar)
- fbi->fb.changevar(con);
-
- /* If the current console is selected, activate the new var. */
- if (con != fbi->fb.currcon)
- return 0;
-
- sa1100fb_hw_set_var(dvar, fbi);
-
- return 0;
-}
-
-static int
-__do_set_cmap(struct fb_cmap *cmap, int kspc, int con,
- struct fb_info *info)
-{
- struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
- struct fb_cmap *dcmap = get_con_cmap(info, con);
- int err = 0;
-
- if (con == -1)
- con = info->currcon;
-
- /* no colormap allocated? (we always have "this" colour map allocated) */
- if (con >= 0)
- err = fb_alloc_cmap(&fb_display[con].cmap, fbi->palette_size, 0);
-
- if (!err && con == info->currcon)
- err = fb_set_cmap(cmap, kspc, info);
-
- if (!err)
- fb_copy_cmap(cmap, dcmap, kspc ? 0 : 1);
-
- return err;
+ return ret;
}
static int
sa1100fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
- struct display *disp = get_con_display(info, con);
+ struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
+ struct display *disp = (con < 0) ? info->disp : (fb_display + con);
- if (disp->visual == FB_VISUAL_TRUECOLOR ||
- disp->visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
+ /*
+ * Make sure the user isn't doing something stupid.
+ */
+ if (!kspc && (disp->var.bits_per_pixel == 16 || fbi->cmap_static))
return -EINVAL;
- return __do_set_cmap(cmap, kspc, con, info);
-}
-
-static int
-sa1100fb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
-{
- struct display *display = get_con_display(info, con);
-
- *fix = info->fix;
-
- fix->line_length = display->line_length;
- fix->visual = display->visual;
- return 0;
-}
-
-static int
-sa1100fb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
-{
- *var = *get_con_var(info, con);
- return 0;
-}
-
-static int
-sa1100fb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
-{
- struct fb_cmap *dcmap = get_con_cmap(info, con);
- fb_copy_cmap(dcmap, cmap, kspc ? 0 : 2);
- return 0;
+ return gen_set_cmap(cmap, kspc, con, info);
}
/*
@@ -1312,16 +1136,16 @@ static int sa1100fb_blank(int blank, struct fb_info *info)
case VESA_POWERDOWN:
case VESA_VSYNC_SUSPEND:
case VESA_HSYNC_SUSPEND:
- if (fbi->fb.disp->visual == FB_VISUAL_PSEUDOCOLOR ||
- fbi->fb.disp->visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
+ if (fbi->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR ||
+ fbi->fb.fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
for (i = 0; i < fbi->palette_size; i++)
sa1100fb_setpalettereg(i, 0, 0, 0, 0, info);
sa1100fb_schedule_task(fbi, C_DISABLE);
break;
case VESA_NO_BLANKING:
- if (fbi->fb.disp->visual == FB_VISUAL_PSEUDOCOLOR ||
- fbi->fb.disp->visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
+ if (fbi->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR ||
+ fbi->fb.fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
fb_set_cmap(&fbi->fb.cmap, 1, info);
sa1100fb_schedule_task(fbi, C_ENABLE);
}
@@ -1329,71 +1153,19 @@ static int sa1100fb_blank(int blank, struct fb_info *info)
}
static struct fb_ops sa1100fb_ops = {
- owner: THIS_MODULE,
- fb_get_fix: sa1100fb_get_fix,
- fb_get_var: sa1100fb_get_var,
- fb_set_var: sa1100fb_set_var,
- fb_get_cmap: sa1100fb_get_cmap,
- fb_set_cmap: sa1100fb_set_cmap,
- fb_setcolreg: sa1100fb_setcolreg,
- fb_blank: sa1100fb_blank,
+ .owner = THIS_MODULE,
+ .fb_check_var = sa1100fb_check_var,
+ .fb_set_par = sa1100fb_set_par,
+ .fb_set_var = sa1100fb_set_var,
+ .fb_get_cmap = gen_get_cmap,
+ .fb_set_cmap = sa1100fb_set_cmap,
+ .fb_setcolreg = sa1100fb_setcolreg,
+ .fb_blank = sa1100fb_blank,
};
-/*
- * sa1100fb_switch():
- * Change to the specified console. Palette and video mode
- * are changed to the console's stored parameters.
- *
- * Uh oh, this can be called from a tasklet (IRQ)
- */
-static int sa1100fb_switch(int con, struct fb_info *info)
-{
- struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
- struct display *disp;
- struct fb_cmap *cmap;
-
- DPRINTK("con=%d info->modename=%s\n", con, fbi->fb.modename);
-
- if (con == info->currcon)
- return 0;
-
- if (info->currcon >= 0) {
- disp = fb_display + info->currcon;
-
- /*
- * Save the old colormap and video mode.
- */
- disp->var = fbi->fb.var;
-
- if (disp->cmap.len)
- fb_copy_cmap(&fbi->fb.cmap, &disp->cmap, 0);
- }
-
- info->currcon = con;
- disp = fb_display + con;
-
- /*
- * Make sure that our colourmap contains 256 entries.
- */
- fb_alloc_cmap(&fbi->fb.cmap, 256, 0);
-
- if (disp->cmap.len)
- cmap = &disp->cmap;
- else
- cmap = fb_default_cmap(1 << disp->var.bits_per_pixel);
-
- fb_copy_cmap(cmap, &fbi->fb.cmap, 0);
-
- fbi->fb.var = disp->var;
- fbi->fb.var.activate = FB_ACTIVATE_NOW;
-
- sa1100fb_set_var(&fbi->fb.var, con, info);
- return 0;
-}
-
static int sa1100fb_updatevar(int con, struct fb_info *info)
{
- DPRINTK("entered\n");
+ /* we don't support panning nor scrolling */
return 0;
}
@@ -1401,34 +1173,14 @@ static int sa1100fb_updatevar(int con, struct fb_info *info)
* Calculate the PCD value from the clock rate (in picoseconds).
* We take account of the PPCR clock setting.
*/
-static inline int get_pcd(unsigned int pixclock)
+static inline unsigned int get_pcd(unsigned int pixclock, unsigned int cpuclock)
{
- unsigned int pcd;
-
- if (pixclock) {
- pcd = cpufreq_get(0) / 100;
- pcd *= pixclock;
- pcd /= 10000000;
- pcd += 1; /* make up for integer math truncations */
- } else {
- /*
- * People seem to be missing this message. Make it big.
- * Make it stand out. Make sure people see it.
- */
- printk(KERN_WARNING "******************************************************\n");
- printk(KERN_WARNING "** ZERO PIXEL CLOCK DETECTED **\n");
- printk(KERN_WARNING "** You are using a zero pixclock. This means that **\n");
- printk(KERN_WARNING "** clock scaling will not be able to adjust your **\n");
- printk(KERN_WARNING "** your timing parameters appropriately, and the **\n");
- printk(KERN_WARNING "** bandwidth calculations will fail to work. This **\n");
- printk(KERN_WARNING "** will shortly become an error condition, which **\n");
- printk(KERN_WARNING "** will prevent your LCD display working. Please **\n");
- printk(KERN_WARNING "** send your patches in as soon as possible to shut **\n");
- printk(KERN_WARNING "** this message up. **\n");
- printk(KERN_WARNING "******************************************************\n");
- pcd = 0;
- }
- return pcd;
+ unsigned int pcd = cpuclock / 100;
+
+ pcd *= pixclock;
+ pcd /= 10000000;
+
+ return pcd + 1; /* make up for integer math truncations */
}
/*
@@ -1439,7 +1191,7 @@ static inline int get_pcd(unsigned int pixclock)
static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_info *fbi)
{
struct sa1100fb_lcd_reg new_regs;
- u_int half_screen_size, yres, pcd = get_pcd(var->pixclock);
+ u_int half_screen_size, yres, pcd;
u_long flags;
DPRINTK("Configuring SA1100 LCD\n");
@@ -1502,13 +1254,10 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_
LCCR2_BegFrmDel(var->upper_margin) +
LCCR2_EndFrmDel(var->lower_margin);
- new_regs.lccr3 = fbi->lccr3 |
+ pcd = get_pcd(var->pixclock, cpufreq_get(0));
+ new_regs.lccr3 = LCCR3_PixClkDiv(pcd) | fbi->lccr3 |
(var->sync & FB_SYNC_HOR_HIGH_ACT ? LCCR3_HorSnchH : LCCR3_HorSnchL) |
- (var->sync & FB_SYNC_VERT_HIGH_ACT ? LCCR3_VrtSnchH : LCCR3_VrtSnchL) |
- LCCR3_ACBsCntOff;
-
- if (pcd)
- new_regs.lccr3 |= LCCR3_PixClkDiv(pcd);
+ (var->sync & FB_SYNC_VERT_HIGH_ACT ? LCCR3_VrtSnchH : LCCR3_VrtSnchL);
DPRINTK("nlccr0 = 0x%08x\n", new_regs.lccr0);
DPRINTK("nlccr1 = 0x%08x\n", new_regs.lccr1);
@@ -1547,61 +1296,20 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_
* to ensure that things happen in the right way 100% of time time.
* -- rmk
*/
-
-/*
- * FIXME: move LCD power stuff into sa1100fb_power_up_lcd()
- * Also, I'm expecting that the backlight stuff should
- * be handled differently.
- */
-static inline void sa1100fb_backlight_on(struct sa1100fb_info *fbi)
-{
- DPRINTK("backlight on\n");
-
- if (sa1100fb_backlight_power)
- sa1100fb_backlight_power(1);
-}
-
-/*
- * FIXME: move LCD power stuf into sa1100fb_power_down_lcd()
- * Also, I'm expecting that the backlight stuff should
- * be handled differently.
- */
-static inline void sa1100fb_backlight_off(struct sa1100fb_info *fbi)
+static inline void __sa1100fb_backlight_power(struct sa1100fb_info *fbi, int on)
{
- DPRINTK("backlight off\n");
+ DPRINTK("backlight o%s\n", on ? "n" : "ff");
if (sa1100fb_backlight_power)
- sa1100fb_backlight_power(0);
+ sa1100fb_backlight_power(on);
}
-static inline void sa1100fb_power_up_lcd(struct sa1100fb_info *fbi)
+static inline void __sa1100fb_lcd_power(struct sa1100fb_info *fbi, int on)
{
- DPRINTK("LCD power on\n");
+ DPRINTK("LCD power o%s\n", on ? "n" : "ff");
if (sa1100fb_lcd_power)
- sa1100fb_lcd_power(1);
-
-#ifdef CONFIG_SA1100_STORK
- if (machine_is_stork()) {
- storkSetLCDCPLD(0, 1);
- storkSetLatchA(STORK_LCD_BACKLIGHT_INVERTER_ON);
- }
-#endif
-}
-
-static inline void sa1100fb_power_down_lcd(struct sa1100fb_info *fbi)
-{
- DPRINTK("LCD power off\n");
-
- if (sa1100fb_lcd_power)
- sa1100fb_lcd_power(0);
-
-#ifdef CONFIG_SA1100_STORK
- if (machine_is_stork()) {
- storkSetLCDCPLD(0, 0);
- storkClearLatchA(STORK_LCD_BACKLIGHT_INVERTER_ON);
- }
-#endif
+ sa1100fb_lcd_power(on);
}
static void sa1100fb_setup_gpio(struct sa1100fb_info *fbi)
@@ -1630,38 +1338,9 @@ static void sa1100fb_setup_gpio(struct sa1100fb_info *fbi)
}
- if (machine_is_cerf()) {
- /* GPIO15 is used as a bypass for 3.8" displays */
+ /* GPIO15 is used as a bypass for 3.8" displays */
+ if (machine_is_cerf())
mask |= GPIO_GPIO15;
-#ifdef CONFIG_SA1100_CERF
-#warning Read Me Now!
-#endif
-#if 0 /* if this causes you problems, mail <rmk@arm.linux.org.uk> please. */
- /*
- * This was enabled for the 72_A version only, which is a _color_
- * _dual_ LCD. Now look at the generic test above, and calculate
- * the mask value for a colour dual display...
- *
- * I therefore conclude that the code below is redundant, and will
- * be killed at the start of November 2001.
- */
- /* FIXME: why is this? The Cerf's display doesn't seem
- * to be dual scan or active. I just leave it here,
- * but in my opinion this is definitively wrong.
- * -- Erik <J.A.K.Mouw@its.tudelft.nl>
- */
-
- /* REPLY: Umm.. Well to be honest, the 5.7" LCD which
- * this was used for does not use these pins, but
- * apparently all hell breaks loose if they are not
- * set on the Cerf, so we decided to leave them in ;)
- * -- Daniel Chemko <dchemko@intrinsyc.com>
- */
- /* color {dual/single} passive */
- mask |= GPIO_LDD15 | GPIO_LDD14 | GPIO_LDD13 | GPIO_LDD12 |
- GPIO_LDD11 | GPIO_LDD10 | GPIO_LDD9 | GPIO_LDD8;
-#endif
- }
if (mask) {
GPDR |= mask;
@@ -1733,7 +1412,7 @@ static void sa1100fb_disable_controller(struct sa1100fb_info *fbi)
}
#endif
#ifdef CONFIG_SA1100_HUW_WEBPANEL
-#error Move me into sa1100fb_power_up_lcd and/or sa1100fb_backlight_on
+#error Move me into __sa1100fb_lcd_power and/or __sa1100fb_backlight_power
if (machine_is_huw_webpanel()) {
// dont forget to set the control lines to zero (?)
DPRINTK("ShutDown HuW LCD controller\n");
@@ -1806,10 +1485,10 @@ static void set_ctrlr_state(struct sa1100fb_info *fbi, u_int state)
if (old_state != C_DISABLE) {
fbi->state = state;
- sa1100fb_backlight_off(fbi);
+ __sa1100fb_backlight_power(fbi, 0);
if (old_state != C_DISABLE_CLKCHANGE)
sa1100fb_disable_controller(fbi);
- sa1100fb_power_down_lcd(fbi);
+ __sa1100fb_lcd_power(fbi, 0);
}
break;
@@ -1855,9 +1534,9 @@ static void set_ctrlr_state(struct sa1100fb_info *fbi, u_int state)
if (old_state != C_ENABLE) {
fbi->state = C_ENABLE;
sa1100fb_setup_gpio(fbi);
- sa1100fb_power_up_lcd(fbi);
+ __sa1100fb_lcd_power(fbi, 1);
sa1100fb_enable_controller(fbi);
- sa1100fb_backlight_on(fbi);
+ __sa1100fb_backlight_power(fbi, 1);
}
break;
}
@@ -1888,18 +1567,19 @@ static unsigned int sa1100fb_min_dma_period(struct sa1100fb_info *fbi)
int i;
for (i = 0; i < MAX_NR_CONSOLES; i++) {
+ struct display *disp = &fb_display[i];
unsigned int period;
/*
* Do we own this display?
*/
- if (fb_display[i].fb_info != &fbi->fb)
+ if (disp->fb_info != &fbi->fb)
continue;
/*
* Ok, calculate its DMA period
*/
- period = sa1100fb_display_dma_period(get_con_var(&fbi->fb, i));
+ period = sa1100fb_display_dma_period(&disp->var);
if (period < min_period)
min_period = period;
}
@@ -1913,33 +1593,42 @@ static unsigned int sa1100fb_min_dma_period(struct sa1100fb_info *fbi)
* subsystem.
*/
static int
-sa1100fb_clkchg_notifier(struct notifier_block *nb, unsigned long val,
+sa1100fb_freq_transition(struct notifier_block *nb, unsigned long val,
void *data)
{
- struct sa1100fb_info *fbi = TO_INF(nb, clockchg);
- struct cpufreq_minmax *mm = data;
+ struct sa1100fb_info *fbi = TO_INF(nb, freq_transition);
+ struct cpufreq_freqs *f = data;
u_int pcd;
switch (val) {
- case CPUFREQ_MINMAX:
- printk(KERN_DEBUG "min dma period: %d ps, old clock %d kHz, "
- "new clock %d kHz\n", sa1100fb_min_dma_period(fbi),
- mm->cur_freq, mm->new_freq);
- /* todo: fill in min/max values */
- break;
-
case CPUFREQ_PRECHANGE:
set_ctrlr_state(fbi, C_DISABLE_CLKCHANGE);
break;
case CPUFREQ_POSTCHANGE:
- pcd = get_pcd(fbi->fb.var.pixclock);
+ pcd = get_pcd(fbi->fb.var.pixclock, f->new);
fbi->reg_lccr3 = (fbi->reg_lccr3 & ~0xff) | LCCR3_PixClkDiv(pcd);
set_ctrlr_state(fbi, C_ENABLE_CLKCHANGE);
break;
}
return 0;
}
+
+static int
+sa1100fb_freq_policy(struct notifier_block *nb, unsigned long val,
+ void *data)
+{
+ struct sa1100fb_info *fbi = TO_INF(nb, freq_policy);
+ struct cpufreq_policy *policy = data;
+
+ if (val == CPUFREQ_INCOMPATIBLE) {
+ printk(KERN_DEBUG "min dma period: %d ps, "
+ "new clock %d kHz\n", sa1100fb_min_dma_period(fbi),
+ policy->max);
+ /* todo: fill in min/max values */
+ }
+ return 0;
+}
#endif
#ifdef CONFIG_PM
@@ -2015,8 +1704,6 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(void)
memset(fbi, 0, sizeof(struct sa1100fb_info) + sizeof(struct display));
- fbi->fb.currcon = -1;
-
strcpy(fbi->fb.fix.id, SA1100_NAME);
fbi->fb.fix.type = FB_TYPE_PACKED_PIXELS;
@@ -2024,6 +1711,7 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(void)
fbi->fb.fix.xpanstep = 0;
fbi->fb.fix.ypanstep = 0;
fbi->fb.fix.ywrapstep = 0;
+ fbi->fb.fix.line_length = 0;
fbi->fb.fix.accel = FB_ACCEL_NONE;
fbi->fb.var.nonstd = 0;
@@ -2038,7 +1726,7 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(void)
fbi->fb.fbops = &sa1100fb_ops;
fbi->fb.changevar = NULL;
- fbi->fb.switch_con = sa1100fb_switch;
+ fbi->fb.switch_con = gen_switch;
fbi->fb.updatevar = sa1100fb_updatevar;
fbi->fb.flags = FBINFO_FLAG_DEFAULT;
fbi->fb.node = NODEV;
@@ -2052,6 +1740,16 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(void)
inf = sa1100fb_get_machine_info(fbi);
+ /*
+ * People just don't seem to get this. We don't support
+ * anything but correct entries now, so panic if someone
+ * does something stupid.
+ */
+ if (inf->lccr3 & (LCCR3_VrtSnchL|LCCR3_HorSnchL|0xff) ||
+ inf->pixclock == 0)
+ panic("sa1100fb error: invalid LCCR3 fields set or zero "
+ "pixclock.");
+
fbi->max_xres = inf->xres;
fbi->fb.var.xres = inf->xres;
fbi->fb.var.xres_virtual = inf->xres;
@@ -2077,6 +1775,7 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(void)
fbi->task_state = (u_char)-1;
fbi->fb.fix.smem_len = fbi->max_xres * fbi->max_yres *
fbi->max_bpp / 8;
+ fbi->fb.disp->inverse = inf->cmap_inverse;
init_waitqueue_head(&fbi->ctrlr_wait);
INIT_TQUEUE(&fbi->task, sa1100fb_task, fbi);
@@ -2116,7 +1815,7 @@ int __init sa1100fb_init(void)
#endif
#ifdef CONFIG_SA1100_FREEBIRD
-#error Please move this into sa1100fb_power_up_lcd
+#error Please move this into __sa1100fb_lcd_power
if (machine_is_freebird()) {
BCR_set(BCR_FREEBIRD_LCD_DISP);
mdelay(20);
@@ -2141,8 +1840,10 @@ int __init sa1100fb_init(void)
fbi->pm->data = fbi;
#endif
#ifdef CONFIG_CPU_FREQ
- fbi->clockchg.notifier_call = sa1100fb_clkchg_notifier;
- cpufreq_register_notifier(&fbi->clockchg);
+ fbi->freq_transition.notifier_call = sa1100fb_freq_transition;
+ fbi->freq_policy.notifier_call = sa1100fb_freq_policy;
+ cpufreq_register_notifier(&fbi->freq_transition, CPUFREQ_TRANSITION_NOTIFIER);
+ cpufreq_register_notifier(&fbi->freq_policy, CPUFREQ_POLICY_NOTIFIER);
#endif
/*
diff --git a/drivers/video/sa1100fb.h b/drivers/video/sa1100fb.h
index 96e79705be5c..9b3b4a402a51 100644
--- a/drivers/video/sa1100fb.h
+++ b/drivers/video/sa1100fb.h
@@ -107,7 +107,8 @@ struct sa1100fb_info {
struct pm_dev *pm;
#endif
#ifdef CONFIG_CPU_FREQ
- struct notifier_block clockchg;
+ struct notifier_block freq_transition;
+ struct notifier_block freq_policy;
#endif
};
diff --git a/fs/devfs/base.c b/fs/devfs/base.c
index 3d80896ebd8f..5186280cfd7b 100644
--- a/fs/devfs/base.c
+++ b/fs/devfs/base.c
@@ -2396,7 +2396,6 @@ static int check_disc_changed (struct devfs_entry *de)
warn_no_part = 0;
retval = full_check_disk_change (bdev);
warn_no_part = tmp;
-out:
devfs_put_ops (de);
return retval;
} /* End Function check_disc_changed */
diff --git a/fs/driverfs/inode.c b/fs/driverfs/inode.c
index af1ed60b5646..0f35e27e669c 100644
--- a/fs/driverfs/inode.c
+++ b/fs/driverfs/inode.c
@@ -703,3 +703,4 @@ EXPORT_SYMBOL(driverfs_create_symlink);
EXPORT_SYMBOL(driverfs_create_dir);
EXPORT_SYMBOL(driverfs_remove_file);
EXPORT_SYMBOL(driverfs_remove_dir);
+MODULE_LICENSE("GPL");
diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c
index c08e0da58c1d..a10c66e58996 100644
--- a/fs/jfs/jfs_logmgr.c
+++ b/fs/jfs/jfs_logmgr.c
@@ -1202,8 +1202,6 @@ int lmLogInit(struct jfs_log * log)
/*
* validate log superblock
*/
-
-
if (!test_bit(log_INLINELOG, &log->flag))
log->l2bsize = 12; /* XXX kludge alert XXX */
if ((rc = lbmRead(log, 1, &bpsuper)))
diff --git a/fs/nls/nls_cp1250.c b/fs/nls/nls_cp1250.c
index afae07580e35..982dc66a5227 100644
--- a/fs/nls/nls_cp1250.c
+++ b/fs/nls/nls_cp1250.c
@@ -344,7 +344,7 @@ static void __exit exit_nls_cp1250(void)
module_init(init_nls_cp1250)
module_exit(exit_nls_cp1250)
-MODULE_LICENSE("BSD without advertising clause");
+MODULE_LICENSE("Dual BSD/GPL");
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/include/asm-arm/arch-sa1100/h3600.h b/include/asm-arm/arch-sa1100/h3600.h
index d0fc9198c9eb..1b6355971574 100644
--- a/include/asm-arm/arch-sa1100/h3600.h
+++ b/include/asm-arm/arch-sa1100/h3600.h
@@ -16,7 +16,7 @@
*
* History:
*
- * 2001-10-?? Andrew Christian Added support for iPAQ H3800
+ * 2001-10-?? Andrew Christian Added support for iPAQ H3800
*
*/
@@ -26,6 +26,11 @@
/* generalized support for H3xxx series Compaq Pocket PC's */
#define machine_is_h3xxx() (machine_is_h3100() || machine_is_h3600() || machine_is_h3800())
+/* Physical memory regions corresponding to chip selects */
+#define H3600_EGPIO_PHYS (SA1100_CS5_PHYS + 0x01000000)
+#define H3600_BANK_2_PHYS SA1100_CS2_PHYS
+#define H3600_BANK_4_PHYS SA1100_CS4_PHYS
+
/* Virtual memory regions corresponding to chip selects 2 & 4 (used on sleeves) */
#define H3600_EGPIO_VIRT 0xf0000000
#define H3600_BANK_2_VIRT 0xf1000000
@@ -36,8 +41,7 @@
--- these are common across all current iPAQ platforms
*/
-#define GPIO_H3600_NPOWER_BUTTON GPIO_GPIO (0) /* Also known as the "off button" */
-#define GPIO_H3600_MICROCONTROLLER GPIO_GPIO (1) /* From ASIC2 on H3800 */
+#define GPIO_H3600_NPOWER_BUTTON GPIO_GPIO (0) /* Also known as the "off button" */
#define GPIO_H3600_PCMCIA_CD1 GPIO_GPIO (10)
#define GPIO_H3600_PCMCIA_IRQ1 GPIO_GPIO (11)
@@ -56,83 +60,105 @@
#define GPIO_H3600_COM_CTS GPIO_GPIO (25)
#define GPIO_H3600_COM_RTS GPIO_GPIO (26)
-#define IRQ_GPIO_H3600_NPOWER_BUTTON IRQ_GPIO0
-#define IRQ_GPIO_H3600_MICROCONTROLLER IRQ_GPIO1
+#define IRQ_GPIO_H3600_NPOWER_BUTTON IRQ_GPIO0
#define IRQ_GPIO_H3600_PCMCIA_CD1 IRQ_GPIO10
#define IRQ_GPIO_H3600_PCMCIA_IRQ1 IRQ_GPIO11
#define IRQ_GPIO_H3600_PCMCIA_CD0 IRQ_GPIO17
#define IRQ_GPIO_H3600_PCMCIA_IRQ0 IRQ_GPIO21
-#define IRQ_GPIO_H3600_COM_DCD IRQ_GPIO23
+#define IRQ_GPIO_H3600_COM_DCD IRQ_GPIO23
#define IRQ_GPIO_H3600_OPT_IRQ IRQ_GPIO24
-#define IRQ_GPIO_H3600_COM_CTS IRQ_GPIO25
+#define IRQ_GPIO_H3600_COM_CTS IRQ_GPIO25
#ifndef __ASSEMBLY__
-enum ipaq_model {
- IPAQ_H3100,
- IPAQ_H3600,
- IPAQ_H3800
-};
enum ipaq_egpio_type {
- IPAQ_EGPIO_LCD_ON, /* Power to the LCD panel */
+ IPAQ_EGPIO_LCD_POWER, /* Power to the LCD panel */
IPAQ_EGPIO_CODEC_NRESET, /* Clear to reset the audio codec (remember to return high) */
- IPAQ_EGPIO_AUDIO_ON, /* Audio power */
- IPAQ_EGPIO_QMUTE, /* Audio muting */
+ IPAQ_EGPIO_AUDIO_ON, /* Audio power */
+ IPAQ_EGPIO_QMUTE, /* Audio muting */
IPAQ_EGPIO_OPT_NVRAM_ON, /* Non-volatile RAM on extension sleeves (SPI interface) */
- IPAQ_EGPIO_OPT_ON, /* Power to extension sleeves */
- IPAQ_EGPIO_CARD_RESET, /* Reset PCMCIA cards on extension sleeve (???) */
- IPAQ_EGPIO_OPT_RESET, /* Reset option pack (???) */
- IPAQ_EGPIO_IR_ON, /* IR sensor/emitter power */
- IPAQ_EGPIO_IR_FSEL, /* IR speed selection 1->fast, 0->slow */
- IPAQ_EGPIO_RS232_ON, /* Maxim RS232 chip power */
- IPAQ_EGPIO_VPP_ON, /* Turn on power to flash programming */
+ IPAQ_EGPIO_OPT_ON, /* Power to extension sleeves */
+ IPAQ_EGPIO_CARD_RESET, /* Reset PCMCIA cards on extension sleeve (???) */
+ IPAQ_EGPIO_OPT_RESET, /* Reset option pack (???) */
+ IPAQ_EGPIO_IR_ON, /* IR sensor/emitter power */
+ IPAQ_EGPIO_IR_FSEL, /* IR speed selection 1->fast, 0->slow */
+ IPAQ_EGPIO_RS232_ON, /* Maxim RS232 chip power */
+ IPAQ_EGPIO_VPP_ON, /* Turn on power to flash programming */
+ IPAQ_EGPIO_LCD_ENABLE, /* Enable/disable LCD controller */
};
struct ipaq_model_ops {
- enum ipaq_model model;
const char *generic_name;
- void (*initialize)(void);
- void (*control)(enum ipaq_egpio_type, int);
+ void (*control)(enum ipaq_egpio_type, int);
unsigned long (*read)(void);
+ void (*blank_callback)(int blank);
+ int (*pm_callback)(int req); /* Primary model callback */
+ int (*pm_callback_aux)(int req); /* Secondary callback (used by HAL modules) */
};
extern struct ipaq_model_ops ipaq_model_ops;
-static __inline__ enum ipaq_model h3600_model( void ) {
- return ipaq_model_ops.model;
-}
-
-static __inline__ const char * h3600_generic_name( void ) {
+static __inline__ const char * h3600_generic_name(void)
+{
return ipaq_model_ops.generic_name;
}
-static __inline__ void init_h3600_egpio( void ) {
- if (ipaq_model_ops.initialize)
- ipaq_model_ops.initialize();
-}
-
-static __inline__ void assign_h3600_egpio( enum ipaq_egpio_type x, int level ) {
+static __inline__ void assign_h3600_egpio(enum ipaq_egpio_type x, int level)
+{
if (ipaq_model_ops.control)
ipaq_model_ops.control(x,level);
}
-static __inline__ void clr_h3600_egpio( enum ipaq_egpio_type x ) {
+static __inline__ void clr_h3600_egpio(enum ipaq_egpio_type x)
+{
if (ipaq_model_ops.control)
ipaq_model_ops.control(x,0);
}
-static __inline__ void set_h3600_egpio( enum ipaq_egpio_type x ) {
+static __inline__ void set_h3600_egpio(enum ipaq_egpio_type x)
+{
if (ipaq_model_ops.control)
ipaq_model_ops.control(x,1);
}
-static __inline__ unsigned long read_h3600_egpio( void ) {
+static __inline__ unsigned long read_h3600_egpio(void)
+{
if (ipaq_model_ops.read)
return ipaq_model_ops.read();
return 0;
}
+static __inline__ int h3600_register_blank_callback(void (*f)(int))
+{
+ ipaq_model_ops.blank_callback = f;
+ return 0;
+}
+
+static __inline__ void h3600_unregister_blank_callback(void (*f)(int))
+{
+ ipaq_model_ops.blank_callback = NULL;
+}
+
+
+static __inline__ int h3600_register_pm_callback(int (*f)(int))
+{
+ ipaq_model_ops.pm_callback_aux = f;
+ return 0;
+}
+
+static __inline__ void h3600_unregister_pm_callback(int (*f)(int))
+{
+ ipaq_model_ops.pm_callback_aux = NULL;
+}
+
+static __inline__ int h3600_power_management(int req)
+{
+ if (ipaq_model_ops.pm_callback)
+ return ipaq_model_ops.pm_callback(req);
+ return 0;
+}
+
#endif /* ASSEMBLY */
#endif /* _INCLUDE_H3600_H_ */
diff --git a/include/asm-arm/arch-sa1100/irqs.h b/include/asm-arm/arch-sa1100/irqs.h
index cc5dcda895c6..66e4f596c739 100644
--- a/include/asm-arm/arch-sa1100/irqs.h
+++ b/include/asm-arm/arch-sa1100/irqs.h
@@ -108,18 +108,18 @@
#define AUDDTS (IRQ_BOARD_END + 40)
#define AUDRDD (IRQ_BOARD_END + 41)
#define AUDSTO (IRQ_BOARD_END + 42)
-#define USBPWR (IRQ_BOARD_END + 43)
-#define NIRQHCIM (IRQ_BOARD_END + 44)
-#define IRQHCIBUFFACC (IRQ_BOARD_END + 45)
-#define IRQHCIRMTWKP (IRQ_BOARD_END + 46)
-#define NHCIMFCIR (IRQ_BOARD_END + 47)
-#define USB_PORT_RESUME (IRQ_BOARD_END + 48)
-#define S0_READY_NINT (IRQ_BOARD_END + 49)
-#define S1_READY_NINT (IRQ_BOARD_END + 50)
-#define S0_CD_VALID (IRQ_BOARD_END + 51)
-#define S1_CD_VALID (IRQ_BOARD_END + 52)
-#define S0_BVD1_STSCHG (IRQ_BOARD_END + 53)
-#define S1_BVD1_STSCHG (IRQ_BOARD_END + 54)
+#define IRQ_USBPWR (IRQ_BOARD_END + 43)
+#define IRQ_NHCIM (IRQ_BOARD_END + 44)
+#define IRQ_HCIBUFFACC (IRQ_BOARD_END + 45)
+#define IRQ_HCIRMTWKP (IRQ_BOARD_END + 46)
+#define IRQ_NHCIMFCIR (IRQ_BOARD_END + 47)
+#define IRQ_USB_PORT_RESUME (IRQ_BOARD_END + 48)
+#define IRQ_S0_READY_NINT (IRQ_BOARD_END + 49)
+#define IRQ_S1_READY_NINT (IRQ_BOARD_END + 50)
+#define IRQ_S0_CD_VALID (IRQ_BOARD_END + 51)
+#define IRQ_S1_CD_VALID (IRQ_BOARD_END + 52)
+#define IRQ_S0_BVD1_STSCHG (IRQ_BOARD_END + 53)
+#define IRQ_S1_BVD1_STSCHG (IRQ_BOARD_END + 54)
/*
* Figure out the MAX IRQ number.
@@ -129,7 +129,7 @@
* Otherwise, we have the standard IRQs only.
*/
#ifdef CONFIG_SA1111
-#define NR_IRQS (S1_BVD1_STSCHG + 1)
+#define NR_IRQS (IRQ_S1_BVD1_STSCHG + 1)
#elif defined(CONFIG_SA1100_GRAPHICSCLIENT) || \
defined(CONFIG_SA1100_GRAPHICSMASTER) || \
defined(CONFIG_SA1100_H3800)
diff --git a/include/asm-arm/hardware/sa1111.h b/include/asm-arm/hardware/sa1111.h
index c334e869f8ef..311e4832eb2f 100644
--- a/include/asm-arm/hardware/sa1111.h
+++ b/include/asm-arm/hardware/sa1111.h
@@ -64,18 +64,10 @@
#define SA1111_SMCR 0x0004
#define SA1111_SKID 0x0008
-#define _SBI_SKCR _SA1111(SA1111_SKCR)
-#define _SBI_SMCR _SA1111(SA1111_SMCR)
-#define _SBI_SKID _SA1111(SA1111_SKID)
-
-#if LANGUAGE == C
-
#define SBI_SKCR __CCREG(SA1111_SKCR)
#define SBI_SMCR __CCREG(SA1111_SMCR)
#define SBI_SKID __CCREG(SA1111_SKID)
-#endif /* LANGUAGE == C */
-
#define SKCR_PLL_BYPASS (1<<0)
#define SKCR_RCLKEN (1<<1)
#define SKCR_SLEEP (1<<2)
@@ -135,22 +127,10 @@
#define SA1111_SKPMC 0x020c
#define SA1111_SKPTC 0x0210
#define SA1111_SKPEN0 0x0214
-#define SA1111_SKPWN0 0x0218
+#define SA1111_SKPWM0 0x0218
#define SA1111_SKPEN1 0x021c
#define SA1111_SKPWM1 0x0220
-#define _SKPCR _SA1111(SA1111_SKPCR)
-#define _SKCDR _SA1111(SA1111_SKCDR)
-#define _SKAUD _SA1111(SA1111_SKAUD)
-#define _SKPMC _SA1111(SA1111_SKPMC)
-#define _SKPTC _SA1111(SA1111_SKPTC)
-#define _SKPEN0 _SA1111(SA1111_SKPEN0)
-#define _SKPWM0 _SA1111(SA1111_SKPWM0)
-#define _SKPEN1 _SA1111(SA1111_SKPEN1)
-#define _SKPWM1 _SA1111(SA1111_SKPWM1)
-
-#if LANGUAGE == C
-
#define SKPCR __CCREG(SA1111_SKPCR)
#define SKCDR __CCREG(SA1111_SKCDR)
#define SKAUD __CCREG(SA1111_SKAUD)
@@ -161,8 +141,6 @@
#define SKPEN1 __CCREG(SA1111_SKPEN1)
#define SKPWM1 __CCREG(SA1111_SKPWM1)
-#endif /* LANGUAGE == C */
-
#define SKPCR_UCLKEN (1<<0)
#define SKPCR_ACCLKEN (1<<1)
#define SKPCR_I2SCLKEN (1<<2)
@@ -176,21 +154,14 @@
/*
* USB Host controller
*/
-#define _USB_OHCI_OP_BASE _SA1111( 0x400 )
-#define _USB_STATUS _SA1111( 0x518 )
-#define _USB_RESET _SA1111( 0x51c )
-#define _USB_INTERRUPTEST _SA1111( 0x520 )
-
-#define _USB_EXTENT (_USB_INTERRUPTEST - _USB_OHCI_OP_BASE + 4)
-
-#if LANGUAGE == C
-
-#define USB_OHCI_OP_BASE __CCREG(0x0400)
-#define USB_STATUS __CCREG(0x0518)
-#define USB_RESET __CCREG(0x051c)
-#define USB_INTERRUPTEST __CCReG(0x0520)
+#define SA1111_USB 0x0400
-#endif /* LANGUAGE == C */
+/*
+ * Offsets from SA1111_USB_BASE
+ */
+#define SA1111_USB_STATUS 0x0118
+#define SA1111_USB_RESET 0x011c
+#define SA1111_USB_IRQTEST 0x0120
#define USB_RESET_FORCEIFRESET (1 << 0)
#define USB_RESET_FORCEHCRESET (1 << 1)
@@ -451,82 +422,56 @@
* WAKE_POL0 Wake-up polarity selection 0
* WAKE_POL1 Wake-up polarity selection 1
*/
+#define SA1111_INTC 0x1600
-#define SA1111_INTTEST0 0x1600
-#define SA1111_INTTEST1 0x1604
-#define SA1111_INTEN0 0x1608
-#define SA1111_INTEN1 0x160c
-#define SA1111_INTPOL0 0x1610
-#define SA1111_INTPOL1 0x1614
-#define SA1111_INTTSTSEL 0x1618
-#define SA1111_INTSTATCLR0 0x161c
-#define SA1111_INTSTATCLR1 0x1620
-#define SA1111_INTSET0 0x1624
-#define SA1111_INTSET1 0x1628
-#define SA1111_WAKE_EN0 0x162c
-#define SA1111_WAKE_EN1 0x1630
-#define SA1111_WAKE_POL0 0x1634
-#define SA1111_WAKE_POL1 0x1638
-
-#define _INTTEST0 _SA1111(SA1111_INTTEST0)
-#define _INTTEST1 _SA1111(SA1111_INTTEST1)
-#define _INTEN0 _SA1111(SA1111_INTEN0)
-#define _INTEN1 _SA1111(SA1111_INTEN1)
-#define _INTPOL0 _SA1111(SA1111_INTPOL0)
-#define _INTPOL1 _SA1111(SA1111_INTPOL1)
-#define _INTTSTSEL _SA1111(SA1111_INTTSTSEL)
-#define _INTSTATCLR0 _SA1111(SA1111_INTSTATCLR0)
-#define _INTSTATCLR1 _SA1111(SA1111_INTSTATCLR1)
-#define _INTSET0 _SA1111(SA1111_INTSET0)
-#define _INTSET1 _SA1111(SA1111_INTSET1)
-#define _WAKE_EN0 _SA1111(SA1111_WAKE_EN0)
-#define _WAKE_EN1 _SA1111(SA1111_WAKE_EN1)
-#define _WAKE_POL0 _SA1111(SA1111_WAKE_POL0)
-#define _WAKE_POL1 _SA1111(SA1111_WAKE_POL1)
-
-#if LANGUAGE == C
-
-#define INTTEST0 __CCREG(SA1111_INTTEST0)
-#define INTTEST1 __CCREG(SA1111_INTTEST1)
-#define INTEN0 __CCREG(SA1111_INTEN0)
-#define INTEN1 __CCREG(SA1111_INTEN1)
-#define INTPOL0 __CCREG(SA1111_INTPOL0)
-#define INTPOL1 __CCREG(SA1111_INTPOL1)
-#define INTTSTSEL __CCREG(SA1111_INTTSTSEL)
-#define INTSTATCLR0 __CCREG(SA1111_INTSTATCLR0)
-#define INTSTATCLR1 __CCREG(SA1111_INTSTATCLR1)
-#define INTSET0 __CCREG(SA1111_INTSET0)
-#define INTSET1 __CCREG(SA1111_INTSET1)
-#define WAKE_EN0 __CCREG(SA1111_WAKE_EN0)
-#define WAKE_EN1 __CCREG(SA1111_WAKE_EN1)
-#define WAKE_POL0 __CCREG(SA1111_WAKE_POL0)
-#define WAKE_POL1 __CCREG(SA1111_WAKE_POL1)
-
-#endif /* LANGUAGE == C */
+/*
+ * These are offsets from the above base.
+ */
+#define SA1111_INTTEST0 0x0000
+#define SA1111_INTTEST1 0x0004
+#define SA1111_INTEN0 0x0008
+#define SA1111_INTEN1 0x000c
+#define SA1111_INTPOL0 0x0010
+#define SA1111_INTPOL1 0x0014
+#define SA1111_INTTSTSEL 0x0018
+#define SA1111_INTSTATCLR0 0x001c
+#define SA1111_INTSTATCLR1 0x0020
+#define SA1111_INTSET0 0x0024
+#define SA1111_INTSET1 0x0028
+#define SA1111_WAKEEN0 0x002c
+#define SA1111_WAKEEN1 0x0030
+#define SA1111_WAKEPOL0 0x0034
+#define SA1111_WAKEPOL1 0x0038
+
+#define INTTEST0 __CCREG(SA1111_INTC + SA1111_INTTEST0)
+#define INTTEST1 __CCREG(SA1111_INTC + SA1111_INTTEST1)
+#define INTEN0 __CCREG(SA1111_INTC + SA1111_INTEN0)
+#define INTEN1 __CCREG(SA1111_INTC + SA1111_INTEN1)
+#define INTPOL0 __CCREG(SA1111_INTC + SA1111_INTPOL0)
+#define INTPOL1 __CCREG(SA1111_INTC + SA1111_INTPOL1)
+#define INTTSTSEL __CCREG(SA1111_INTC + SA1111_INTTSTSEL)
+#define INTSTATCLR0 __CCREG(SA1111_INTC + SA1111_INTSTATCLR0)
+#define INTSTATCLR1 __CCREG(SA1111_INTC + SA1111_INTSTATCLR1)
+#define INTSET0 __CCREG(SA1111_INTC + SA1111_INTSET0)
+#define INTSET1 __CCREG(SA1111_INTC + SA1111_INTSET1)
+#define WAKE_EN0 __CCREG(SA1111_INTC + SA1111_WAKEEN0)
+#define WAKE_EN1 __CCREG(SA1111_INTC + SA1111_WAKEEN1)
+#define WAKE_POL0 __CCREG(SA1111_INTC + SA1111_WAKEPOL0)
+#define WAKE_POL1 __CCREG(SA1111_INTC + SA1111_WAKEPOL1)
/*
* PS/2 Trackpad and Mouse Interfaces
*
- * Registers (prefix kbd applies to trackpad interface, mse to mouse)
- * KBDCR Control Register
- * KBDSTAT Status Register
- * KBDDATA Transmit/Receive Data register
- * KBDCLKDIV Clock Division Register
- * KBDPRECNT Clock Precount Register
- * KBDTEST1 Test register 1
- * KBDTEST2 Test register 2
- * KBDTEST3 Test register 3
- * KBDTEST4 Test register 4
- * MSECR
- * MSESTAT
- * MSEDATA
- * MSECLKDIV
- * MSEPRECNT
- * MSETEST1
- * MSETEST2
- * MSETEST3
- * MSETEST4
- *
+ * Registers
+ * PS2CR Control Register
+ * PS2STAT Status Register
+ * PS2DATA Transmit/Receive Data register
+ * PS2CLKDIV Clock Division Register
+ * PS2PRECNT Clock Precount Register
+ * PS2TEST1 Test register 1
+ * PS2TEST2 Test register 2
+ * PS2TEST3 Test register 3
+ * PS2TEST4 Test register 4
*/
#define SA1111_KBD 0x0a00
@@ -564,17 +509,14 @@
* PCSSR Sleep State Register
*/
-#define _PCCR _SA1111( 0x1800 )
-#define _PCSSR _SA1111( 0x1804 )
-#define _PCSR _SA1111( 0x1808 )
-
-#if LANGUAGE == C
-
-#define PCCR __CCREG(0x1800)
-#define PCSSR __CCREG(0x1804)
-#define PCSR __CCREG(0x1808)
+#define SA1111_PCMCIA 0x1600
-#endif /* LANGUAGE == C */
+/*
+ * These are offsets from the above base.
+ */
+#define SA1111_PCCR 0x0000
+#define SA1111_PCSSR 0x0004
+#define SA1111_PCSR 0x0008
#define PCSR_S0_READY (1<<0)
#define PCSR_S1_READY (1<<1)
@@ -603,21 +545,61 @@
#define PCSSR_S0_SLEEP (1<<0)
#define PCSSR_S1_SLEEP (1<<1)
-struct sa1111_device {
+
+
+
+extern struct bus_type sa1111_bus_type;
+
+#define SA1111_DEVID_SBI 0
+#define SA1111_DEVID_SK 1
+#define SA1111_DEVID_USB 2
+#define SA1111_DEVID_SAC 3
+#define SA1111_DEVID_SSP 4
+#define SA1111_DEVID_PS2 5
+#define SA1111_DEVID_GPIO 6
+#define SA1111_DEVID_INT 7
+#define SA1111_DEVID_PCMCIA 8
+
+struct sa1111_dev {
struct device dev;
- struct resource resource;
- void *base;
+ unsigned int devid;
+ struct resource res;
+ void *mapbase;
+ unsigned int skpcr_mask;
+ unsigned int irq[6];
};
-extern struct sa1111_device *sa1111;
+#define SA1111_DEV(_d) container_of((_d), struct sa1111_dev, dev)
-int sa1111_check_dma_bug(dma_addr_t addr);
+struct sa1111_driver {
+ struct device_driver drv;
+ unsigned int devid;
+};
+
+#define SA1111_DRV(_d) container_of((_d), struct sa1111_driver, drv)
+
+#define SA1111_DRIVER_NAME(_sadev) ((_sadev)->dev.driver->name)
+
+/*
+ * Probe for a SA1111 chip.
+ */
+extern int sa1111_init(unsigned long phys, unsigned int irq);
/*
* These frob the SKPCR register.
*/
-void sa1111_enable_device(unsigned int mask);
-void sa1111_disable_device(unsigned int mask);
+void sa1111_enable_device(struct sa1111_dev *);
+void sa1111_disable_device(struct sa1111_dev *);
+
+unsigned int sa1111_pll_clock(struct sa1111_dev *);
+#define SA1111_AUDIO_ACLINK 0
+#define SA1111_AUDIO_I2S 1
+
+void sa1111_select_audio_mode(struct sa1111_dev *sadev, int mode);
+int sa1111_set_audio_rate(struct sa1111_dev *sadev, int rate);
+int sa1111_get_audio_rate(struct sa1111_dev *sadev);
+
+int sa1111_check_dma_bug(dma_addr_t addr);
#endif /* _ASM_ARCH_SA1111 */
diff --git a/include/asm-arm/pci.h b/include/asm-arm/pci.h
index 70fcb5c4d021..3a7310558dd2 100644
--- a/include/asm-arm/pci.h
+++ b/include/asm-arm/pci.h
@@ -27,15 +27,11 @@ void sa1111_dma_sync_sg(struct pci_dev *, struct scatterlist *, int, int);
#ifdef CONFIG_SA1111
#define SA1111_FAKE_PCIDEV ((struct pci_dev *) 1111)
-
-static inline int dev_is_sa1111(const struct pci_dev *dev)
-{
- return (dev == SA1111_FAKE_PCIDEV);
-}
+#define dev_is_sa1111(dev) (dev == SA1111_FAKE_PCIDEV)
#else
-static inline int dev_is_sa1111(const struct pci_dev *dev) { return 0; }
+#define dev_is_sa1111(dev) (0)
#endif
diff --git a/include/linux/auto_fs.h b/include/linux/auto_fs.h
index 39b120cd2e12..13bc53bc06f5 100644
--- a/include/linux/auto_fs.h
+++ b/include/linux/auto_fs.h
@@ -45,7 +45,7 @@
* If so, 32-bit user-space code should be backwards compatible.
*/
-#if defined(__sparc__) || defined(__mips__) || defined(__x86_64) \
+#if defined(__sparc__) || defined(__mips__) || defined(__x86_64__) \
|| defined(__powerpc__) || defined(__s390__)
typedef unsigned int autofs_wqt_t;
#else
diff --git a/include/linux/module.h b/include/linux/module.h
index c71778e38536..4dc669b060fb 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -253,6 +253,7 @@ static const struct gtype##_id * __module_##gtype##_table \
* software modules
*
* "GPL" [GNU Public License v2 or later]
+ * "GPL v2" [GNU Public License v2]
* "GPL and additional rights" [GNU Public License v2 rights and more]
* "Dual BSD/GPL" [GNU Public License v2 or BSD license choice]
* "Dual MPL/GPL" [GNU Public License v2 or Mozilla license choice]
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 5d323aa0d36e..5dbc3cb115f7 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -84,6 +84,7 @@
#include <linux/list.h> /* for struct list_head */
#include <linux/device.h> /* for struct device */
#include <linux/fs.h> /* for struct file_operations */
+#include <linux/completion.h> /* for struct completion */
static __inline__ void wait_ms(unsigned int ms)
@@ -452,9 +453,9 @@ static inline int usb_make_path (struct usb_device *dev, char *buf, size_t size)
* User mode code can read these tables to choose which modules to load.
* Declare the table as a MODULE_DEVICE_TABLE.
*
- * The third probe() parameter will point to a matching entry from this
- * table. (Null value reserved.) Use the driver_data field for each
- * match to hold information tied to that match: device quirks, etc.
+ * A probe() parameter will point to a matching entry from this table.
+ * Use the driver_info field for each match to hold information tied
+ * to that match: device quirks, etc.
*
* Terminate the driver's table with an all-zeroes entry.
* Use the flag values to control which fields are compared.
@@ -604,17 +605,14 @@ struct usb_device_id {
* @name: The driver name should be unique among USB drivers,
* and should normally be the same as the module name.
* @probe: Called to see if the driver is willing to manage a particular
- * interface on a device. The probe routine returns a handle that
- * will later be provided to disconnect(), or a null pointer to
- * indicate that the driver will not handle the interface.
- * The handle is normally a pointer to driver-specific data.
- * If the probe() routine needs to access the interface
- * structure itself, use usb_ifnum_to_if() to make sure it's using
- * the right one.
+ * interface on a device. If it is, probe returns zero and uses
+ * dev_set_drvdata() to associate driver-specific data with the
+ * interface. It may also use usb_set_interface() to specify the
+ * appropriate altsetting. If unwilling to manage the interface,
+ * return a negative errno value.
* @disconnect: Called when the interface is no longer accessible, usually
- * because its device has been (or is being) disconnected. The
- * handle passed is what was returned by probe(), or was provided
- * to usb_driver_claim_interface().
+ * because its device has been (or is being) disconnected or the
+ * driver module is being unloaded.
* @ioctl: Used for drivers that want to talk to userspace through
* the "usbfs" filesystem. This lets devices provide ways to
* expose information to user space regardless of where they
@@ -648,7 +646,7 @@ struct usb_driver {
void (*disconnect) (struct usb_interface *intf);
- int (*ioctl) (struct usb_device *dev, unsigned int code, void *buf);
+ int (*ioctl) (struct usb_interface *intf, unsigned int code, void *buf);
const struct usb_device_id *id_table;
@@ -1074,6 +1072,57 @@ extern int usb_set_interface(struct usb_device *dev, int ifnum, int alternate);
#define USB_CTRL_SET_TIMEOUT 3
+
+/**
+ * struct usb_sg_request - support for scatter/gather I/O
+ * @status: zero indicates success, else negative errno
+ * @bytes: counts bytes transferred.
+ *
+ * These requests are initialized using usb_sg_init(), and then are used
+ * as request handles passed to usb_sg_wait() or usb_sg_cancel(). Most
+ * members of the request object aren't for driver access.
+ *
+ * The status and bytecount values are valid only after usb_sg_wait()
+ * returns. If the status is zero, then the bytecount matches the total
+ * from the request.
+ *
+ * After an error completion, drivers may need to clear a halt condition
+ * on the endpoint.
+ */
+struct usb_sg_request {
+ int status;
+ size_t bytes;
+
+ // members not documented above are private to usbcore,
+ // and are not provided for driver access!
+ spinlock_t lock;
+
+ struct usb_device *dev;
+ int pipe;
+ struct scatterlist *sg;
+ int nents;
+
+ int entries;
+ struct urb **urbs;
+
+ int count;
+ struct completion complete;
+};
+
+int usb_sg_init (
+ struct usb_sg_request *io,
+ struct usb_device *dev,
+ unsigned pipe,
+ unsigned period,
+ struct scatterlist *sg,
+ int nents,
+ size_t length,
+ int mem_flags
+);
+void usb_sg_cancel (struct usb_sg_request *io);
+void usb_sg_wait (struct usb_sg_request *io);
+
+
/* -------------------------------------------------------------------------- */
/*
diff --git a/include/linux/usbdevice_fs.h b/include/linux/usbdevice_fs.h
index de18e956f47b..84653713900c 100644
--- a/include/linux/usbdevice_fs.h
+++ b/include/linux/usbdevice_fs.h
@@ -108,7 +108,7 @@ struct usbdevfs_urb {
struct usbdevfs_iso_packet_desc iso_frame_desc[0];
};
-/* ioctls for talking to drivers in the usbcore module: */
+/* ioctls for talking directly to drivers */
struct usbdevfs_ioctl {
int ifno; /* interface 0..N ; negative numbers reserved */
int ioctl_code; /* MUST encode size + direction of data so the