Merge branch 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/linux-arm-soc
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 30 Jul 2011 06:31:22 +0000 (23:31 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 30 Jul 2011 06:31:22 +0000 (23:31 -0700)
* 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/linux-arm-soc:
  ARM: zynq: remove incorrectly deleted file
  ARM: tegra: only select MACH_HAS_SND_SOC_TEGRA_WM8903 if SND_SOC

339 files changed:
Documentation/devicetree/bindings/gpio/gpio_keys.txt [new file with mode: 0644]
Documentation/devicetree/bindings/watchdog/fsl-imx-wdt.txt [new file with mode: 0644]
Documentation/devicetree/bindings/watchdog/samsung-wdt.txt [new file with mode: 0644]
Documentation/md.txt
Documentation/security/keys-ecryptfs.txt [new file with mode: 0644]
Documentation/security/keys-trusted-encrypted.txt
Documentation/watchdog/00-INDEX
Documentation/watchdog/watchdog-kernel-api.txt [new file with mode: 0644]
MAINTAINERS
arch/microblaze/include/asm/cpuinfo.h
arch/microblaze/include/asm/irqflags.h
arch/microblaze/include/asm/processor.h
arch/microblaze/include/asm/prom.h
arch/microblaze/include/asm/pvr.h
arch/microblaze/include/asm/setup.h
arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c
arch/microblaze/kernel/cpu/cpuinfo-static.c
arch/microblaze/kernel/cpu/cpuinfo.c
arch/microblaze/kernel/cpu/mb.c
arch/microblaze/kernel/early_printk.c
arch/microblaze/kernel/hw_exception_handler.S
arch/microblaze/kernel/intc.c
arch/microblaze/kernel/process.c
arch/microblaze/kernel/prom.c
arch/microblaze/kernel/setup.c
arch/sparc/include/asm/elf_64.h
arch/sparc/include/asm/hypervisor.h
arch/sparc/include/asm/spitfire.h
arch/sparc/include/asm/xor_64.h
arch/sparc/kernel/cpu.c
arch/sparc/kernel/cpumap.c
arch/sparc/kernel/head_64.S
arch/sparc/kernel/hvapi.c
arch/sparc/kernel/pcr.c
arch/sparc/kernel/perf_event.c
arch/sparc/lib/atomic32.c
drivers/char/hw_random/n2-drv.c
drivers/char/hw_random/n2rng.h
drivers/char/tpm/tpm.c
drivers/char/tpm/tpm.h
drivers/char/tpm/tpm_nsc.c
drivers/char/tpm/tpm_tis.c
drivers/crypto/n2_core.c
drivers/infiniband/ulp/iser/iser_initiator.c
drivers/input/joystick/xpad.c
drivers/input/keyboard/adp5588-keys.c
drivers/input/keyboard/adp5589-keys.c
drivers/input/keyboard/atkbd.c
drivers/input/keyboard/gpio_keys.c
drivers/input/keyboard/lm8323.c
drivers/input/keyboard/mpr121_touchkey.c
drivers/input/keyboard/pmic8xxx-keypad.c
drivers/input/keyboard/qt1070.c
drivers/input/keyboard/sh_keysc.c
drivers/input/keyboard/tegra-kbc.c
drivers/input/keyboard/tnetv107x-keypad.c
drivers/input/misc/Kconfig
drivers/input/misc/Makefile
drivers/input/misc/bfin_rotary.c
drivers/input/misc/kxtj9.c [new file with mode: 0644]
drivers/input/misc/mma8450.c [new file with mode: 0644]
drivers/input/misc/mpu3050.c [new file with mode: 0644]
drivers/input/misc/xen-kbdfront.c
drivers/input/mouse/gpio_mouse.c
drivers/input/mouse/lifebook.c
drivers/input/mouse/pxa930_trkball.c
drivers/input/mouse/sentelic.c
drivers/input/mouse/synaptics.c
drivers/input/mouse/synaptics.h
drivers/input/serio/at32psif.c
drivers/input/serio/hp_sdc.c
drivers/input/tablet/aiptek.c
drivers/input/tablet/wacom_wac.c
drivers/input/touchscreen/ads7846.c
drivers/input/touchscreen/atmel-wm97xx.c
drivers/input/touchscreen/atmel_mxt_ts.c
drivers/input/touchscreen/cy8ctmg110_ts.c
drivers/input/touchscreen/intel-mid-touch.c
drivers/input/touchscreen/mainstone-wm97xx.c
drivers/input/touchscreen/tnetv107x-ts.c
drivers/input/touchscreen/wm9705.c
drivers/input/touchscreen/wm9712.c
drivers/input/touchscreen/wm9713.c
drivers/input/touchscreen/zylonite-wm97xx.c
drivers/isdn/i4l/isdn_net.c
drivers/md/bitmap.c
drivers/md/bitmap.h
drivers/md/md.c
drivers/md/md.h
drivers/md/raid1.c
drivers/md/raid1.h
drivers/md/raid10.c
drivers/md/raid10.h
drivers/md/raid5.c
drivers/md/raid5.h
drivers/net/Makefile
drivers/net/acenic.c
drivers/net/acenic.h
drivers/net/bonding/bond_main.c
drivers/net/bonding/bond_sysfs.c
drivers/net/forcedeth.c
drivers/net/gianfar.c
drivers/net/ifb.c
drivers/net/macvlan.c
drivers/net/tg3.c
drivers/net/tg3.h
drivers/net/tun.c
drivers/net/usb/asix.c
drivers/net/veth.c
drivers/net/wan/hdlc_fr.c
drivers/net/wireless/airo.c
drivers/net/wireless/b43/Kconfig
drivers/net/wireless/b43/bus.c
drivers/net/wireless/b43/main.c
drivers/net/wireless/hostap/hostap_main.c
drivers/nfc/pn533.c
drivers/scsi/be2iscsi/be_main.h
drivers/scsi/bnx2i/bnx2i_hwi.c
drivers/scsi/bnx2i/bnx2i_iscsi.c
drivers/scsi/libiscsi.c
drivers/staging/ath6kl/os/linux/ar6000_drv.c
drivers/staging/brcm80211/brcmsmac/mac80211_if.h
drivers/target/Kconfig
drivers/target/Makefile
drivers/target/iscsi/Kconfig [new file with mode: 0644]
drivers/target/iscsi/Makefile [new file with mode: 0644]
drivers/target/iscsi/iscsi_target.c [new file with mode: 0644]
drivers/target/iscsi/iscsi_target.h [new file with mode: 0644]
drivers/target/iscsi/iscsi_target_auth.c [new file with mode: 0644]
drivers/target/iscsi/iscsi_target_auth.h [new file with mode: 0644]
drivers/target/iscsi/iscsi_target_configfs.c [new file with mode: 0644]
drivers/target/iscsi/iscsi_target_configfs.h [new file with mode: 0644]
drivers/target/iscsi/iscsi_target_core.h [new file with mode: 0644]
drivers/target/iscsi/iscsi_target_datain_values.c [new file with mode: 0644]
drivers/target/iscsi/iscsi_target_datain_values.h [new file with mode: 0644]
drivers/target/iscsi/iscsi_target_device.c [new file with mode: 0644]
drivers/target/iscsi/iscsi_target_device.h [new file with mode: 0644]
drivers/target/iscsi/iscsi_target_erl0.c [new file with mode: 0644]
drivers/target/iscsi/iscsi_target_erl0.h [new file with mode: 0644]
drivers/target/iscsi/iscsi_target_erl1.c [new file with mode: 0644]
drivers/target/iscsi/iscsi_target_erl1.h [new file with mode: 0644]
drivers/target/iscsi/iscsi_target_erl2.c [new file with mode: 0644]
drivers/target/iscsi/iscsi_target_erl2.h [new file with mode: 0644]
drivers/target/iscsi/iscsi_target_login.c [new file with mode: 0644]
drivers/target/iscsi/iscsi_target_login.h [new file with mode: 0644]
drivers/target/iscsi/iscsi_target_nego.c [new file with mode: 0644]
drivers/target/iscsi/iscsi_target_nego.h [new file with mode: 0644]
drivers/target/iscsi/iscsi_target_nodeattrib.c [new file with mode: 0644]
drivers/target/iscsi/iscsi_target_nodeattrib.h [new file with mode: 0644]
drivers/target/iscsi/iscsi_target_parameters.c [new file with mode: 0644]
drivers/target/iscsi/iscsi_target_parameters.h [new file with mode: 0644]
drivers/target/iscsi/iscsi_target_seq_pdu_list.c [new file with mode: 0644]
drivers/target/iscsi/iscsi_target_seq_pdu_list.h [new file with mode: 0644]
drivers/target/iscsi/iscsi_target_stat.c [new file with mode: 0644]
drivers/target/iscsi/iscsi_target_stat.h [new file with mode: 0644]
drivers/target/iscsi/iscsi_target_tmr.c [new file with mode: 0644]
drivers/target/iscsi/iscsi_target_tmr.h [new file with mode: 0644]
drivers/target/iscsi/iscsi_target_tpg.c [new file with mode: 0644]
drivers/target/iscsi/iscsi_target_tpg.h [new file with mode: 0644]
drivers/target/iscsi/iscsi_target_tq.c [new file with mode: 0644]
drivers/target/iscsi/iscsi_target_tq.h [new file with mode: 0644]
drivers/target/iscsi/iscsi_target_util.c [new file with mode: 0644]
drivers/target/iscsi/iscsi_target_util.h [new file with mode: 0644]
drivers/target/target_core_transport.c
drivers/watchdog/Kconfig
drivers/watchdog/Makefile
drivers/watchdog/at91sam9_wdt.c
drivers/watchdog/at91sam9_wdt.h [moved from arch/arm/mach-at91/include/mach/at91_wdt.h with 96% similarity]
drivers/watchdog/dw_wdt.c [new file with mode: 0644]
drivers/watchdog/hpwdt.c
drivers/watchdog/iTCO_wdt.c
drivers/watchdog/imx2_wdt.c
drivers/watchdog/it8712f_wdt.c
drivers/watchdog/it87_wdt.c
drivers/watchdog/mpcore_wdt.c
drivers/watchdog/mtx-1_wdt.c
drivers/watchdog/of_xilinx_wdt.c [new file with mode: 0644]
drivers/watchdog/pc87413_wdt.c
drivers/watchdog/s3c2410_wdt.c
drivers/watchdog/sch311x_wdt.c
drivers/watchdog/sp805_wdt.c
drivers/watchdog/watchdog_core.c [new file with mode: 0644]
drivers/watchdog/watchdog_dev.c [new file with mode: 0644]
drivers/watchdog/watchdog_dev.h [new file with mode: 0644]
fs/btrfs/btrfs_inode.h
fs/btrfs/ctree.c
fs/btrfs/ctree.h
fs/btrfs/delayed-inode.c
fs/btrfs/dir-item.c
fs/btrfs/disk-io.c
fs/btrfs/disk-io.h
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/extent_io.h
fs/btrfs/file-item.c
fs/btrfs/file.c
fs/btrfs/free-space-cache.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/locking.c
fs/btrfs/locking.h
fs/btrfs/relocation.c
fs/btrfs/struct-funcs.c
fs/btrfs/transaction.c
fs/btrfs/tree-log.c
fs/btrfs/volumes.c
fs/btrfs/xattr.c
fs/ecryptfs/ecryptfs_kernel.h
fs/ecryptfs/keystore.c
fs/ext2/acl.h
fs/gfs2/ops_fstype.c
fs/jfs/jfs_dmap.c
fs/jfs/jfs_txnmgr.c
fs/jfs/namei.c
fs/lockd/clntproc.c
fs/nfs/Kconfig
fs/nfs/callback_proc.c
fs/nfs/client.c
fs/nfs/delegation.c
fs/nfs/internal.h
fs/nfs/namespace.c
fs/nfs/nfs4_fs.h
fs/nfs/nfs4filelayout.c
fs/nfs/nfs4filelayout.h
fs/nfs/nfs4filelayoutdev.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c
fs/nfs/nfs4xdr.c
fs/nfs/objlayout/objio_osd.c
fs/nfs/pagelist.c
fs/nfs/pnfs.c
fs/nfs/pnfs.h
fs/nfs/pnfs_dev.c
fs/nfs/read.c
fs/nfs/unlink.c
fs/nfs/write.c
fs/proc/generic.c
fs/proc/proc_net.c
fs/proc/root.c
fs/xfs/linux-2.6/xfs_buf.c
fs/xfs/linux-2.6/xfs_file.c
fs/xfs/linux-2.6/xfs_iops.c
fs/xfs/xfs_da_btree.c
include/keys/encrypted-type.h
include/linux/ecryptfs.h [new file with mode: 0644]
include/linux/if.h
include/linux/input.h
include/linux/input/kxtj9.h [new file with mode: 0644]
include/linux/kernel.h
include/linux/netdevice.h
include/linux/nfs4.h
include/linux/nfs_fs_sb.h
include/linux/nfs_page.h
include/linux/nfs_xdr.h
include/linux/pnfs_osd_xdr.h
include/linux/proc_fs.h
include/linux/raid/md_p.h
include/linux/sunrpc/bc_xprt.h
include/linux/sunrpc/sched.h
include/linux/sunrpc/svc.h
include/linux/sunrpc/xprt.h
include/linux/watchdog.h
include/linux/wm97xx.h
include/scsi/iscsi_proto.h
include/sound/pcm.h
include/sound/pcm_params.h
include/sound/soc-dapm.h
kernel/cgroup.c
kernel/compat.c
kernel/signal.c
net/8021q/vlan_dev.c
net/bluetooth/bnep/netdev.c
net/core/dev.c
net/core/pktgen.c
net/ethernet/eth.c
net/ipv4/devinet.c
net/ipv6/addrconf.c
net/l2tp/l2tp_eth.c
net/mac80211/iface.c
net/socket.c
net/sunrpc/Kconfig
net/sunrpc/Makefile
net/sunrpc/backchannel_rqst.c
net/sunrpc/bc_svc.c
net/sunrpc/clnt.c
net/sunrpc/sched.c
net/sunrpc/svc.c
net/sunrpc/svcsock.c
net/sunrpc/xdr.c
net/sunrpc/xprt.c
net/sunrpc/xprtrdma/transport.c
net/sunrpc/xprtrdma/xprt_rdma.h
net/sunrpc/xprtsock.c
net/wireless/reg.c
security/apparmor/domain.c
security/apparmor/lsm.c
security/keys/Makefile
security/keys/ecryptfs_format.c [new file with mode: 0644]
security/keys/ecryptfs_format.h [new file with mode: 0644]
security/keys/encrypted.c
security/keys/request_key_auth.c
security/tomoyo/Kconfig
security/tomoyo/Makefile
security/tomoyo/audit.c [new file with mode: 0644]
security/tomoyo/common.c
security/tomoyo/common.h
security/tomoyo/condition.c [new file with mode: 0644]
security/tomoyo/domain.c
security/tomoyo/file.c
security/tomoyo/gc.c
security/tomoyo/group.c
security/tomoyo/load_policy.c
security/tomoyo/memory.c
security/tomoyo/mount.c
security/tomoyo/realpath.c
security/tomoyo/securityfs_if.c
security/tomoyo/tomoyo.c
security/tomoyo/util.c
sound/core/pcm_lib.c
sound/oss/ad1848.c
sound/oss/sb_mixer.c
sound/pci/asihpi/asihpi.c
sound/pci/asihpi/hpioctl.c
sound/pci/hda/Kconfig
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_codec.h
sound/pci/hda/hda_local.h
sound/pci/hda/patch_analog.c
sound/pci/hda/patch_cirrus.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/pci/hda/patch_via.c
sound/soc/codecs/sgtl5000.c
sound/soc/codecs/wm8962.c
sound/soc/davinci/davinci-vcif.c
sound/soc/samsung/i2s.c
sound/soc/soc-core.c
sound/soc/soc-dapm.c

diff --git a/Documentation/devicetree/bindings/gpio/gpio_keys.txt b/Documentation/devicetree/bindings/gpio/gpio_keys.txt
new file mode 100644 (file)
index 0000000..7190c99
--- /dev/null
@@ -0,0 +1,36 @@
+Device-Tree bindings for input/gpio_keys.c keyboard driver
+
+Required properties:
+       - compatible = "gpio-keys";
+
+Optional properties:
+       - autorepeat: Boolean, Enable auto repeat feature of Linux input
+         subsystem.
+
+Each button (key) is represented as a sub-node of "gpio-keys":
+Subnode properties:
+
+       - gpios: OF devcie-tree gpio specificatin.
+       - label: Descriptive name of the key.
+       - linux,code: Keycode to emit.
+
+Optional subnode-properties:
+       - linux,input-type: Specify event type this button/key generates.
+         If not specified defaults to <1> == EV_KEY.
+       - debounce-interval: Debouncing interval time in milliseconds.
+         If not specified defaults to 5.
+       - gpio-key,wakeup: Boolean, button can wake-up the system.
+
+Example nodes:
+
+       gpio_keys {
+                       compatible = "gpio-keys";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       autorepeat;
+                       button@21 {
+                               label = "GPIO Key UP";
+                               linux,code = <103>;
+                               gpios = <&gpio1 0 1>;
+                       };
+                       ...
diff --git a/Documentation/devicetree/bindings/watchdog/fsl-imx-wdt.txt b/Documentation/devicetree/bindings/watchdog/fsl-imx-wdt.txt
new file mode 100644 (file)
index 0000000..2144af1
--- /dev/null
@@ -0,0 +1,14 @@
+* Freescale i.MX Watchdog Timer (WDT) Controller
+
+Required properties:
+- compatible : Should be "fsl,<soc>-wdt"
+- reg : Should contain WDT registers location and length
+- interrupts : Should contain WDT interrupt
+
+Examples:
+
+wdt@73f98000 {
+       compatible = "fsl,imx51-wdt", "fsl,imx21-wdt";
+       reg = <0x73f98000 0x4000>;
+       interrupts = <58>;
+};
diff --git a/Documentation/devicetree/bindings/watchdog/samsung-wdt.txt b/Documentation/devicetree/bindings/watchdog/samsung-wdt.txt
new file mode 100644 (file)
index 0000000..79ead82
--- /dev/null
@@ -0,0 +1,11 @@
+* Samsung's Watchdog Timer Controller
+
+The Samsung's Watchdog controller is used for resuming system operation
+after a preset amount of time during which the WDT reset event has not
+occured.
+
+Required properties:
+- compatible : should be "samsung,s3c2410-wdt"
+- reg : base physical address of the controller and length of memory mapped
+       region.
+- interrupts : interrupt number to the cpu.
index f0eee83..fc94770 100644 (file)
@@ -360,18 +360,20 @@ Each directory contains:
         A file recording the current state of the device in the array
        which can be a comma separated list of
              faulty   - device has been kicked from active use due to
-                         a detected fault
+                         a detected fault or it has unacknowledged bad
+                         blocks
              in_sync  - device is a fully in-sync member of the array
              writemostly - device will only be subject to read
                         requests if there are no other options.
                         This applies only to raid1 arrays.
-             blocked  - device has failed, metadata is "external",
-                        and the failure hasn't been acknowledged yet.
+             blocked  - device has failed, and the failure hasn't been
+                        acknowledged yet by the metadata handler.
                         Writes that would write to this device if
                         it were not faulty are blocked.
              spare    - device is working, but not a full member.
                         This includes spares that are in the process
                         of being recovered to
+             write_error - device has ever seen a write error.
        This list may grow in future.
        This can be written to.
        Writing "faulty"  simulates a failure on the device.
@@ -379,9 +381,11 @@ Each directory contains:
        Writing "writemostly" sets the writemostly flag.
        Writing "-writemostly" clears the writemostly flag.
        Writing "blocked" sets the "blocked" flag.
-       Writing "-blocked" clears the "blocked" flag and allows writes
-               to complete.
+       Writing "-blocked" clears the "blocked" flags and allows writes
+               to complete and possibly simulates an error.
        Writing "in_sync" sets the in_sync flag.
+       Writing "write_error" sets writeerrorseen flag.
+       Writing "-write_error" clears writeerrorseen flag.
 
        This file responds to select/poll. Any change to 'faulty'
        or 'blocked' causes an event.
@@ -419,7 +423,6 @@ Each directory contains:
         written, it will be rejected.
 
       recovery_start
-
         When the device is not 'in_sync', this records the number of
        sectors from the start of the device which are known to be
        correct.  This is normally zero, but during a recovery
@@ -435,6 +438,20 @@ Each directory contains:
        Setting this to 'none' is equivalent to setting 'in_sync'.
        Setting to any other value also clears the 'in_sync' flag.
        
+      bad_blocks
+       This gives the list of all known bad blocks in the form of
+       start address and length (in sectors respectively). If output
+       is too big to fit in a page, it will be truncated. Writing
+       "sector length" to this file adds new acknowledged (i.e.
+       recorded to disk safely) bad blocks.
+
+      unacknowledged_bad_blocks
+       This gives the list of known-but-not-yet-saved-to-disk bad
+       blocks in the same form of 'bad_blocks'. If output is too big
+       to fit in a page, it will be truncated. Writing to this file
+       adds bad blocks without acknowledging them. This is largely
+       for testing.
+
 
 
 An active md device will also contain and entry for each active device
diff --git a/Documentation/security/keys-ecryptfs.txt b/Documentation/security/keys-ecryptfs.txt
new file mode 100644 (file)
index 0000000..c3bbeba
--- /dev/null
@@ -0,0 +1,68 @@
+               Encrypted keys for the eCryptfs filesystem
+
+ECryptfs is a stacked filesystem which transparently encrypts and decrypts each
+file using a randomly generated File Encryption Key (FEK).
+
+Each FEK is in turn encrypted with a File Encryption Key Encryption Key (FEFEK)
+either in kernel space or in user space with a daemon called 'ecryptfsd'.  In
+the former case the operation is performed directly by the kernel CryptoAPI
+using a key, the FEFEK, derived from a user prompted passphrase;  in the latter
+the FEK is encrypted by 'ecryptfsd' with the help of external libraries in order
+to support other mechanisms like public key cryptography, PKCS#11 and TPM based
+operations.
+
+The data structure defined by eCryptfs to contain information required for the
+FEK decryption is called authentication token and, currently, can be stored in a
+kernel key of the 'user' type, inserted in the user's session specific keyring
+by the userspace utility 'mount.ecryptfs' shipped with the package
+'ecryptfs-utils'.
+
+The 'encrypted' key type has been extended with the introduction of the new
+format 'ecryptfs' in order to be used in conjunction with the eCryptfs
+filesystem.  Encrypted keys of the newly introduced format store an
+authentication token in its payload with a FEFEK randomly generated by the
+kernel and protected by the parent master key.
+
+In order to avoid known-plaintext attacks, the datablob obtained through
+commands 'keyctl print' or 'keyctl pipe' does not contain the overall
+authentication token, which content is well known, but only the FEFEK in
+encrypted form.
+
+The eCryptfs filesystem may really benefit from using encrypted keys in that the
+required key can be securely generated by an Administrator and provided at boot
+time after the unsealing of a 'trusted' key in order to perform the mount in a
+controlled environment.  Another advantage is that the key is not exposed to
+threats of malicious software, because it is available in clear form only at
+kernel level.
+
+Usage:
+   keyctl add encrypted name "new ecryptfs key-type:master-key-name keylen" ring
+   keyctl add encrypted name "load hex_blob" ring
+   keyctl update keyid "update key-type:master-key-name"
+
+name:= '<16 hexadecimal characters>'
+key-type:= 'trusted' | 'user'
+keylen:= 64
+
+
+Example of encrypted key usage with the eCryptfs filesystem:
+
+Create an encrypted key "1000100010001000" of length 64 bytes with format
+'ecryptfs' and save it using a previously loaded user key "test":
+
+    $ keyctl add encrypted 1000100010001000 "new ecryptfs user:test 64" @u
+    19184530
+
+    $ keyctl print 19184530
+    ecryptfs user:test 64 490045d4bfe48c99f0d465fbbbb79e7500da954178e2de0697
+    dd85091f5450a0511219e9f7cd70dcd498038181466f78ac8d4c19504fcc72402bfc41c2
+    f253a41b7507ccaa4b2b03fff19a69d1cc0b16e71746473f023a95488b6edfd86f7fdd40
+    9d292e4bacded1258880122dd553a661
+
+    $ keyctl pipe 19184530 > ecryptfs.blob
+
+Mount an eCryptfs filesystem using the created encrypted key "1000100010001000"
+into the '/secret' directory:
+
+    $ mount -i -t ecryptfs -oecryptfs_sig=1000100010001000,\
+      ecryptfs_cipher=aes,ecryptfs_key_bytes=32 /secret /secret
index 8fb79bc..5f50cca 100644 (file)
@@ -53,12 +53,19 @@ they are only as secure as the user key encrypting them.  The master user key
 should therefore be loaded in as secure a way as possible, preferably early in
 boot.
 
+The decrypted portion of encrypted keys can contain either a simple symmetric
+key or a more complex structure. The format of the more complex structure is
+application specific, which is identified by 'format'.
+
 Usage:
-  keyctl add encrypted name "new key-type:master-key-name keylen" ring
-  keyctl add encrypted name "load hex_blob" ring
-  keyctl update keyid "update key-type:master-key-name"
+    keyctl add encrypted name "new [format] key-type:master-key-name keylen"
+        ring
+    keyctl add encrypted name "load hex_blob" ring
+    keyctl update keyid "update key-type:master-key-name"
+
+format:= 'default | ecryptfs'
+key-type:= 'trusted' | 'user'
 
-where 'key-type' is either 'trusted' or 'user'.
 
 Examples of trusted and encrypted key usage:
 
@@ -114,15 +121,25 @@ Reseal a trusted key under new pcr values:
     7ef6a24defe4846104209bf0c3eced7fa1a672ed5b125fc9d8cd88b476a658a4434644ef
     df8ae9a178e9f83ba9f08d10fa47e4226b98b0702f06b3b8
 
-Create and save an encrypted key "evm" using the above trusted key "kmk":
+The initial consumer of trusted keys is EVM, which at boot time needs a high
+quality symmetric key for HMAC protection of file metadata.  The use of a
+trusted key provides strong guarantees that the EVM key has not been
+compromised by a user level problem, and when sealed to specific boot PCR
+values, protects against boot and offline attacks.  Create and save an
+encrypted key "evm" using the above trusted key "kmk":
 
+option 1: omitting 'format'
     $ keyctl add encrypted evm "new trusted:kmk 32" @u
     159771175
 
+option 2: explicitly defining 'format' as 'default'
+    $ keyctl add encrypted evm "new default trusted:kmk 32" @u
+    159771175
+
     $ keyctl print 159771175
-    trusted:kmk 32 2375725ad57798846a9bbd240de8906f006e66c03af53b1b382dbbc55
-    be2a44616e4959430436dc4f2a7a9659aa60bb4652aeb2120f149ed197c564e024717c64
-    5972dcb82ab2dde83376d82b2e3c09ffc
+    default trusted:kmk 32 2375725ad57798846a9bbd240de8906f006e66c03af53b1b3
+    82dbbc55be2a44616e4959430436dc4f2a7a9659aa60bb4652aeb2120f149ed197c564e0
+    24717c64 5972dcb82ab2dde83376d82b2e3c09ffc
 
     $ keyctl pipe 159771175 > evm.blob
 
@@ -132,14 +149,11 @@ Load an encrypted key "evm" from saved blob:
     831684262
 
     $ keyctl print 831684262
-    trusted:kmk 32 2375725ad57798846a9bbd240de8906f006e66c03af53b1b382dbbc55
-    be2a44616e4959430436dc4f2a7a9659aa60bb4652aeb2120f149ed197c564e024717c64
-    5972dcb82ab2dde83376d82b2e3c09ffc
-
-
-The initial consumer of trusted keys is EVM, which at boot time needs a high
-quality symmetric key for HMAC protection of file metadata.  The use of a
-trusted key provides strong guarantees that the EVM key has not been
-compromised by a user level problem, and when sealed to specific boot PCR
-values, protects against boot and offline attacks.  Other uses for trusted and
-encrypted keys, such as for disk and file encryption are anticipated.
+    default trusted:kmk 32 2375725ad57798846a9bbd240de8906f006e66c03af53b1b3
+    82dbbc55be2a44616e4959430436dc4f2a7a9659aa60bb4652aeb2120f149ed197c564e0
+    24717c64 5972dcb82ab2dde83376d82b2e3c09ffc
+
+Other uses for trusted and encrypted keys, such as for disk and file encryption
+are anticipated.  In particular the new format 'ecryptfs' has been defined in
+in order to use encrypted keys to mount an eCryptfs filesystem.  More details
+about the usage can be found in the file 'Documentation/keys-ecryptfs.txt'.
index ee99451..fc51128 100644 (file)
@@ -8,6 +8,8 @@ src/
        - directory holding watchdog related example programs.
 watchdog-api.txt
        - description of the Linux Watchdog driver API.
+watchdog-kernel-api.txt
+       - description of the Linux WatchDog Timer Driver Core kernel API.
 watchdog-parameters.txt
        - information on driver parameters (for drivers other than
          the ones that have driver-specific files here)
diff --git a/Documentation/watchdog/watchdog-kernel-api.txt b/Documentation/watchdog/watchdog-kernel-api.txt
new file mode 100644 (file)
index 0000000..4f7c894
--- /dev/null
@@ -0,0 +1,162 @@
+The Linux WatchDog Timer Driver Core kernel API.
+===============================================
+Last reviewed: 22-Jul-2011
+
+Wim Van Sebroeck <wim@iguana.be>
+
+Introduction
+------------
+This document does not describe what a WatchDog Timer (WDT) Driver or Device is.
+It also does not describe the API which can be used by user space to communicate
+with a WatchDog Timer. If you want to know this then please read the following
+file: Documentation/watchdog/watchdog-api.txt .
+
+So what does this document describe? It describes the API that can be used by
+WatchDog Timer Drivers that want to use the WatchDog Timer Driver Core
+Framework. This framework provides all interfacing towards user space so that
+the same code does not have to be reproduced each time. This also means that
+a watchdog timer driver then only needs to provide the different routines
+(operations) that control the watchdog timer (WDT).
+
+The API
+-------
+Each watchdog timer driver that wants to use the WatchDog Timer Driver Core
+must #include <linux/watchdog.h> (you would have to do this anyway when
+writing a watchdog device driver). This include file contains following
+register/unregister routines:
+
+extern int watchdog_register_device(struct watchdog_device *);
+extern void watchdog_unregister_device(struct watchdog_device *);
+
+The watchdog_register_device routine registers a watchdog timer device.
+The parameter of this routine is a pointer to a watchdog_device structure.
+This routine returns zero on success and a negative errno code for failure.
+
+The watchdog_unregister_device routine deregisters a registered watchdog timer
+device. The parameter of this routine is the pointer to the registered
+watchdog_device structure.
+
+The watchdog device structure looks like this:
+
+struct watchdog_device {
+       const struct watchdog_info *info;
+       const struct watchdog_ops *ops;
+       unsigned int bootstatus;
+       unsigned int timeout;
+       unsigned int min_timeout;
+       unsigned int max_timeout;
+       void *driver_data;
+       unsigned long status;
+};
+
+It contains following fields:
+* info: a pointer to a watchdog_info structure. This structure gives some
+  additional information about the watchdog timer itself. (Like it's unique name)
+* ops: a pointer to the list of watchdog operations that the watchdog supports.
+* timeout: the watchdog timer's timeout value (in seconds).
+* min_timeout: the watchdog timer's minimum timeout value (in seconds).
+* max_timeout: the watchdog timer's maximum timeout value (in seconds).
+* bootstatus: status of the device after booting (reported with watchdog
+  WDIOF_* status bits).
+* driver_data: a pointer to the drivers private data of a watchdog device.
+  This data should only be accessed via the watchdog_set_drvadata and
+  watchdog_get_drvdata routines.
+* status: this field contains a number of status bits that give extra
+  information about the status of the device (Like: is the watchdog timer
+  running/active, is the nowayout bit set, is the device opened via
+  the /dev/watchdog interface or not, ...).
+
+The list of watchdog operations is defined as:
+
+struct watchdog_ops {
+       struct module *owner;
+       /* mandatory operations */
+       int (*start)(struct watchdog_device *);
+       int (*stop)(struct watchdog_device *);
+       /* optional operations */
+       int (*ping)(struct watchdog_device *);
+       unsigned int (*status)(struct watchdog_device *);
+       int (*set_timeout)(struct watchdog_device *, unsigned int);
+       long (*ioctl)(struct watchdog_device *, unsigned int, unsigned long);
+};
+
+It is important that you first define the module owner of the watchdog timer
+driver's operations. This module owner will be used to lock the module when
+the watchdog is active. (This to avoid a system crash when you unload the
+module and /dev/watchdog is still open).
+Some operations are mandatory and some are optional. The mandatory operations
+are:
+* start: this is a pointer to the routine that starts the watchdog timer
+  device.
+  The routine needs a pointer to the watchdog timer device structure as a
+  parameter. It returns zero on success or a negative errno code for failure.
+* stop: with this routine the watchdog timer device is being stopped.
+  The routine needs a pointer to the watchdog timer device structure as a
+  parameter. It returns zero on success or a negative errno code for failure.
+  Some watchdog timer hardware can only be started and not be stopped. The
+  driver supporting this hardware needs to make sure that a start and stop
+  routine is being provided. This can be done by using a timer in the driver
+  that regularly sends a keepalive ping to the watchdog timer hardware.
+
+Not all watchdog timer hardware supports the same functionality. That's why
+all other routines/operations are optional. They only need to be provided if
+they are supported. These optional routines/operations are:
+* ping: this is the routine that sends a keepalive ping to the watchdog timer
+  hardware.
+  The routine needs a pointer to the watchdog timer device structure as a
+  parameter. It returns zero on success or a negative errno code for failure.
+  Most hardware that does not support this as a separate function uses the
+  start function to restart the watchdog timer hardware. And that's also what
+  the watchdog timer driver core does: to send a keepalive ping to the watchdog
+  timer hardware it will either use the ping operation (when available) or the
+  start operation (when the ping operation is not available).
+  (Note: the WDIOC_KEEPALIVE ioctl call will only be active when the
+  WDIOF_KEEPALIVEPING bit has been set in the option field on the watchdog's
+  info structure).
+* status: this routine checks the status of the watchdog timer device. The
+  status of the device is reported with watchdog WDIOF_* status flags/bits.
+* set_timeout: this routine checks and changes the timeout of the watchdog
+  timer device. It returns 0 on success, -EINVAL for "parameter out of range"
+  and -EIO for "could not write value to the watchdog". On success the timeout
+  value of the watchdog_device will be changed to the value that was just used
+  to re-program the watchdog timer device.
+  (Note: the WDIOF_SETTIMEOUT needs to be set in the options field of the
+  watchdog's info structure).
+* ioctl: if this routine is present then it will be called first before we do
+  our own internal ioctl call handling. This routine should return -ENOIOCTLCMD
+  if a command is not supported. The parameters that are passed to the ioctl
+  call are: watchdog_device, cmd and arg.
+
+The status bits should (preferably) be set with the set_bit and clear_bit alike
+bit-operations. The status bits that are defined are:
+* WDOG_ACTIVE: this status bit indicates whether or not a watchdog timer device
+  is active or not. When the watchdog is active after booting, then you should
+  set this status bit (Note: when you register the watchdog timer device with
+  this bit set, then opening /dev/watchdog will skip the start operation)
+* WDOG_DEV_OPEN: this status bit shows whether or not the watchdog device
+  was opened via /dev/watchdog.
+  (This bit should only be used by the WatchDog Timer Driver Core).
+* WDOG_ALLOW_RELEASE: this bit stores whether or not the magic close character
+  has been sent (so that we can support the magic close feature).
+  (This bit should only be used by the WatchDog Timer Driver Core).
+* WDOG_NO_WAY_OUT: this bit stores the nowayout setting for the watchdog.
+  If this bit is set then the watchdog timer will not be able to stop.
+
+Note: The WatchDog Timer Driver Core supports the magic close feature and
+the nowayout feature. To use the magic close feature you must set the
+WDIOF_MAGICCLOSE bit in the options field of the watchdog's info structure.
+The nowayout feature will overrule the magic close feature.
+
+To get or set driver specific data the following two helper functions should be
+used:
+
+static inline void watchdog_set_drvdata(struct watchdog_device *wdd, void *data)
+static inline void *watchdog_get_drvdata(struct watchdog_device *wdd)
+
+The watchdog_set_drvdata function allows you to add driver specific data. The
+arguments of this function are the watchdog device where you want to add the
+driver specific data to and a pointer to the data itself.
+
+The watchdog_get_drvdata function allows you to retrieve driver specific data.
+The argument of this function is the watchdog device where you want to retrieve
+data from. The function retruns the pointer to the driver specific data.
index 7b2e9e8..1d2e79d 100644 (file)
@@ -6408,7 +6408,7 @@ L:        tomoyo-users-en@lists.sourceforge.jp (subscribers-only, for users in English)
 L:     tomoyo-dev@lists.sourceforge.jp (subscribers-only, for developers in Japanese)
 L:     tomoyo-users@lists.sourceforge.jp (subscribers-only, for users in Japanese)
 W:     http://tomoyo.sourceforge.jp/
-T:     quilt http://svn.sourceforge.jp/svnroot/tomoyo/trunk/2.3.x/tomoyo-lsm/patches/
+T:     quilt http://svn.sourceforge.jp/svnroot/tomoyo/trunk/2.4.x/tomoyo-lsm/patches/
 S:     Maintained
 F:     security/tomoyo/
 
index d8f0133..7d6831a 100644 (file)
@@ -38,6 +38,7 @@ struct cpuinfo {
        u32 use_exc;
        u32 ver_code;
        u32 mmu;
+       u32 mmu_privins;
        u32 endian;
 
        /* CPU caches */
index c4532f0..c9a6262 100644 (file)
@@ -14,7 +14,7 @@
 
 #if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
 
-static inline unsigned long arch_local_irq_save(void)
+static inline notrace unsigned long arch_local_irq_save(void)
 {
        unsigned long flags;
        asm volatile("  msrclr %0, %1   \n"
@@ -25,7 +25,7 @@ static inline unsigned long arch_local_irq_save(void)
        return flags;
 }
 
-static inline void arch_local_irq_disable(void)
+static inline notrace void arch_local_irq_disable(void)
 {
        /* this uses r0 without declaring it - is that correct? */
        asm volatile("  msrclr r0, %0   \n"
@@ -35,7 +35,7 @@ static inline void arch_local_irq_disable(void)
                     : "memory");
 }
 
-static inline void arch_local_irq_enable(void)
+static inline notrace void arch_local_irq_enable(void)
 {
        /* this uses r0 without declaring it - is that correct? */
        asm volatile("  msrset  r0, %0  \n"
@@ -47,7 +47,7 @@ static inline void arch_local_irq_enable(void)
 
 #else /* !CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR */
 
-static inline unsigned long arch_local_irq_save(void)
+static inline notrace unsigned long arch_local_irq_save(void)
 {
        unsigned long flags, tmp;
        asm volatile (" mfs     %0, rmsr        \n"
@@ -61,7 +61,7 @@ static inline unsigned long arch_local_irq_save(void)
        return flags;
 }
 
-static inline void arch_local_irq_disable(void)
+static inline notrace void arch_local_irq_disable(void)
 {
        unsigned long tmp;
        asm volatile("  mfs     %0, rmsr        \n"
@@ -74,7 +74,7 @@ static inline void arch_local_irq_disable(void)
                     : "memory");
 }
 
-static inline void arch_local_irq_enable(void)
+static inline notrace void arch_local_irq_enable(void)
 {
        unsigned long tmp;
        asm volatile("  mfs     %0, rmsr        \n"
@@ -89,7 +89,7 @@ static inline void arch_local_irq_enable(void)
 
 #endif /* CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR */
 
-static inline unsigned long arch_local_save_flags(void)
+static inline notrace unsigned long arch_local_save_flags(void)
 {
        unsigned long flags;
        asm volatile("  mfs     %0, rmsr        \n"
@@ -100,7 +100,7 @@ static inline unsigned long arch_local_save_flags(void)
        return flags;
 }
 
-static inline void arch_local_irq_restore(unsigned long flags)
+static inline notrace void arch_local_irq_restore(unsigned long flags)
 {
        asm volatile("  mts     rmsr, %0        \n"
                     "  nop                     \n"
@@ -109,12 +109,12 @@ static inline void arch_local_irq_restore(unsigned long flags)
                     : "memory");
 }
 
-static inline bool arch_irqs_disabled_flags(unsigned long flags)
+static inline notrace bool arch_irqs_disabled_flags(unsigned long flags)
 {
        return (flags & MSR_IE) == 0;
 }
 
-static inline bool arch_irqs_disabled(void)
+static inline notrace bool arch_irqs_disabled(void)
 {
        return arch_irqs_disabled_flags(arch_local_save_flags());
 }
index aed2a6b..7283bfb 100644 (file)
@@ -125,9 +125,6 @@ struct thread_struct {
        .pgdir = swapper_pg_dir, \
 }
 
-/* Do necessary setup to start up a newly executed thread.  */
-void start_thread(struct pt_regs *regs,
-               unsigned long pc, unsigned long usp);
 
 /* Free all resources held by a thread. */
 extern inline void release_thread(struct task_struct *dead_task)
index 9ad567e..20c5e8e 100644 (file)
 #define HAVE_ARCH_DEVTREE_FIXUPS
 
 /* Other Prototypes */
-extern int early_uartlite_console(void);
-extern int early_uart16550_console(void);
+enum early_consoles {
+       UARTLITE = 1,
+       UART16550 = 2,
+};
+
+extern int of_early_console(void *version);
 
 /*
  * OF address retreival & translation
index a10bec6..4bbdb4c 100644 (file)
@@ -111,16 +111,16 @@ struct pvr_s {
 /* Target family PVR mask */
 #define PVR10_TARGET_FAMILY_MASK       0xFF000000
 
-/* MMU descrtiption */
+/* MMU description */
 #define PVR11_USE_MMU                  0xC0000000
 #define PVR11_MMU_ITLB_SIZE            0x38000000
 #define PVR11_MMU_DTLB_SIZE            0x07000000
 #define PVR11_MMU_TLB_ACCESS           0x00C00000
 #define PVR11_MMU_ZONES                        0x003C0000
+#define PVR11_MMU_PRIVINS              0x00010000
 /* MSR Reset value PVR mask */
 #define PVR11_MSR_RESET_VALUE_MASK     0x000007FF
 
-
 /* PVR access macros */
 #define PVR_IS_FULL(_pvr)      (_pvr.pvr[0] & PVR0_PVR_FULL_MASK)
 #define PVR_USE_BARREL(_pvr)   (_pvr.pvr[0] & PVR0_USE_BARREL_MASK)
@@ -216,6 +216,7 @@ struct pvr_s {
 #define PVR_MMU_DTLB_SIZE(_pvr)                (_pvr.pvr[11] & PVR11_MMU_DTLB_SIZE)
 #define PVR_MMU_TLB_ACCESS(_pvr)       (_pvr.pvr[11] & PVR11_MMU_TLB_ACCESS)
 #define PVR_MMU_ZONES(_pvr)            (_pvr.pvr[11] & PVR11_MMU_ZONES)
+#define PVR_MMU_PRIVINS(pvr)           (pvr.pvr[11] & PVR11_MMU_PRIVINS)
 
 /* endian */
 #define PVR_ENDIAN(_pvr)       (_pvr.pvr[0] & PVR0_ENDI)
index 8f39689..904e5ef 100644 (file)
@@ -23,6 +23,7 @@ extern char cmd_line[COMMAND_LINE_SIZE];
 void early_printk(const char *fmt, ...);
 
 int setup_early_printk(char *opt);
+void remap_early_printk(void);
 void disable_early_printk(void);
 
 #if defined(CONFIG_EARLY_PRINTK)
index f70a604..916aaed 100644 (file)
@@ -72,6 +72,7 @@ void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu)
        CI(pvr_user2, USER2);
 
        CI(mmu, USE_MMU);
+       CI(mmu_privins, MMU_PRIVINS);
        CI(endian, ENDIAN);
 
        CI(use_icache, USE_ICACHE);
index b16b994..592bb2e 100644 (file)
@@ -119,6 +119,7 @@ void __init set_cpuinfo_static(struct cpuinfo *ci, struct device_node *cpu)
        ci->pvr_user2 = fcpu(cpu, "xlnx,pvr-user2");
 
        ci->mmu = fcpu(cpu, "xlnx,use-mmu");
+       ci->mmu_privins = fcpu(cpu, "xlnx,mmu-privileged-instr");
        ci->endian = fcpu(cpu, "xlnx,endianness");
 
        ci->ver_code = 0;
index c1640c5..44394d8 100644 (file)
@@ -88,4 +88,8 @@ void __init setup_cpuinfo(void)
                printk(KERN_WARNING "%s: Unsupported PVR setting\n", __func__);
                set_cpuinfo_static(&cpuinfo, cpu);
        }
+
+       if (cpuinfo.mmu_privins)
+               printk(KERN_WARNING "%s: Stream instructions enabled"
+                       " - USERSPACE CAN LOCK THIS KERNEL!\n", __func__);
 }
index b4048af..7b5dca7 100644 (file)
@@ -97,6 +97,10 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                (cpuinfo.use_exc & PVR2_FPU_EXC_MASK) ? "fpu " : "",
                (cpuinfo.use_exc & PVR2_USE_FSL_EXC) ? "fsl " : "");
 
+       count += seq_printf(m,
+                       "Stream-insns:\t%sprivileged\n",
+                       cpuinfo.mmu_privins ? "un" : "");
+
        if (cpuinfo.use_icache)
                count += seq_printf(m,
                                "Icache:\t\t%ukB\tline length:\t%dB\n",
@@ -110,10 +114,11 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                                "Dcache:\t\t%ukB\tline length:\t%dB\n",
                                cpuinfo.dcache_size >> 10,
                                cpuinfo.dcache_line_length);
+               seq_printf(m, "Dcache-Policy:\t");
                if (cpuinfo.dcache_wb)
-                       count += seq_printf(m, "\t\twrite-back\n");
+                       count += seq_printf(m, "write-back\n");
                else
-                       count += seq_printf(m, "\t\twrite-through\n");
+                       count += seq_printf(m, "write-through\n");
        } else
                count += seq_printf(m, "Dcache:\t\tno\n");
 
index c3616a0..d26d92d 100644 (file)
@@ -35,7 +35,7 @@ static void early_printk_uartlite_putc(char c)
         * we'll never timeout on a working UART.
         */
 
-       unsigned retries = 10000;
+       unsigned retries = 1000000;
        /* read status bit - 0x8 offset */
        while (--retries && (in_be32(base_addr + 8) & (1 << 3)))
                ;
@@ -60,7 +60,7 @@ static void early_printk_uartlite_write(struct console *unused,
 static struct console early_serial_uartlite_console = {
        .name = "earlyser",
        .write = early_printk_uartlite_write,
-       .flags = CON_PRINTBUFFER,
+       .flags = CON_PRINTBUFFER | CON_BOOT,
        .index = -1,
 };
 #endif /* CONFIG_SERIAL_UARTLITE_CONSOLE */
@@ -104,7 +104,7 @@ static void early_printk_uart16550_write(struct console *unused,
 static struct console early_serial_uart16550_console = {
        .name = "earlyser",
        .write = early_printk_uart16550_write,
-       .flags = CON_PRINTBUFFER,
+       .flags = CON_PRINTBUFFER | CON_BOOT,
        .index = -1,
 };
 #endif /* CONFIG_SERIAL_8250_CONSOLE */
@@ -127,48 +127,56 @@ void early_printk(const char *fmt, ...)
 
 int __init setup_early_printk(char *opt)
 {
+       int version = 0;
+
        if (early_console_initialized)
                return 1;
 
-#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
-       base_addr = early_uartlite_console();
+       base_addr = of_early_console(&version);
        if (base_addr) {
-               early_console_initialized = 1;
 #ifdef CONFIG_MMU
                early_console_reg_tlb_alloc(base_addr);
 #endif
-               early_console = &early_serial_uartlite_console;
-               early_printk("early_printk_console is enabled at 0x%08x\n",
-                                                       base_addr);
-
-               /* register_console(early_console); */
-
-               return 0;
-       }
-#endif /* CONFIG_SERIAL_UARTLITE_CONSOLE */
-
+               switch (version) {
+#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
+               case UARTLITE:
+                       printk(KERN_INFO "Early console on uartlite "
+                                               "at 0x%08x\n", base_addr);
+                       early_console = &early_serial_uartlite_console;
+                       break;
+#endif
 #ifdef CONFIG_SERIAL_8250_CONSOLE
-       base_addr = early_uart16550_console();
-       base_addr &= ~3; /* clear register offset */
-       if (base_addr) {
-               early_console_initialized = 1;
-#ifdef CONFIG_MMU
-               early_console_reg_tlb_alloc(base_addr);
+               case UART16550:
+                       printk(KERN_INFO "Early console on uart16650 "
+                                               "at 0x%08x\n", base_addr);
+                       early_console = &early_serial_uart16550_console;
+                       break;
 #endif
-               early_console = &early_serial_uart16550_console;
-
-               early_printk("early_printk_console is enabled at 0x%08x\n",
-                                                       base_addr);
-
-               /* register_console(early_console); */
+               default:
+                       printk(KERN_INFO  "Unsupported early console %d\n",
+                                                               version);
+                       return 1;
+               }
 
+               register_console(early_console);
+               early_console_initialized = 1;
                return 0;
        }
-#endif /* CONFIG_SERIAL_8250_CONSOLE */
-
        return 1;
 }
 
+/* Remap early console to virtual address and do not allocate one TLB
+ * only for early console because of performance degression */
+void __init remap_early_printk(void)
+{
+       if (!early_console_initialized || !early_console)
+               return;
+       printk(KERN_INFO "early_printk_console remaping from 0x%x to ",
+                                                               base_addr);
+       base_addr = (u32) ioremap(base_addr, PAGE_SIZE);
+       printk(KERN_CONT "0x%x\n", base_addr);
+}
+
 void __init disable_early_printk(void)
 {
        if (!early_console_initialized || !early_console)
index 56572e9..e62be83 100644 (file)
@@ -1113,23 +1113,23 @@ lw_r10_vm:      R3_TO_LWREG_VM_V        (10);
 lw_r11_vm:     R3_TO_LWREG_VM_V        (11);
 lw_r12_vm:     R3_TO_LWREG_VM_V        (12);
 lw_r13_vm:     R3_TO_LWREG_VM_V        (13);
-lw_r14_vm:     R3_TO_LWREG_VM          (14);
+lw_r14_vm:     R3_TO_LWREG_VM_V        (14);
 lw_r15_vm:     R3_TO_LWREG_VM_V        (15);
-lw_r16_vm:     R3_TO_LWREG_VM          (16);
+lw_r16_vm:     R3_TO_LWREG_VM_V        (16);
 lw_r17_vm:     R3_TO_LWREG_VM_V        (17);
 lw_r18_vm:     R3_TO_LWREG_VM_V        (18);
-lw_r19_vm:     R3_TO_LWREG_VM          (19);
-lw_r20_vm:     R3_TO_LWREG_VM          (20);
-lw_r21_vm:     R3_TO_LWREG_VM          (21);
-lw_r22_vm:     R3_TO_LWREG_VM          (22);
-lw_r23_vm:     R3_TO_LWREG_VM          (23);
-lw_r24_vm:     R3_TO_LWREG_VM          (24);
-lw_r25_vm:     R3_TO_LWREG_VM          (25);
-lw_r26_vm:     R3_TO_LWREG_VM          (26);
-lw_r27_vm:     R3_TO_LWREG_VM          (27);
-lw_r28_vm:     R3_TO_LWREG_VM          (28);
-lw_r29_vm:     R3_TO_LWREG_VM          (29);
-lw_r30_vm:     R3_TO_LWREG_VM          (30);
+lw_r19_vm:     R3_TO_LWREG_VM_V        (19);
+lw_r20_vm:     R3_TO_LWREG_VM_V        (20);
+lw_r21_vm:     R3_TO_LWREG_VM_V        (21);
+lw_r22_vm:     R3_TO_LWREG_VM_V        (22);
+lw_r23_vm:     R3_TO_LWREG_VM_V        (23);
+lw_r24_vm:     R3_TO_LWREG_VM_V        (24);
+lw_r25_vm:     R3_TO_LWREG_VM_V        (25);
+lw_r26_vm:     R3_TO_LWREG_VM_V        (26);
+lw_r27_vm:     R3_TO_LWREG_VM_V        (27);
+lw_r28_vm:     R3_TO_LWREG_VM_V        (28);
+lw_r29_vm:     R3_TO_LWREG_VM_V        (29);
+lw_r30_vm:     R3_TO_LWREG_VM_V        (30);
 lw_r31_vm:     R3_TO_LWREG_VM_V        (31);
 
 sw_table_vm:
@@ -1147,23 +1147,23 @@ sw_r10_vm:      SWREG_TO_R3_VM_V        (10);
 sw_r11_vm:     SWREG_TO_R3_VM_V        (11);
 sw_r12_vm:     SWREG_TO_R3_VM_V        (12);
 sw_r13_vm:     SWREG_TO_R3_VM_V        (13);
-sw_r14_vm:     SWREG_TO_R3_VM          (14);
+sw_r14_vm:     SWREG_TO_R3_VM_V        (14);
 sw_r15_vm:     SWREG_TO_R3_VM_V        (15);
-sw_r16_vm:     SWREG_TO_R3_VM          (16);
+sw_r16_vm:     SWREG_TO_R3_VM_V        (16);
 sw_r17_vm:     SWREG_TO_R3_VM_V        (17);
 sw_r18_vm:     SWREG_TO_R3_VM_V        (18);
-sw_r19_vm:     SWREG_TO_R3_VM          (19);
-sw_r20_vm:     SWREG_TO_R3_VM          (20);
-sw_r21_vm:     SWREG_TO_R3_VM          (21);
-sw_r22_vm:     SWREG_TO_R3_VM          (22);
-sw_r23_vm:     SWREG_TO_R3_VM          (23);
-sw_r24_vm:     SWREG_TO_R3_VM          (24);
-sw_r25_vm:     SWREG_TO_R3_VM          (25);
-sw_r26_vm:     SWREG_TO_R3_VM          (26);
-sw_r27_vm:     SWREG_TO_R3_VM          (27);
-sw_r28_vm:     SWREG_TO_R3_VM          (28);
-sw_r29_vm:     SWREG_TO_R3_VM          (29);
-sw_r30_vm:     SWREG_TO_R3_VM          (30);
+sw_r19_vm:     SWREG_TO_R3_VM_V        (19);
+sw_r20_vm:     SWREG_TO_R3_VM_V        (20);
+sw_r21_vm:     SWREG_TO_R3_VM_V        (21);
+sw_r22_vm:     SWREG_TO_R3_VM_V        (22);
+sw_r23_vm:     SWREG_TO_R3_VM_V        (23);
+sw_r24_vm:     SWREG_TO_R3_VM_V        (24);
+sw_r25_vm:     SWREG_TO_R3_VM_V        (25);
+sw_r26_vm:     SWREG_TO_R3_VM_V        (26);
+sw_r27_vm:     SWREG_TO_R3_VM_V        (27);
+sw_r28_vm:     SWREG_TO_R3_VM_V        (28);
+sw_r29_vm:     SWREG_TO_R3_VM_V        (29);
+sw_r30_vm:     SWREG_TO_R3_VM_V        (30);
 sw_r31_vm:     SWREG_TO_R3_VM_V        (31);
 #endif /* CONFIG_MMU */
 
index c88f066..eb41441 100644 (file)
@@ -134,7 +134,7 @@ void __init init_IRQ(void)
        intr_type =
                be32_to_cpup(of_get_property(intc,
                                                "xlnx,kind-of-intr", NULL));
-       if (intr_type >= (1 << (nr_irq + 1)))
+       if (intr_type > (u32)((1ULL << nr_irq) - 1))
                printk(KERN_INFO " ERROR: Mismatch in kind-of-intr param\n");
 
 #ifdef CONFIG_SELFMOD_INTC
index 968648a..dbb8124 100644 (file)
@@ -237,7 +237,6 @@ unsigned long get_wchan(struct task_struct *p)
 /* Set up a thread for executing a new program */
 void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long usp)
 {
-       set_fs(USER_DS);
        regs->pc = pc;
        regs->r1 = usp;
        regs->pt_mode = 0;
index b15cc21..977484a 100644 (file)
@@ -53,69 +53,58 @@ void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
 }
 
 #ifdef CONFIG_EARLY_PRINTK
-/* MS this is Microblaze specifig function */
-static int __init early_init_dt_scan_serial(unsigned long node,
-                               const char *uname, int depth, void *data)
-{
-       unsigned long l;
-       char *p;
-       const __be32 *addr;
-
-       pr_debug("search \"serial\", depth: %d, uname: %s\n", depth, uname);
-
-/* find all serial nodes */
-       if (strncmp(uname, "serial", 6) != 0)
-               return 0;
-
-/* find compatible node with uartlite */
-       p = of_get_flat_dt_prop(node, "compatible", &l);
-       if ((strncmp(p, "xlnx,xps-uartlite", 17) != 0) &&
-                       (strncmp(p, "xlnx,opb-uartlite", 17) != 0) &&
-                       (strncmp(p, "xlnx,axi-uartlite", 17) != 0))
-               return 0;
-
-       addr = of_get_flat_dt_prop(node, "reg", &l);
-       return be32_to_cpup(addr); /* return address */
-}
+char *stdout;
 
-/* this function is looking for early uartlite console - Microblaze specific */
-int __init early_uartlite_console(void)
-{
-       return of_scan_flat_dt(early_init_dt_scan_serial, NULL);
-}
-
-/* MS this is Microblaze specifig function */
-static int __init early_init_dt_scan_serial_full(unsigned long node,
+int __init early_init_dt_scan_chosen_serial(unsigned long node,
                                const char *uname, int depth, void *data)
 {
        unsigned long l;
        char *p;
-       unsigned int addr;
-
-       pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
-
-/* find all serial nodes */
-       if (strncmp(uname, "serial", 6) != 0)
-               return 0;
 
-       early_init_dt_check_for_initrd(node);
-
-/* find compatible node with uartlite */
-       p = of_get_flat_dt_prop(node, "compatible", &l);
-
-       if ((strncmp(p, "xlnx,xps-uart16550", 18) != 0) &&
-               (strncmp(p, "xlnx,axi-uart16550", 18) != 0))
-               return 0;
-
-       addr = *(u32 *)of_get_flat_dt_prop(node, "reg", &l);
-       addr += *(u32 *)of_get_flat_dt_prop(node, "reg-offset", &l);
-       return be32_to_cpu(addr); /* return address */
+       pr_debug("%s: depth: %d, uname: %s\n", __func__, depth, uname);
+
+       if (depth == 1 && (strcmp(uname, "chosen") == 0 ||
+                               strcmp(uname, "chosen@0") == 0)) {
+               p = of_get_flat_dt_prop(node, "linux,stdout-path", &l);
+               if (p != NULL && l > 0)
+                       stdout = p; /* store pointer to stdout-path */
+       }
+
+       if (stdout && strstr(stdout, uname)) {
+               p = of_get_flat_dt_prop(node, "compatible", &l);
+               pr_debug("Compatible string: %s\n", p);
+
+               if ((strncmp(p, "xlnx,xps-uart16550", 18) == 0) ||
+                       (strncmp(p, "xlnx,axi-uart16550", 18) == 0)) {
+                       unsigned int addr;
+
+                       *(u32 *)data = UART16550;
+
+                       addr = *(u32 *)of_get_flat_dt_prop(node, "reg", &l);
+                       addr += *(u32 *)of_get_flat_dt_prop(node,
+                                                       "reg-offset", &l);
+                       /* clear register offset */
+                       return be32_to_cpu(addr) & ~3;
+               }
+               if ((strncmp(p, "xlnx,xps-uartlite", 17) == 0) ||
+                               (strncmp(p, "xlnx,opb-uartlite", 17) == 0) ||
+                               (strncmp(p, "xlnx,axi-uartlite", 17) == 0) ||
+                               (strncmp(p, "xlnx,mdm", 8) == 0)) {
+                       unsigned int *addrp;
+
+                       *(u32 *)data = UARTLITE;
+
+                       addrp = of_get_flat_dt_prop(node, "reg", &l);
+                       return be32_to_cpup(addrp); /* return address */
+               }
+       }
+       return 0;
 }
 
-/* this function is looking for early uartlite console - Microblaze specific */
-int __init early_uart16550_console(void)
+/* this function is looking for early console - Microblaze specific */
+int __init of_early_console(void *version)
 {
-       return of_scan_flat_dt(early_init_dt_scan_serial_full, NULL);
+       return of_scan_flat_dt(early_init_dt_scan_chosen_serial, version);
 }
 #endif
 
index 8e2c09b..0e654a1 100644 (file)
@@ -59,6 +59,11 @@ void __init setup_arch(char **cmdline_p)
 
        setup_memory();
 
+#ifdef CONFIG_EARLY_PRINTK
+       /* remap early console to virtual address */
+       remap_early_printk();
+#endif
+
        xilinx_pci_init();
 
 #if defined(CONFIG_SELFMOD_INTC) || defined(CONFIG_SELFMOD_TIMER)
index cfa9cd2..64f7a00 100644 (file)
@@ -177,9 +177,11 @@ static inline unsigned int sparc64_elf_hwcap(void)
                cap |= HWCAP_SPARC_ULTRA3;
        else if (tlb_type == hypervisor) {
                if (sun4v_chip_type == SUN4V_CHIP_NIAGARA1 ||
-                   sun4v_chip_type == SUN4V_CHIP_NIAGARA2)
+                   sun4v_chip_type == SUN4V_CHIP_NIAGARA2 ||
+                   sun4v_chip_type == SUN4V_CHIP_NIAGARA3)
                        cap |= HWCAP_SPARC_BLKINIT;
-               if (sun4v_chip_type == SUN4V_CHIP_NIAGARA2)
+               if (sun4v_chip_type == SUN4V_CHIP_NIAGARA2 ||
+                   sun4v_chip_type == SUN4V_CHIP_NIAGARA3)
                        cap |= HWCAP_SPARC_N2;
        }
 
index 7568640..7a5f80d 100644 (file)
@@ -2950,6 +2950,7 @@ extern unsigned long sun4v_ncs_request(unsigned long request,
 #define HV_GRP_N2_CPU                  0x0202
 #define HV_GRP_NIU                     0x0204
 #define HV_GRP_VF_CPU                  0x0205
+#define HV_GRP_KT_CPU                  0x0209
 #define HV_GRP_DIAG                    0x0300
 
 #ifndef __ASSEMBLY__
index f0d0c40..55a17c6 100644 (file)
@@ -42,6 +42,7 @@
 #define SUN4V_CHIP_INVALID     0x00
 #define SUN4V_CHIP_NIAGARA1    0x01
 #define SUN4V_CHIP_NIAGARA2    0x02
+#define SUN4V_CHIP_NIAGARA3    0x03
 #define SUN4V_CHIP_UNKNOWN     0xff
 
 #ifndef __ASSEMBLY__
index bee4bf4..9ed6ff6 100644 (file)
@@ -65,6 +65,7 @@ static struct xor_block_template xor_block_niagara = {
 #define XOR_SELECT_TEMPLATE(FASTEST) \
        ((tlb_type == hypervisor && \
          (sun4v_chip_type == SUN4V_CHIP_NIAGARA1 || \
-          sun4v_chip_type == SUN4V_CHIP_NIAGARA2)) ? \
+          sun4v_chip_type == SUN4V_CHIP_NIAGARA2 || \
+          sun4v_chip_type == SUN4V_CHIP_NIAGARA3)) ? \
         &xor_block_niagara : \
         &xor_block_VIS)
index 138dbbc..17cf290 100644 (file)
@@ -474,11 +474,18 @@ static void __init sun4v_cpu_probe(void)
                sparc_pmu_type = "niagara2";
                break;
 
+       case SUN4V_CHIP_NIAGARA3:
+               sparc_cpu_type = "UltraSparc T3 (Niagara3)";
+               sparc_fpu_type = "UltraSparc T3 integrated FPU";
+               sparc_pmu_type = "niagara3";
+               break;
+
        default:
                printk(KERN_WARNING "CPU: Unknown sun4v cpu type [%s]\n",
                       prom_cpu_compatible);
                sparc_cpu_type = "Unknown SUN4V CPU";
                sparc_fpu_type = "Unknown SUN4V FPU";
+               sparc_pmu_type = "Unknown SUN4V PMU";
                break;
        }
 }
index d91fd78..4197e8d 100644 (file)
@@ -324,6 +324,7 @@ static int iterate_cpu(struct cpuinfo_tree *t, unsigned int root_index)
        switch (sun4v_chip_type) {
        case SUN4V_CHIP_NIAGARA1:
        case SUN4V_CHIP_NIAGARA2:
+       case SUN4V_CHIP_NIAGARA3:
                rover_inc_table = niagara_iterate_method;
                break;
        default:
index aa594c7..c752603 100644 (file)
@@ -132,6 +132,8 @@ prom_sun4v_name:
        .asciz  "sun4v"
 prom_niagara_prefix:
        .asciz  "SUNW,UltraSPARC-T"
+prom_sparc_prefix:
+       .asciz  "SPARC-T"
        .align  4
 prom_root_compatible:
        .skip   64
@@ -379,6 +381,22 @@ sun4v_chip_type:
        sethi   %hi(prom_niagara_prefix), %g7
        or      %g7, %lo(prom_niagara_prefix), %g7
        mov     17, %g3
+90:    ldub    [%g7], %g2
+       ldub    [%g1], %g4
+       cmp     %g2, %g4
+       bne,pn  %icc, 89f
+        add    %g7, 1, %g7
+       subcc   %g3, 1, %g3
+       bne,pt  %xcc, 90b
+        add    %g1, 1, %g1
+       ba,pt   %xcc, 91f
+        nop
+
+89:    sethi   %hi(prom_cpu_compatible), %g1
+       or      %g1, %lo(prom_cpu_compatible), %g1
+       sethi   %hi(prom_sparc_prefix), %g7
+       or      %g7, %lo(prom_sparc_prefix), %g7
+       mov     7, %g3
 90:    ldub    [%g7], %g2
        ldub    [%g1], %g4
        cmp     %g2, %g4
@@ -389,6 +407,15 @@ sun4v_chip_type:
         add    %g1, 1, %g1
 
        sethi   %hi(prom_cpu_compatible), %g1
+       or      %g1, %lo(prom_cpu_compatible), %g1
+       ldub    [%g1 + 7], %g2
+       cmp     %g2, '3'
+       be,pt   %xcc, 5f
+        mov    SUN4V_CHIP_NIAGARA3, %g4
+       ba,pt   %xcc, 4f
+        nop
+
+91:    sethi   %hi(prom_cpu_compatible), %g1
        or      %g1, %lo(prom_cpu_compatible), %g1
        ldub    [%g1 + 17], %g2
        cmp     %g2, '1'
@@ -397,6 +424,7 @@ sun4v_chip_type:
        cmp     %g2, '2'
        be,pt   %xcc, 5f
         mov    SUN4V_CHIP_NIAGARA2, %g4
+       
 4:
        mov     SUN4V_CHIP_UNKNOWN, %g4
 5:     sethi   %hi(sun4v_chip_type), %g2
@@ -514,6 +542,9 @@ niagara_tlb_fixup:
         cmp    %g1, SUN4V_CHIP_NIAGARA2
        be,pt   %xcc, niagara2_patch
         nop
+       cmp     %g1, SUN4V_CHIP_NIAGARA3
+       be,pt   %xcc, niagara2_patch
+        nop
 
        call    generic_patch_copyops
         nop
index 7c60afb..d306e64 100644 (file)
@@ -38,6 +38,7 @@ static struct api_info api_table[] = {
        { .group = HV_GRP_N2_CPU,                               },
        { .group = HV_GRP_NIU,                                  },
        { .group = HV_GRP_VF_CPU,                               },
+       { .group = HV_GRP_KT_CPU,                               },
        { .group = HV_GRP_DIAG,         .flags = FLAG_PRE_API   },
 };
 
index 8ac23e6..343b0f9 100644 (file)
@@ -80,8 +80,11 @@ static void n2_pcr_write(u64 val)
 {
        unsigned long ret;
 
-       ret = sun4v_niagara2_setperf(HV_N2_PERF_SPARC_CTL, val);
-       if (ret != HV_EOK)
+       if (val & PCR_N2_HTRACE) {
+               ret = sun4v_niagara2_setperf(HV_N2_PERF_SPARC_CTL, val);
+               if (ret != HV_EOK)
+                       write_pcr(val);
+       } else
                write_pcr(val);
 }
 
@@ -106,6 +109,10 @@ static int __init register_perf_hsvc(void)
                        perf_hsvc_group = HV_GRP_N2_CPU;
                        break;
 
+               case SUN4V_CHIP_NIAGARA3:
+                       perf_hsvc_group = HV_GRP_KT_CPU;
+                       break;
+
                default:
                        return -ENODEV;
                }
index 171e8d8..614da62 100644 (file)
@@ -1343,7 +1343,8 @@ static bool __init supported_pmu(void)
                sparc_pmu = &niagara1_pmu;
                return true;
        }
-       if (!strcmp(sparc_pmu_type, "niagara2")) {
+       if (!strcmp(sparc_pmu_type, "niagara2") ||
+           !strcmp(sparc_pmu_type, "niagara3")) {
                sparc_pmu = &niagara2_pmu;
                return true;
        }
index 1a371f8..8600eb2 100644 (file)
@@ -55,7 +55,7 @@ int atomic_cmpxchg(atomic_t *v, int old, int new)
 }
 EXPORT_SYMBOL(atomic_cmpxchg);
 
-int atomic_add_unless(atomic_t *v, int a, int u)
+int __atomic_add_unless(atomic_t *v, int a, int u)
 {
        int ret;
        unsigned long flags;
@@ -67,7 +67,7 @@ int atomic_add_unless(atomic_t *v, int a, int u)
        spin_unlock_irqrestore(ATOMIC_HASH(v), flags);
        return ret != u;
 }
-EXPORT_SYMBOL(atomic_add_unless);
+EXPORT_SYMBOL(__atomic_add_unless);
 
 /* Atomic operations are already serializing */
 void atomic_set(atomic_t *v, int i)
index ac6739e..c3de70d 100644 (file)
@@ -1,6 +1,6 @@
 /* n2-drv.c: Niagara-2 RNG driver.
  *
- * Copyright (C) 2008 David S. Miller <davem@davemloft.net>
+ * Copyright (C) 2008, 2011 David S. Miller <davem@davemloft.net>
  */
 
 #include <linux/kernel.h>
@@ -22,8 +22,8 @@
 
 #define DRV_MODULE_NAME                "n2rng"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "0.1"
-#define DRV_MODULE_RELDATE     "May 15, 2008"
+#define DRV_MODULE_VERSION     "0.2"
+#define DRV_MODULE_RELDATE     "July 27, 2011"
 
 static char version[] __devinitdata =
        DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
@@ -623,14 +623,14 @@ static const struct of_device_id n2rng_match[];
 static int __devinit n2rng_probe(struct platform_device *op)
 {
        const struct of_device_id *match;
-       int victoria_falls;
+       int multi_capable;
        int err = -ENOMEM;
        struct n2rng *np;
 
        match = of_match_device(n2rng_match, &op->dev);
        if (!match)
                return -EINVAL;
-       victoria_falls = (match->data != NULL);
+       multi_capable = (match->data != NULL);
 
        n2rng_driver_version();
        np = kzalloc(sizeof(*np), GFP_KERNEL);
@@ -640,8 +640,8 @@ static int __devinit n2rng_probe(struct platform_device *op)
 
        INIT_DELAYED_WORK(&np->work, n2rng_work);
 
-       if (victoria_falls)
-               np->flags |= N2RNG_FLAG_VF;
+       if (multi_capable)
+               np->flags |= N2RNG_FLAG_MULTI;
 
        err = -ENODEV;
        np->hvapi_major = 2;
@@ -658,10 +658,10 @@ static int __devinit n2rng_probe(struct platform_device *op)
                }
        }
 
-       if (np->flags & N2RNG_FLAG_VF) {
+       if (np->flags & N2RNG_FLAG_MULTI) {
                if (np->hvapi_major < 2) {
-                       dev_err(&op->dev, "VF RNG requires HVAPI major "
-                               "version 2 or later, got %lu\n",
+                       dev_err(&op->dev, "multi-unit-capable RNG requires "
+                               "HVAPI major version 2 or later, got %lu\n",
                                np->hvapi_major);
                        goto out_hvapi_unregister;
                }
@@ -688,8 +688,8 @@ static int __devinit n2rng_probe(struct platform_device *op)
                goto out_free_units;
 
        dev_info(&op->dev, "Found %s RNG, units: %d\n",
-                ((np->flags & N2RNG_FLAG_VF) ?
-                 "Victoria Falls" : "Niagara2"),
+                ((np->flags & N2RNG_FLAG_MULTI) ?
+                 "multi-unit-capable" : "single-unit"),
                 np->num_units);
 
        np->hwrng.name = "n2rng";
@@ -751,6 +751,11 @@ static const struct of_device_id n2rng_match[] = {
                .compatible     = "SUNW,vf-rng",
                .data           = (void *) 1,
        },
+       {
+               .name           = "random-number-generator",
+               .compatible     = "SUNW,kt-rng",
+               .data           = (void *) 1,
+       },
        {},
 };
 MODULE_DEVICE_TABLE(of, n2rng_match);
index 4bea07f..f244ac8 100644 (file)
@@ -68,7 +68,7 @@ struct n2rng {
        struct platform_device  *op;
 
        unsigned long           flags;
-#define N2RNG_FLAG_VF          0x00000001 /* Victoria Falls RNG, else N2 */
+#define N2RNG_FLAG_MULTI       0x00000001 /* Multi-unit capable RNG */
 #define N2RNG_FLAG_CONTROL     0x00000002 /* Operating in control domain */
 #define N2RNG_FLAG_READY       0x00000008 /* Ready for hw-rng layer      */
 #define N2RNG_FLAG_SHUTDOWN    0x00000010 /* Driver unregistering        */
index 7beb0e2..caf8012 100644 (file)
@@ -534,6 +534,7 @@ void tpm_get_timeouts(struct tpm_chip *chip)
        struct duration_t *duration_cap;
        ssize_t rc;
        u32 timeout;
+       unsigned int scale = 1;
 
        tpm_cmd.header.in = tpm_getcap_header;
        tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP;
@@ -545,24 +546,30 @@ void tpm_get_timeouts(struct tpm_chip *chip)
        if (rc)
                goto duration;
 
-       if (be32_to_cpu(tpm_cmd.header.out.length)
-           != 4 * sizeof(u32))
-               goto duration;
+       if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 ||
+           be32_to_cpu(tpm_cmd.header.out.length)
+           != sizeof(tpm_cmd.header.out) + sizeof(u32) + 4 * sizeof(u32))
+               return;
 
        timeout_cap = &tpm_cmd.params.getcap_out.cap.timeout;
        /* Don't overwrite default if value is 0 */
        timeout = be32_to_cpu(timeout_cap->a);
+       if (timeout && timeout < 1000) {
+               /* timeouts in msec rather usec */
+               scale = 1000;
+               chip->vendor.timeout_adjusted = true;
+       }
        if (timeout)
-               chip->vendor.timeout_a = usecs_to_jiffies(timeout);
+               chip->vendor.timeout_a = usecs_to_jiffies(timeout * scale);
        timeout = be32_to_cpu(timeout_cap->b);
        if (timeout)
-               chip->vendor.timeout_b = usecs_to_jiffies(timeout);
+               chip->vendor.timeout_b = usecs_to_jiffies(timeout * scale);
        timeout = be32_to_cpu(timeout_cap->c);
        if (timeout)
-               chip->vendor.timeout_c = usecs_to_jiffies(timeout);
+               chip->vendor.timeout_c = usecs_to_jiffies(timeout * scale);
        timeout = be32_to_cpu(timeout_cap->d);
        if (timeout)
-               chip->vendor.timeout_d = usecs_to_jiffies(timeout);
+               chip->vendor.timeout_d = usecs_to_jiffies(timeout * scale);
 
 duration:
        tpm_cmd.header.in = tpm_getcap_header;
@@ -575,23 +582,31 @@ duration:
        if (rc)
                return;
 
-       if (be32_to_cpu(tpm_cmd.header.out.return_code)
-           != 3 * sizeof(u32))
+       if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 ||
+           be32_to_cpu(tpm_cmd.header.out.length)
+           != sizeof(tpm_cmd.header.out) + sizeof(u32) + 3 * sizeof(u32))
                return;
+
        duration_cap = &tpm_cmd.params.getcap_out.cap.duration;
        chip->vendor.duration[TPM_SHORT] =
            usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_short));
+       chip->vendor.duration[TPM_MEDIUM] =
+           usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_medium));
+       chip->vendor.duration[TPM_LONG] =
+           usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_long));
+
        /* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above
         * value wrong and apparently reports msecs rather than usecs. So we
         * fix up the resulting too-small TPM_SHORT value to make things work.
+        * We also scale the TPM_MEDIUM and -_LONG values by 1000.
         */
-       if (chip->vendor.duration[TPM_SHORT] < (HZ/100))
+       if (chip->vendor.duration[TPM_SHORT] < (HZ / 100)) {
                chip->vendor.duration[TPM_SHORT] = HZ;
-
-       chip->vendor.duration[TPM_MEDIUM] =
-           usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_medium));
-       chip->vendor.duration[TPM_LONG] =
-           usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_long));
+               chip->vendor.duration[TPM_MEDIUM] *= 1000;
+               chip->vendor.duration[TPM_LONG] *= 1000;
+               chip->vendor.duration_adjusted = true;
+               dev_info(chip->dev, "Adjusting TPM timeout parameters.");
+       }
 }
 EXPORT_SYMBOL_GPL(tpm_get_timeouts);
 
@@ -600,7 +615,7 @@ void tpm_continue_selftest(struct tpm_chip *chip)
        u8 data[] = {
                0, 193,                 /* TPM_TAG_RQU_COMMAND */
                0, 0, 0, 10,            /* length */
-               0, 0, 0, 83,            /* TPM_ORD_GetCapability */
+               0, 0, 0, 83,            /* TPM_ORD_ContinueSelfTest */
        };
 
        tpm_transmit(chip, data, sizeof(data));
@@ -863,18 +878,24 @@ ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr,
        data = tpm_cmd.params.readpubek_out_buffer;
        str +=
            sprintf(str,
-                   "Algorithm: %02X %02X %02X %02X\nEncscheme: %02X %02X\n"
-                   "Sigscheme: %02X %02X\nParameters: %02X %02X %02X %02X"
-                   " %02X %02X %02X %02X %02X %02X %02X %02X\n"
-                   "Modulus length: %d\nModulus: \n",
-                   data[10], data[11], data[12], data[13], data[14],
-                   data[15], data[16], data[17], data[22], data[23],
-                   data[24], data[25], data[26], data[27], data[28],
-                   data[29], data[30], data[31], data[32], data[33],
-                   be32_to_cpu(*((__be32 *) (data + 34))));
+                   "Algorithm: %02X %02X %02X %02X\n"
+                   "Encscheme: %02X %02X\n"
+                   "Sigscheme: %02X %02X\n"
+                   "Parameters: %02X %02X %02X %02X "
+                   "%02X %02X %02X %02X "
+                   "%02X %02X %02X %02X\n"
+                   "Modulus length: %d\n"
+                   "Modulus:\n",
+                   data[0], data[1], data[2], data[3],
+                   data[4], data[5],
+                   data[6], data[7],
+                   data[12], data[13], data[14], data[15],
+                   data[16], data[17], data[18], data[19],
+                   data[20], data[21], data[22], data[23],
+                   be32_to_cpu(*((__be32 *) (data + 24))));
 
        for (i = 0; i < 256; i++) {
-               str += sprintf(str, "%02X ", data[i + 38]);
+               str += sprintf(str, "%02X ", data[i + 28]);
                if ((i + 1) % 16 == 0)
                        str += sprintf(str, "\n");
        }
@@ -937,6 +958,35 @@ ssize_t tpm_show_caps_1_2(struct device * dev,
 }
 EXPORT_SYMBOL_GPL(tpm_show_caps_1_2);
 
+ssize_t tpm_show_durations(struct device *dev, struct device_attribute *attr,
+                         char *buf)
+{
+       struct tpm_chip *chip = dev_get_drvdata(dev);
+
+       return sprintf(buf, "%d %d %d [%s]\n",
+                      jiffies_to_usecs(chip->vendor.duration[TPM_SHORT]),
+                      jiffies_to_usecs(chip->vendor.duration[TPM_MEDIUM]),
+                      jiffies_to_usecs(chip->vendor.duration[TPM_LONG]),
+                      chip->vendor.duration_adjusted
+                      ? "adjusted" : "original");
+}
+EXPORT_SYMBOL_GPL(tpm_show_durations);
+
+ssize_t tpm_show_timeouts(struct device *dev, struct device_attribute *attr,
+                         char *buf)
+{
+       struct tpm_chip *chip = dev_get_drvdata(dev);
+
+       return sprintf(buf, "%d %d %d %d [%s]\n",
+                      jiffies_to_usecs(chip->vendor.timeout_a),
+                      jiffies_to_usecs(chip->vendor.timeout_b),
+                      jiffies_to_usecs(chip->vendor.timeout_c),
+                      jiffies_to_usecs(chip->vendor.timeout_d),
+                      chip->vendor.timeout_adjusted
+                      ? "adjusted" : "original");
+}
+EXPORT_SYMBOL_GPL(tpm_show_timeouts);
+
 ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr,
                        const char *buf, size_t count)
 {
index 72ddb03..9c4163c 100644 (file)
@@ -56,6 +56,10 @@ extern ssize_t tpm_show_owned(struct device *, struct device_attribute *attr,
                                char *);
 extern ssize_t tpm_show_temp_deactivated(struct device *,
                                         struct device_attribute *attr, char *);
+extern ssize_t tpm_show_durations(struct device *,
+                                 struct device_attribute *attr, char *);
+extern ssize_t tpm_show_timeouts(struct device *,
+                                struct device_attribute *attr, char *);
 
 struct tpm_chip;
 
@@ -67,6 +71,7 @@ struct tpm_vendor_specific {
        unsigned long base;             /* TPM base address */
 
        int irq;
+       int probed_irq;
 
        int region_size;
        int have_region;
@@ -81,7 +86,9 @@ struct tpm_vendor_specific {
        struct list_head list;
        int locality;
        unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* jiffies */
+       bool timeout_adjusted;
        unsigned long duration[3]; /* jiffies */
+       bool duration_adjusted;
 
        wait_queue_head_t read_queue;
        wait_queue_head_t int_queue;
index a605cb7..82facc9 100644 (file)
@@ -330,12 +330,12 @@ static int __init init_nsc(void)
        pdev->dev.driver = &nsc_drv.driver;
        pdev->dev.release = tpm_nsc_remove;
 
-       if ((rc = platform_device_register(pdev)) < 0)
-               goto err_free_dev;
+       if ((rc = platform_device_add(pdev)) < 0)
+               goto err_put_dev;
 
        if (request_region(base, 2, "tpm_nsc0") == NULL ) {
                rc = -EBUSY;
-               goto err_unreg_dev;
+               goto err_del_dev;
        }
 
        if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_nsc))) {
@@ -382,10 +382,10 @@ static int __init init_nsc(void)
 
 err_rel_reg:
        release_region(base, 2);
-err_unreg_dev:
-       platform_device_unregister(pdev);
-err_free_dev:
-       kfree(pdev);
+err_del_dev:
+       platform_device_del(pdev);
+err_put_dev:
+       platform_device_put(pdev);
 err_unreg_drv:
        platform_driver_unregister(&nsc_drv);
        return rc;
index dd21df5..7fc2f10 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/interrupt.h>
 #include <linux/wait.h>
 #include <linux/acpi.h>
+#include <linux/freezer.h>
 #include "tpm.h"
 
 #define TPM_HEADER_SIZE 10
@@ -79,7 +80,7 @@ enum tis_defaults {
 static LIST_HEAD(tis_chips);
 static DEFINE_SPINLOCK(tis_lock);
 
-#ifdef CONFIG_ACPI
+#ifdef CONFIG_PNP
 static int is_itpm(struct pnp_dev *dev)
 {
        struct acpi_device *acpi = pnp_acpi_device(dev);
@@ -92,11 +93,6 @@ static int is_itpm(struct pnp_dev *dev)
 
        return 0;
 }
-#else
-static int is_itpm(struct pnp_dev *dev)
-{
-       return 0;
-}
 #endif
 
 static int check_locality(struct tpm_chip *chip, int l)
@@ -120,7 +116,7 @@ static void release_locality(struct tpm_chip *chip, int l, int force)
 
 static int request_locality(struct tpm_chip *chip, int l)
 {
-       unsigned long stop;
+       unsigned long stop, timeout;
        long rc;
 
        if (check_locality(chip, l) >= 0)
@@ -129,17 +125,25 @@ static int request_locality(struct tpm_chip *chip, int l)
        iowrite8(TPM_ACCESS_REQUEST_USE,
                 chip->vendor.iobase + TPM_ACCESS(l));
 
+       stop = jiffies + chip->vendor.timeout_a;
+
        if (chip->vendor.irq) {
+again:
+               timeout = stop - jiffies;
+               if ((long)timeout <= 0)
+                       return -1;
                rc = wait_event_interruptible_timeout(chip->vendor.int_queue,
                                                      (check_locality
                                                       (chip, l) >= 0),
-                                                     chip->vendor.timeout_a);
+                                                     timeout);
                if (rc > 0)
                        return l;
-
+               if (rc == -ERESTARTSYS && freezing(current)) {
+                       clear_thread_flag(TIF_SIGPENDING);
+                       goto again;
+               }
        } else {
                /* wait for burstcount */
-               stop = jiffies + chip->vendor.timeout_a;
                do {
                        if (check_locality(chip, l) >= 0)
                                return l;
@@ -196,15 +200,24 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
        if ((status & mask) == mask)
                return 0;
 
+       stop = jiffies + timeout;
+
        if (chip->vendor.irq) {
+again:
+               timeout = stop - jiffies;
+               if ((long)timeout <= 0)
+                       return -ETIME;
                rc = wait_event_interruptible_timeout(*queue,
                                                      ((tpm_tis_status
                                                        (chip) & mask) ==
                                                       mask), timeout);
                if (rc > 0)
                        return 0;
+               if (rc == -ERESTARTSYS && freezing(current)) {
+                       clear_thread_flag(TIF_SIGPENDING);
+                       goto again;
+               }
        } else {
-               stop = jiffies + timeout;
                do {
                        msleep(TPM_TIMEOUT);
                        status = tpm_tis_status(chip);
@@ -288,11 +301,10 @@ MODULE_PARM_DESC(itpm, "Force iTPM workarounds (found on some Lenovo laptops)");
  * tpm.c can skip polling for the data to be available as the interrupt is
  * waited for here
  */
-static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
+static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len)
 {
        int rc, status, burstcnt;
        size_t count = 0;
-       u32 ordinal;
 
        if (request_locality(chip, 0) < 0)
                return -EBUSY;
@@ -327,8 +339,7 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
 
        /* write last byte */
        iowrite8(buf[count],
-                chip->vendor.iobase +
-                TPM_DATA_FIFO(chip->vendor.locality));
+                chip->vendor.iobase + TPM_DATA_FIFO(chip->vendor.locality));
        wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
                      &chip->vendor.int_queue);
        status = tpm_tis_status(chip);
@@ -337,6 +348,28 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
                goto out_err;
        }
 
+       return 0;
+
+out_err:
+       tpm_tis_ready(chip);
+       release_locality(chip, chip->vendor.locality, 0);
+       return rc;
+}
+
+/*
+ * If interrupts are used (signaled by an irq set in the vendor structure)
+ * tpm.c can skip polling for the data to be available as the interrupt is
+ * waited for here
+ */
+static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
+{
+       int rc;
+       u32 ordinal;
+
+       rc = tpm_tis_send_data(chip, buf, len);
+       if (rc < 0)
+               return rc;
+
        /* go and do it */
        iowrite8(TPM_STS_GO,
                 chip->vendor.iobase + TPM_STS(chip->vendor.locality));
@@ -358,6 +391,47 @@ out_err:
        return rc;
 }
 
+/*
+ * Early probing for iTPM with STS_DATA_EXPECT flaw.
+ * Try sending command without itpm flag set and if that
+ * fails, repeat with itpm flag set.
+ */
+static int probe_itpm(struct tpm_chip *chip)
+{
+       int rc = 0;
+       u8 cmd_getticks[] = {
+               0x00, 0xc1, 0x00, 0x00, 0x00, 0x0a,
+               0x00, 0x00, 0x00, 0xf1
+       };
+       size_t len = sizeof(cmd_getticks);
+       int rem_itpm = itpm;
+
+       itpm = 0;
+
+       rc = tpm_tis_send_data(chip, cmd_getticks, len);
+       if (rc == 0)
+               goto out;
+
+       tpm_tis_ready(chip);
+       release_locality(chip, chip->vendor.locality, 0);
+
+       itpm = 1;
+
+       rc = tpm_tis_send_data(chip, cmd_getticks, len);
+       if (rc == 0) {
+               dev_info(chip->dev, "Detected an iTPM.\n");
+               rc = 1;
+       } else
+               rc = -EFAULT;
+
+out:
+       itpm = rem_itpm;
+       tpm_tis_ready(chip);
+       release_locality(chip, chip->vendor.locality, 0);
+
+       return rc;
+}
+
 static const struct file_operations tis_ops = {
        .owner = THIS_MODULE,
        .llseek = no_llseek,
@@ -376,6 +450,8 @@ static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated,
                   NULL);
 static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL);
 static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel);
+static DEVICE_ATTR(durations, S_IRUGO, tpm_show_durations, NULL);
+static DEVICE_ATTR(timeouts, S_IRUGO, tpm_show_timeouts, NULL);
 
 static struct attribute *tis_attrs[] = {
        &dev_attr_pubek.attr,
@@ -385,7 +461,9 @@ static struct attribute *tis_attrs[] = {
        &dev_attr_owned.attr,
        &dev_attr_temp_deactivated.attr,
        &dev_attr_caps.attr,
-       &dev_attr_cancel.attr, NULL,
+       &dev_attr_cancel.attr,
+       &dev_attr_durations.attr,
+       &dev_attr_timeouts.attr, NULL,
 };
 
 static struct attribute_group tis_attr_grp = {
@@ -416,7 +494,7 @@ static irqreturn_t tis_int_probe(int irq, void *dev_id)
        if (interrupt == 0)
                return IRQ_NONE;
 
-       chip->vendor.irq = irq;
+       chip->vendor.probed_irq = irq;
 
        /* Clear interrupts handled with TPM_EOI */
        iowrite32(interrupt,
@@ -464,7 +542,7 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
                        resource_size_t len, unsigned int irq)
 {
        u32 vendor, intfcaps, intmask;
-       int rc, i;
+       int rc, i, irq_s, irq_e;
        struct tpm_chip *chip;
 
        if (!(chip = tpm_register_hardware(dev, &tpm_tis)))
@@ -493,6 +571,14 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
                 "1.2 TPM (device-id 0x%X, rev-id %d)\n",
                 vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0)));
 
+       if (!itpm) {
+               itpm = probe_itpm(chip);
+               if (itpm < 0) {
+                       rc = -ENODEV;
+                       goto out_err;
+               }
+       }
+
        if (itpm)
                dev_info(dev, "Intel iTPM workaround enabled\n");
 
@@ -522,6 +608,9 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
        if (intfcaps & TPM_INTF_DATA_AVAIL_INT)
                dev_dbg(dev, "\tData Avail Int Support\n");
 
+       /* get the timeouts before testing for irqs */
+       tpm_get_timeouts(chip);
+
        /* INTERRUPT Setup */
        init_waitqueue_head(&chip->vendor.read_queue);
        init_waitqueue_head(&chip->vendor.int_queue);
@@ -540,13 +629,19 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
        if (interrupts)
                chip->vendor.irq = irq;
        if (interrupts && !chip->vendor.irq) {
-               chip->vendor.irq =
+               irq_s =
                    ioread8(chip->vendor.iobase +
                            TPM_INT_VECTOR(chip->vendor.locality));
+               if (irq_s) {
+                       irq_e = irq_s;
+               } else {
+                       irq_s = 3;
+                       irq_e = 15;
+               }
 
-               for (i = 3; i < 16 && chip->vendor.irq == 0; i++) {
+               for (i = irq_s; i <= irq_e && chip->vendor.irq == 0; i++) {
                        iowrite8(i, chip->vendor.iobase +
-                                   TPM_INT_VECTOR(chip->vendor.locality));
+                                TPM_INT_VECTOR(chip->vendor.locality));
                        if (request_irq
                            (i, tis_int_probe, IRQF_SHARED,
                             chip->vendor.miscdev.name, chip) != 0) {
@@ -568,9 +663,22 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
                                  chip->vendor.iobase +
                                  TPM_INT_ENABLE(chip->vendor.locality));
 
+                       chip->vendor.probed_irq = 0;
+
                        /* Generate Interrupts */
                        tpm_gen_interrupt(chip);
 
+                       chip->vendor.irq = chip->vendor.probed_irq;
+
+                       /* free_irq will call into tis_int_probe;
+                          clear all irqs we haven't seen while doing
+                          tpm_gen_interrupt */
+                       iowrite32(ioread32
+                                 (chip->vendor.iobase +
+                                  TPM_INT_STATUS(chip->vendor.locality)),
+                                 chip->vendor.iobase +
+                                 TPM_INT_STATUS(chip->vendor.locality));
+
                        /* Turn off */
                        iowrite32(intmask,
                                  chip->vendor.iobase +
@@ -609,7 +717,6 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
        list_add(&chip->vendor.list, &tis_chips);
        spin_unlock(&tis_lock);
 
-       tpm_get_timeouts(chip);
        tpm_continue_selftest(chip);
 
        return 0;
@@ -619,6 +726,29 @@ out_err:
        tpm_remove_hardware(chip->dev);
        return rc;
 }
+
+static void tpm_tis_reenable_interrupts(struct tpm_chip *chip)
+{
+       u32 intmask;
+
+       /* reenable interrupts that device may have lost or
+          BIOS/firmware may have disabled */
+       iowrite8(chip->vendor.irq, chip->vendor.iobase +
+                TPM_INT_VECTOR(chip->vendor.locality));
+
+       intmask =
+           ioread32(chip->vendor.iobase +
+                    TPM_INT_ENABLE(chip->vendor.locality));
+
+       intmask |= TPM_INTF_CMD_READY_INT
+           | TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_DATA_AVAIL_INT
+           | TPM_INTF_STS_VALID_INT | TPM_GLOBAL_INT_ENABLE;
+
+       iowrite32(intmask,
+                 chip->vendor.iobase + TPM_INT_ENABLE(chip->vendor.locality));
+}
+
+
 #ifdef CONFIG_PNP
 static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
                                      const struct pnp_device_id *pnp_id)
@@ -650,6 +780,9 @@ static int tpm_tis_pnp_resume(struct pnp_dev *dev)
        struct tpm_chip *chip = pnp_get_drvdata(dev);
        int ret;
 
+       if (chip->vendor.irq)
+               tpm_tis_reenable_interrupts(chip);
+
        ret = tpm_pm_resume(&dev->dev);
        if (!ret)
                tpm_continue_selftest(chip);
@@ -702,6 +835,11 @@ static int tpm_tis_suspend(struct platform_device *dev, pm_message_t msg)
 
 static int tpm_tis_resume(struct platform_device *dev)
 {
+       struct tpm_chip *chip = dev_get_drvdata(&dev->dev);
+
+       if (chip->vendor.irq)
+               tpm_tis_reenable_interrupts(chip);
+
        return tpm_pm_resume(&dev->dev);
 }
 static struct platform_driver tis_drv = {
index 2e5b204..d0183dd 100644 (file)
@@ -1,6 +1,6 @@
 /* n2_core.c: Niagara2 Stream Processing Unit (SPU) crypto support.
  *
- * Copyright (C) 2010 David S. Miller <davem@davemloft.net>
+ * Copyright (C) 2010, 2011 David S. Miller <davem@davemloft.net>
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -31,8 +31,8 @@
 #include "n2_core.h"
 
 #define DRV_MODULE_NAME                "n2_crypto"
-#define DRV_MODULE_VERSION     "0.1"
-#define DRV_MODULE_RELDATE     "April 29, 2010"
+#define DRV_MODULE_VERSION     "0.2"
+#define DRV_MODULE_RELDATE     "July 28, 2011"
 
 static char version[] __devinitdata =
        DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
@@ -1823,22 +1823,17 @@ static int spu_mdesc_scan(struct mdesc_handle *mdesc, struct platform_device *de
 static int __devinit get_irq_props(struct mdesc_handle *mdesc, u64 node,
                                   struct spu_mdesc_info *ip)
 {
-       const u64 *intr, *ino;
-       int intr_len, ino_len;
+       const u64 *ino;
+       int ino_len;
        int i;
 
-       intr = mdesc_get_property(mdesc, node, "intr", &intr_len);
-       if (!intr)
-               return -ENODEV;
-
        ino = mdesc_get_property(mdesc, node, "ino", &ino_len);
-       if (!ino)
+       if (!ino) {
+               printk("NO 'ino'\n");
                return -ENODEV;
+       }
 
-       if (intr_len != ino_len)
-               return -EINVAL;
-
-       ip->num_intrs = intr_len / sizeof(u64);
+       ip->num_intrs = ino_len / sizeof(u64);
        ip->ino_table = kzalloc((sizeof(struct ino_blob) *
                                 ip->num_intrs),
                                GFP_KERNEL);
@@ -1847,7 +1842,7 @@ static int __devinit get_irq_props(struct mdesc_handle *mdesc, u64 node,
 
        for (i = 0; i < ip->num_intrs; i++) {
                struct ino_blob *b = &ip->ino_table[i];
-               b->intr = intr[i];
+               b->intr = i + 1;
                b->ino = ino[i];
        }
 
@@ -2204,6 +2199,10 @@ static struct of_device_id n2_crypto_match[] = {
                .name = "n2cp",
                .compatible = "SUNW,vf-cwq",
        },
+       {
+               .name = "n2cp",
+               .compatible = "SUNW,kt-cwq",
+       },
        {},
 };
 
@@ -2228,6 +2227,10 @@ static struct of_device_id n2_mau_match[] = {
                .name = "ncp",
                .compatible = "SUNW,vf-mau",
        },
+       {
+               .name = "ncp",
+               .compatible = "SUNW,kt-mau",
+       },
        {},
 };
 
index 95a08a8..5745b7f 100644 (file)
@@ -271,7 +271,7 @@ int iser_send_command(struct iscsi_conn *conn,
        unsigned long edtl;
        int err;
        struct iser_data_buf *data_buf;
-       struct iscsi_cmd *hdr =  (struct iscsi_cmd *)task->hdr;
+       struct iscsi_scsi_req *hdr = (struct iscsi_scsi_req *)task->hdr;
        struct scsi_cmnd *sc  =  task->sc;
        struct iser_tx_desc *tx_desc = &iser_task->desc;
 
index 56abf3d..d728875 100644 (file)
@@ -154,10 +154,13 @@ static const struct xpad_device {
        { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", 0, XTYPE_XBOX },
        { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", 0, XTYPE_XBOX },
        { 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
+       { 0x12ab, 0x0004, "Honey Bee Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
+       { 0x0e6f, 0x0105, "HSM3 Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
        { 0x1430, 0x4748, "RedOctane Guitar Hero X-plorer", 0, XTYPE_XBOX360 },
        { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
        { 0x146b, 0x0601, "BigBen Interactive XBOX 360 Controller", 0, XTYPE_XBOX360 },
        { 0x045e, 0x028e, "Microsoft X-Box 360 pad", 0, XTYPE_XBOX360 },
+       { 0x1bad, 0x0002, "Harmonix Rock Band Guitar", 0, XTYPE_XBOX360 },
        { 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
        { 0x0f0d, 0x0016, "Hori Real Arcade Pro.EX", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
        { 0x0f0d, 0x000d, "Hori Fighting Stick EX2", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
@@ -236,9 +239,10 @@ static struct usb_device_id xpad_table [] = {
        XPAD_XBOX360_VENDOR(0x046d),            /* Logitech X-Box 360 style controllers */
        XPAD_XBOX360_VENDOR(0x0738),            /* Mad Catz X-Box 360 controllers */
        XPAD_XBOX360_VENDOR(0x0e6f),            /* 0x0e6f X-Box 360 controllers */
+       XPAD_XBOX360_VENDOR(0x12ab),            /* X-Box 360 dance pads */
        XPAD_XBOX360_VENDOR(0x1430),            /* RedOctane X-Box 360 controllers */
        XPAD_XBOX360_VENDOR(0x146b),            /* BigBen Interactive Controllers */
-       XPAD_XBOX360_VENDOR(0x1bad),            /* Rock Band Drums */
+       XPAD_XBOX360_VENDOR(0x1bad),            /* Harminix Rock Band Guitar and Drums */
        XPAD_XBOX360_VENDOR(0x0f0d),            /* Hori Controllers */
        { }
 };
@@ -545,7 +549,7 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
        struct usb_endpoint_descriptor *ep_irq_out;
        int error;
 
-       if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX)
+       if (xpad->xtype == XTYPE_UNKNOWN)
                return 0;
 
        xpad->odata = usb_alloc_coherent(xpad->udev, XPAD_PKT_LEN,
@@ -579,13 +583,13 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
 
 static void xpad_stop_output(struct usb_xpad *xpad)
 {
-       if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX)
+       if (xpad->xtype != XTYPE_UNKNOWN)
                usb_kill_urb(xpad->irq_out);
 }
 
 static void xpad_deinit_output(struct usb_xpad *xpad)
 {
-       if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX) {
+       if (xpad->xtype != XTYPE_UNKNOWN) {
                usb_free_urb(xpad->irq_out);
                usb_free_coherent(xpad->udev, XPAD_PKT_LEN,
                                xpad->odata, xpad->odata_dma);
@@ -632,6 +636,23 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect
 
                        return usb_submit_urb(xpad->irq_out, GFP_ATOMIC);
 
+               case XTYPE_XBOX360W:
+                       xpad->odata[0] = 0x00;
+                       xpad->odata[1] = 0x01;
+                       xpad->odata[2] = 0x0F;
+                       xpad->odata[3] = 0xC0;
+                       xpad->odata[4] = 0x00;
+                       xpad->odata[5] = strong / 256;
+                       xpad->odata[6] = weak / 256;
+                       xpad->odata[7] = 0x00;
+                       xpad->odata[8] = 0x00;
+                       xpad->odata[9] = 0x00;
+                       xpad->odata[10] = 0x00;
+                       xpad->odata[11] = 0x00;
+                       xpad->irq_out->transfer_buffer_length = 12;
+
+                       return usb_submit_urb(xpad->irq_out, GFP_ATOMIC);
+
                default:
                        dbg("%s - rumble command sent to unsupported xpad type: %d",
                                __func__, xpad->xtype);
@@ -644,7 +665,7 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect
 
 static int xpad_init_ff(struct usb_xpad *xpad)
 {
-       if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX)
+       if (xpad->xtype == XTYPE_UNKNOWN)
                return 0;
 
        input_set_capability(xpad->dev, EV_FF, FF_RUMBLE);
index af45d27..7b404e5 100644 (file)
@@ -9,7 +9,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/version.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
index 6315986..c770826 100644 (file)
@@ -8,7 +8,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/version.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
index 11478eb..19cfc0c 100644 (file)
@@ -1578,14 +1578,14 @@ static int __init atkbd_setup_forced_release(const struct dmi_system_id *id)
        atkbd_platform_fixup = atkbd_apply_forced_release_keylist;
        atkbd_platform_fixup_data = id->driver_data;
 
-       return 0;
+       return 1;
 }
 
 static int __init atkbd_setup_scancode_fixup(const struct dmi_system_id *id)
 {
        atkbd_platform_scancode_fixup = id->driver_data;
 
-       return 0;
+       return 1;
 }
 
 static const struct dmi_system_id atkbd_dmi_quirk_table[] __initconst = {
index 6e6145b..ce281d1 100644 (file)
@@ -2,6 +2,7 @@
  * Driver for keys on GPIO lines capable of generating interrupts.
  *
  * Copyright 2005 Phil Blundell
+ * Copyright 2010, 2011 David Jander <david@protonic.nl>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -25,6 +26,8 @@
 #include <linux/gpio_keys.h>
 #include <linux/workqueue.h>
 #include <linux/gpio.h>
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
 
 struct gpio_button_data {
        struct gpio_keys_button *button;
@@ -415,7 +418,7 @@ static int __devinit gpio_keys_setup_key(struct platform_device *pdev,
        if (!button->can_disable)
                irqflags |= IRQF_SHARED;
 
-       error = request_any_context_irq(irq, gpio_keys_isr, irqflags, desc, bdata);
+       error = request_threaded_irq(irq, NULL, gpio_keys_isr, irqflags, desc, bdata);
        if (error < 0) {
                dev_err(dev, "Unable to claim irq %d; error %d\n",
                        irq, error);
@@ -445,15 +448,120 @@ static void gpio_keys_close(struct input_dev *input)
                ddata->disable(input->dev.parent);
 }
 
+/*
+ * Handlers for alternative sources of platform_data
+ */
+#ifdef CONFIG_OF
+/*
+ * Translate OpenFirmware node properties into platform_data
+ */
+static int gpio_keys_get_devtree_pdata(struct device *dev,
+                           struct gpio_keys_platform_data *pdata)
+{
+       struct device_node *node, *pp;
+       int i;
+       struct gpio_keys_button *buttons;
+       const u32 *reg;
+       int len;
+
+       node = dev->of_node;
+       if (node == NULL)
+               return -ENODEV;
+
+       memset(pdata, 0, sizeof *pdata);
+
+       pdata->rep = !!of_get_property(node, "autorepeat", &len);
+
+       /* First count the subnodes */
+       pdata->nbuttons = 0;
+       pp = NULL;
+       while ((pp = of_get_next_child(node, pp)))
+               pdata->nbuttons++;
+
+       if (pdata->nbuttons == 0)
+               return -ENODEV;
+
+       buttons = kzalloc(pdata->nbuttons * (sizeof *buttons), GFP_KERNEL);
+       if (!buttons)
+               return -ENODEV;
+
+       pp = NULL;
+       i = 0;
+       while ((pp = of_get_next_child(node, pp))) {
+               enum of_gpio_flags flags;
+
+               if (!of_find_property(pp, "gpios", NULL)) {
+                       pdata->nbuttons--;
+                       dev_warn(dev, "Found button without gpios\n");
+                       continue;
+               }
+               buttons[i].gpio = of_get_gpio_flags(pp, 0, &flags);
+               buttons[i].active_low = flags & OF_GPIO_ACTIVE_LOW;
+
+               reg = of_get_property(pp, "linux,code", &len);
+               if (!reg) {
+                       dev_err(dev, "Button without keycode: 0x%x\n", buttons[i].gpio);
+                       goto out_fail;
+               }
+               buttons[i].code = be32_to_cpup(reg);
+
+               buttons[i].desc = of_get_property(pp, "label", &len);
+
+               reg = of_get_property(pp, "linux,input-type", &len);
+               buttons[i].type = reg ? be32_to_cpup(reg) : EV_KEY;
+
+               buttons[i].wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL);
+
+               reg = of_get_property(pp, "debounce-interval", &len);
+               buttons[i].debounce_interval = reg ? be32_to_cpup(reg) : 5;
+
+               i++;
+       }
+
+       pdata->buttons = buttons;
+
+       return 0;
+
+out_fail:
+       kfree(buttons);
+       return -ENODEV;
+}
+
+static struct of_device_id gpio_keys_of_match[] = {
+       { .compatible = "gpio-keys", },
+       { },
+};
+MODULE_DEVICE_TABLE(of, gpio_keys_of_match);
+
+#else
+
+static int gpio_keys_get_devtree_pdata(struct device *dev,
+                           struct gpio_keys_platform_data *altp)
+{
+       return -ENODEV;
+}
+
+#define gpio_keys_of_match NULL
+
+#endif
+
 static int __devinit gpio_keys_probe(struct platform_device *pdev)
 {
        struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
        struct gpio_keys_drvdata *ddata;
        struct device *dev = &pdev->dev;
+       struct gpio_keys_platform_data alt_pdata;
        struct input_dev *input;
        int i, error;
        int wakeup = 0;
 
+       if (!pdata) {
+               error = gpio_keys_get_devtree_pdata(dev, &alt_pdata);
+               if (error)
+                       return error;
+               pdata = &alt_pdata;
+       }
+
        ddata = kzalloc(sizeof(struct gpio_keys_drvdata) +
                        pdata->nbuttons * sizeof(struct gpio_button_data),
                        GFP_KERNEL);
@@ -544,13 +652,15 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
  fail1:
        input_free_device(input);
        kfree(ddata);
+       /* If we have no platform_data, we allocated buttons dynamically. */
+       if (!pdev->dev.platform_data)
+               kfree(pdata->buttons);
 
        return error;
 }
 
 static int __devexit gpio_keys_remove(struct platform_device *pdev)
 {
-       struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
        struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev);
        struct input_dev *input = ddata->input;
        int i;
@@ -559,31 +669,39 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev)
 
        device_init_wakeup(&pdev->dev, 0);
 
-       for (i = 0; i < pdata->nbuttons; i++) {
-               int irq = gpio_to_irq(pdata->buttons[i].gpio);
+       for (i = 0; i < ddata->n_buttons; i++) {
+               int irq = gpio_to_irq(ddata->data[i].button->gpio);
                free_irq(irq, &ddata->data[i]);
                if (ddata->data[i].timer_debounce)
                        del_timer_sync(&ddata->data[i].timer);
                cancel_work_sync(&ddata->data[i].work);
-               gpio_free(pdata->buttons[i].gpio);
+               gpio_free(ddata->data[i].button->gpio);
        }
 
        input_unregister_device(input);
 
+       /*
+        * If we had no platform_data, we allocated buttons dynamically, and
+        * must free them here. ddata->data[0].button is the pointer to the
+        * beginning of the allocated array.
+        */
+       if (!pdev->dev.platform_data)
+               kfree(ddata->data[0].button);
+
+       kfree(ddata);
+
        return 0;
 }
 
-
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int gpio_keys_suspend(struct device *dev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
+       struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev);
        int i;
 
-       if (device_may_wakeup(&pdev->dev)) {
-               for (i = 0; i < pdata->nbuttons; i++) {
-                       struct gpio_keys_button *button = &pdata->buttons[i];
+       if (device_may_wakeup(dev)) {
+               for (i = 0; i < ddata->n_buttons; i++) {
+                       struct gpio_keys_button *button = ddata->data[i].button;
                        if (button->wakeup) {
                                int irq = gpio_to_irq(button->gpio);
                                enable_irq_wake(irq);
@@ -596,15 +714,13 @@ static int gpio_keys_suspend(struct device *dev)
 
 static int gpio_keys_resume(struct device *dev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev);
-       struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
+       struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev);
        int i;
 
-       for (i = 0; i < pdata->nbuttons; i++) {
+       for (i = 0; i < ddata->n_buttons; i++) {
 
-               struct gpio_keys_button *button = &pdata->buttons[i];
-               if (button->wakeup && device_may_wakeup(&pdev->dev)) {
+               struct gpio_keys_button *button = ddata->data[i].button;
+               if (button->wakeup && device_may_wakeup(dev)) {
                        int irq = gpio_to_irq(button->gpio);
                        disable_irq_wake(irq);
                }
@@ -615,22 +731,18 @@ static int gpio_keys_resume(struct device *dev)
 
        return 0;
 }
-
-static const struct dev_pm_ops gpio_keys_pm_ops = {
-       .suspend        = gpio_keys_suspend,
-       .resume         = gpio_keys_resume,
-};
 #endif
 
+static SIMPLE_DEV_PM_OPS(gpio_keys_pm_ops, gpio_keys_suspend, gpio_keys_resume);
+
 static struct platform_driver gpio_keys_device_driver = {
        .probe          = gpio_keys_probe,
        .remove         = __devexit_p(gpio_keys_remove),
        .driver         = {
                .name   = "gpio-keys",
                .owner  = THIS_MODULE,
-#ifdef CONFIG_PM
                .pm     = &gpio_keys_pm_ops,
-#endif
+               .of_match_table = gpio_keys_of_match,
        }
 };
 
@@ -644,10 +756,10 @@ static void __exit gpio_keys_exit(void)
        platform_driver_unregister(&gpio_keys_device_driver);
 }
 
-module_init(gpio_keys_init);
+late_initcall(gpio_keys_init);
 module_exit(gpio_keys_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Phil Blundell <pb@handhelds.org>");
-MODULE_DESCRIPTION("Keyboard driver for CPU GPIOs");
+MODULE_DESCRIPTION("Keyboard driver for GPIOs");
 MODULE_ALIAS("platform:gpio-keys");
index 71f744a..ab0acaf 100644 (file)
@@ -146,7 +146,6 @@ struct lm8323_chip {
        /* device lock */
        struct mutex            lock;
        struct i2c_client       *client;
-       struct work_struct      work;
        struct input_dev        *idev;
        bool                    kp_enabled;
        bool                    pm_suspend;
@@ -162,7 +161,6 @@ struct lm8323_chip {
 
 #define client_to_lm8323(c)    container_of(c, struct lm8323_chip, client)
 #define dev_to_lm8323(d)       container_of(d, struct lm8323_chip, client->dev)
-#define work_to_lm8323(w)      container_of(w, struct lm8323_chip, work)
 #define cdev_to_pwm(c)         container_of(c, struct lm8323_pwm, cdev)
 #define work_to_pwm(w)         container_of(w, struct lm8323_pwm, work)
 
@@ -375,9 +373,9 @@ static void pwm_done(struct lm8323_pwm *pwm)
  * Bottom half: handle the interrupt by posting key events, or dealing with
  * errors appropriately.
  */
-static void lm8323_work(struct work_struct *work)
+static irqreturn_t lm8323_irq(int irq, void *_lm)
 {
-       struct lm8323_chip *lm = work_to_lm8323(work);
+       struct lm8323_chip *lm = _lm;
        u8 ints;
        int i;
 
@@ -409,16 +407,6 @@ static void lm8323_work(struct work_struct *work)
        }
 
        mutex_unlock(&lm->lock);
-}
-
-/*
- * We cannot use I2C in interrupt context, so we just schedule work.
- */
-static irqreturn_t lm8323_irq(int irq, void *data)
-{
-       struct lm8323_chip *lm = data;
-
-       schedule_work(&lm->work);
 
        return IRQ_HANDLED;
 }
@@ -675,7 +663,6 @@ static int __devinit lm8323_probe(struct i2c_client *client,
        lm->client = client;
        lm->idev = idev;
        mutex_init(&lm->lock);
-       INIT_WORK(&lm->work, lm8323_work);
 
        lm->size_x = pdata->size_x;
        lm->size_y = pdata->size_y;
@@ -746,9 +733,8 @@ static int __devinit lm8323_probe(struct i2c_client *client,
                goto fail3;
        }
 
-       err = request_irq(client->irq, lm8323_irq,
-                         IRQF_TRIGGER_FALLING | IRQF_DISABLED,
-                         "lm8323", lm);
+       err = request_threaded_irq(client->irq, NULL, lm8323_irq,
+                         IRQF_TRIGGER_LOW|IRQF_ONESHOT, "lm8323", lm);
        if (err) {
                dev_err(&client->dev, "could not get IRQ %d\n", client->irq);
                goto fail4;
@@ -783,7 +769,6 @@ static int __devexit lm8323_remove(struct i2c_client *client)
 
        disable_irq_wake(client->irq);
        free_irq(client->irq, lm);
-       cancel_work_sync(&lm->work);
 
        input_unregister_device(lm->idev);
 
index 0a9e811..1c1615d 100644 (file)
  * enabled capacitance sensing inputs and its run/suspend mode.
  */
 #define ELECTRODE_CONF_ADDR            0x5e
+#define ELECTRODE_CONF_QUICK_CHARGE    0x80
 #define AUTO_CONFIG_CTRL_ADDR          0x7b
 #define AUTO_CONFIG_USL_ADDR           0x7d
 #define AUTO_CONFIG_LSL_ADDR           0x7e
 #define AUTO_CONFIG_TL_ADDR            0x7f
 
 /* Threshold of touch/release trigger */
-#define TOUCH_THRESHOLD                        0x0f
-#define RELEASE_THRESHOLD              0x0a
+#define TOUCH_THRESHOLD                        0x08
+#define RELEASE_THRESHOLD              0x05
 /* Masks for touch and release triggers */
 #define TOUCH_STATUS_MASK              0xfff
 /* MPR121 has 12 keys */
@@ -127,7 +128,7 @@ static int __devinit mpr121_phys_init(const struct mpr121_platform_data *pdata,
                                      struct i2c_client *client)
 {
        const struct mpr121_init_register *reg;
-       unsigned char usl, lsl, tl;
+       unsigned char usl, lsl, tl, eleconf;
        int i, t, vdd, ret;
 
        /* Set up touch/release threshold for ele0-ele11 */
@@ -163,8 +164,15 @@ static int __devinit mpr121_phys_init(const struct mpr121_platform_data *pdata,
        ret = i2c_smbus_write_byte_data(client, AUTO_CONFIG_USL_ADDR, usl);
        ret |= i2c_smbus_write_byte_data(client, AUTO_CONFIG_LSL_ADDR, lsl);
        ret |= i2c_smbus_write_byte_data(client, AUTO_CONFIG_TL_ADDR, tl);
+
+       /*
+        * Quick charge bit will let the capacitive charge to ready
+        * state quickly, or the buttons may not function after system
+        * boot.
+        */
+       eleconf = mpr121->keycount | ELECTRODE_CONF_QUICK_CHARGE;
        ret |= i2c_smbus_write_byte_data(client, ELECTRODE_CONF_ADDR,
-                                        mpr121->keycount);
+                                        eleconf);
        if (ret != 0)
                goto err_i2c_write;
 
index 6229c3e..e7cc51d 100644 (file)
@@ -700,9 +700,9 @@ static int __devinit pmic8xxx_kp_probe(struct platform_device *pdev)
        return 0;
 
 err_pmic_reg_read:
-       free_irq(kp->key_stuck_irq, NULL);
+       free_irq(kp->key_stuck_irq, kp);
 err_req_stuck_irq:
-       free_irq(kp->key_sense_irq, NULL);
+       free_irq(kp->key_sense_irq, kp);
 err_gpio_config:
 err_get_irq:
        input_free_device(kp->input);
@@ -717,8 +717,8 @@ static int __devexit pmic8xxx_kp_remove(struct platform_device *pdev)
        struct pmic8xxx_kp *kp = platform_get_drvdata(pdev);
 
        device_init_wakeup(&pdev->dev, 0);
-       free_irq(kp->key_stuck_irq, NULL);
-       free_irq(kp->key_sense_irq, NULL);
+       free_irq(kp->key_stuck_irq, kp);
+       free_irq(kp->key_sense_irq, kp);
        input_unregister_device(kp->input);
        kfree(kp);
 
index ca7b891..b21bf5b 100644 (file)
@@ -239,8 +239,6 @@ static int __devexit qt1070_remove(struct i2c_client *client)
        input_unregister_device(data->input);
        kfree(data);
 
-       i2c_set_clientdata(client, NULL);
-
        return 0;
 }
 
index 6876700..934aeb5 100644 (file)
@@ -291,7 +291,7 @@ static int __devexit sh_keysc_remove(struct platform_device *pdev)
        return 0;
 }
 
-#if CONFIG_PM_SLEEP
+#ifdef CONFIG_PM_SLEEP
 static int sh_keysc_suspend(struct device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev);
index 2b3b73e..da3828f 100644 (file)
@@ -657,7 +657,7 @@ static int __devinit tegra_kbc_probe(struct platform_device *pdev)
 
        input_set_drvdata(input_dev, kbc);
 
-       input_dev->evbit[0] = BIT_MASK(EV_KEY);
+       input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
        input_set_capability(input_dev, EV_MSC, MSC_SCAN);
 
        input_dev->keycode = kbc->keycode;
index c8f097a..1c58681 100644 (file)
@@ -337,5 +337,5 @@ module_exit(keypad_exit);
 
 MODULE_AUTHOR("Cyril Chemparathy");
 MODULE_DESCRIPTION("TNETV107X Keypad Driver");
-MODULE_ALIAS("platform: tnetv107x-keypad");
+MODULE_ALIAS("platform:tnetv107x-keypad");
 MODULE_LICENSE("GPL");
index d1bf872..c9104bb 100644 (file)
@@ -100,6 +100,27 @@ config INPUT_MAX8925_ONKEY
          To compile this driver as a module, choose M here: the module
          will be called max8925_onkey.
 
+config INPUT_MMA8450
+       tristate "MMA8450 - Freescale's 3-Axis, 8/12-bit Digital Accelerometer"
+       depends on I2C
+       select INPUT_POLLDEV
+       help
+         Say Y here if you want to support Freescale's MMA8450 Accelerometer
+         through I2C interface.
+
+         To compile this driver as a module, choose M here: the
+         module will be called mma8450.
+
+config INPUT_MPU3050
+       tristate "MPU3050 Triaxial gyroscope sensor"
+       depends on I2C
+       help
+         Say Y here if you want to support InvenSense MPU3050
+         connected via an I2C bus.
+
+         To compile this driver as a module, choose M here: the
+         module will be called mpu3050.
+
 config INPUT_APANEL
        tristate "Fujitsu Lifebook Application Panel buttons"
        depends on X86 && I2C && LEDS_CLASS
@@ -209,6 +230,23 @@ config INPUT_KEYSPAN_REMOTE
          To compile this driver as a module, choose M here: the module will
          be called keyspan_remote.
 
+config INPUT_KXTJ9
+       tristate "Kionix KXTJ9 tri-axis digital accelerometer"
+       depends on I2C
+       help
+         Say Y here to enable support for the Kionix KXTJ9 digital tri-axis
+         accelerometer.
+
+         To compile this driver as a module, choose M here: the module will
+         be called kxtj9.
+
+config INPUT_KXTJ9_POLLED_MODE
+       bool "Enable polling mode support"
+       depends on INPUT_KXTJ9
+       select INPUT_POLLDEV
+       help
+         Say Y here if you need accelerometer to work in polling mode.
+
 config INPUT_POWERMATE
        tristate "Griffin PowerMate and Contour Jog support"
        depends on USB_ARCH_HAS_HCD
index 4da7c3a..299ad5e 100644 (file)
@@ -25,8 +25,11 @@ obj-$(CONFIG_INPUT_DM355EVM)         += dm355evm_keys.o
 obj-$(CONFIG_HP_SDC_RTC)               += hp_sdc_rtc.o
 obj-$(CONFIG_INPUT_IXP4XX_BEEPER)      += ixp4xx-beeper.o
 obj-$(CONFIG_INPUT_KEYSPAN_REMOTE)     += keyspan_remote.o
+obj-$(CONFIG_INPUT_KXTJ9)              += kxtj9.o
 obj-$(CONFIG_INPUT_M68K_BEEP)          += m68kspkr.o
 obj-$(CONFIG_INPUT_MAX8925_ONKEY)      += max8925_onkey.o
+obj-$(CONFIG_INPUT_MMA8450)            += mma8450.o
+obj-$(CONFIG_INPUT_MPU3050)            += mpu3050.o
 obj-$(CONFIG_INPUT_PCAP)               += pcap_keys.o
 obj-$(CONFIG_INPUT_PCF50633_PMU)       += pcf50633-input.o
 obj-$(CONFIG_INPUT_PCF8574)            += pcf8574_keypad.o
@@ -46,4 +49,3 @@ obj-$(CONFIG_INPUT_WISTRON_BTNS)      += wistron_btns.o
 obj-$(CONFIG_INPUT_WM831X_ON)          += wm831x-on.o
 obj-$(CONFIG_INPUT_XEN_KBDDEV_FRONTEND)        += xen-kbdfront.o
 obj-$(CONFIG_INPUT_YEALINK)            += yealink.o
-
index 4f72bdd..d00edc9 100644 (file)
@@ -6,7 +6,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/version.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c
new file mode 100644 (file)
index 0000000..c456f63
--- /dev/null
@@ -0,0 +1,671 @@
+/*
+ * Copyright (C) 2011 Kionix, Inc.
+ * Written by Chris Hudson <chudson@kionix.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307, USA
+ */
+
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/input/kxtj9.h>
+#include <linux/input-polldev.h>
+
+#define NAME                   "kxtj9"
+#define G_MAX                  8000
+/* OUTPUT REGISTERS */
+#define XOUT_L                 0x06
+#define WHO_AM_I               0x0F
+/* CONTROL REGISTERS */
+#define INT_REL                        0x1A
+#define CTRL_REG1              0x1B
+#define INT_CTRL1              0x1E
+#define DATA_CTRL              0x21
+/* CONTROL REGISTER 1 BITS */
+#define PC1_OFF                        0x7F
+#define PC1_ON                 (1 << 7)
+/* Data ready funtion enable bit: set during probe if using irq mode */
+#define DRDYE                  (1 << 5)
+/* INTERRUPT CONTROL REGISTER 1 BITS */
+/* Set these during probe if using irq mode */
+#define KXTJ9_IEL              (1 << 3)
+#define KXTJ9_IEA              (1 << 4)
+#define KXTJ9_IEN              (1 << 5)
+/* INPUT_ABS CONSTANTS */
+#define FUZZ                   3
+#define FLAT                   3
+/* RESUME STATE INDICES */
+#define RES_DATA_CTRL          0
+#define RES_CTRL_REG1          1
+#define RES_INT_CTRL1          2
+#define RESUME_ENTRIES         3
+
+/*
+ * The following table lists the maximum appropriate poll interval for each
+ * available output data rate.
+ */
+static const struct {
+       unsigned int cutoff;
+       u8 mask;
+} kxtj9_odr_table[] = {
+       { 3,    ODR800F },
+       { 5,    ODR400F },
+       { 10,   ODR200F },
+       { 20,   ODR100F },
+       { 40,   ODR50F  },
+       { 80,   ODR25F  },
+       { 0,    ODR12_5F},
+};
+
+struct kxtj9_data {
+       struct i2c_client *client;
+       struct kxtj9_platform_data pdata;
+       struct input_dev *input_dev;
+#ifdef CONFIG_INPUT_KXTJ9_POLLED_MODE
+       struct input_polled_dev *poll_dev;
+#endif
+       unsigned int last_poll_interval;
+       u8 shift;
+       u8 ctrl_reg1;
+       u8 data_ctrl;
+       u8 int_ctrl;
+};
+
+static int kxtj9_i2c_read(struct kxtj9_data *tj9, u8 addr, u8 *data, int len)
+{
+       struct i2c_msg msgs[] = {
+               {
+                       .addr = tj9->client->addr,
+                       .flags = tj9->client->flags,
+                       .len = 1,
+                       .buf = &addr,
+               },
+               {
+                       .addr = tj9->client->addr,
+                       .flags = tj9->client->flags | I2C_M_RD,
+                       .len = len,
+                       .buf = data,
+               },
+       };
+
+       return i2c_transfer(tj9->client->adapter, msgs, 2);
+}
+
+static void kxtj9_report_acceleration_data(struct kxtj9_data *tj9)
+{
+       s16 acc_data[3]; /* Data bytes from hardware xL, xH, yL, yH, zL, zH */
+       s16 x, y, z;
+       int err;
+
+       err = kxtj9_i2c_read(tj9, XOUT_L, (u8 *)acc_data, 6);
+       if (err < 0)
+               dev_err(&tj9->client->dev, "accelerometer data read failed\n");
+
+       x = le16_to_cpu(acc_data[tj9->pdata.axis_map_x]) >> tj9->shift;
+       y = le16_to_cpu(acc_data[tj9->pdata.axis_map_y]) >> tj9->shift;
+       z = le16_to_cpu(acc_data[tj9->pdata.axis_map_z]) >> tj9->shift;
+
+       input_report_abs(tj9->input_dev, ABS_X, tj9->pdata.negate_x ? -x : x);
+       input_report_abs(tj9->input_dev, ABS_Y, tj9->pdata.negate_y ? -y : y);
+       input_report_abs(tj9->input_dev, ABS_Z, tj9->pdata.negate_z ? -z : z);
+       input_sync(tj9->input_dev);
+}
+
+static irqreturn_t kxtj9_isr(int irq, void *dev)
+{
+       struct kxtj9_data *tj9 = dev;
+       int err;
+
+       /* data ready is the only possible interrupt type */
+       kxtj9_report_acceleration_data(tj9);
+
+       err = i2c_smbus_read_byte_data(tj9->client, INT_REL);
+       if (err < 0)
+               dev_err(&tj9->client->dev,
+                       "error clearing interrupt status: %d\n", err);
+
+       return IRQ_HANDLED;
+}
+
+static int kxtj9_update_g_range(struct kxtj9_data *tj9, u8 new_g_range)
+{
+       switch (new_g_range) {
+       case KXTJ9_G_2G:
+               tj9->shift = 4;
+               break;
+       case KXTJ9_G_4G:
+               tj9->shift = 3;
+               break;
+       case KXTJ9_G_8G:
+               tj9->shift = 2;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       tj9->ctrl_reg1 &= 0xe7;
+       tj9->ctrl_reg1 |= new_g_range;
+
+       return 0;
+}
+
+static int kxtj9_update_odr(struct kxtj9_data *tj9, unsigned int poll_interval)
+{
+       int err;
+       int i;
+
+       /* Use the lowest ODR that can support the requested poll interval */
+       for (i = 0; i < ARRAY_SIZE(kxtj9_odr_table); i++) {
+               tj9->data_ctrl = kxtj9_odr_table[i].mask;
+               if (poll_interval < kxtj9_odr_table[i].cutoff)
+                       break;
+       }
+
+       err = i2c_smbus_write_byte_data(tj9->client, CTRL_REG1, 0);
+       if (err < 0)
+               return err;
+
+       err = i2c_smbus_write_byte_data(tj9->client, DATA_CTRL, tj9->data_ctrl);
+       if (err < 0)
+               return err;
+
+       err = i2c_smbus_write_byte_data(tj9->client, CTRL_REG1, tj9->ctrl_reg1);
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
+static int kxtj9_device_power_on(struct kxtj9_data *tj9)
+{
+       if (tj9->pdata.power_on)
+               return tj9->pdata.power_on();
+
+       return 0;
+}
+
+static void kxtj9_device_power_off(struct kxtj9_data *tj9)
+{
+       int err;
+
+       tj9->ctrl_reg1 &= PC1_OFF;
+       err = i2c_smbus_write_byte_data(tj9->client, CTRL_REG1, tj9->ctrl_reg1);
+       if (err < 0)
+               dev_err(&tj9->client->dev, "soft power off failed\n");
+
+       if (tj9->pdata.power_off)
+               tj9->pdata.power_off();
+}
+
+static int kxtj9_enable(struct kxtj9_data *tj9)
+{
+       int err;
+
+       err = kxtj9_device_power_on(tj9);
+       if (err < 0)
+               return err;
+
+       /* ensure that PC1 is cleared before updating control registers */
+       err = i2c_smbus_write_byte_data(tj9->client, CTRL_REG1, 0);
+       if (err < 0)
+               return err;
+
+       /* only write INT_CTRL_REG1 if in irq mode */
+       if (tj9->client->irq) {
+               err = i2c_smbus_write_byte_data(tj9->client,
+                                               INT_CTRL1, tj9->int_ctrl);
+               if (err < 0)
+                       return err;
+       }
+
+       err = kxtj9_update_g_range(tj9, tj9->pdata.g_range);
+       if (err < 0)
+               return err;
+
+       /* turn on outputs */
+       tj9->ctrl_reg1 |= PC1_ON;
+       err = i2c_smbus_write_byte_data(tj9->client, CTRL_REG1, tj9->ctrl_reg1);
+       if (err < 0)
+               return err;
+
+       err = kxtj9_update_odr(tj9, tj9->last_poll_interval);
+       if (err < 0)
+               return err;
+
+       /* clear initial interrupt if in irq mode */
+       if (tj9->client->irq) {
+               err = i2c_smbus_read_byte_data(tj9->client, INT_REL);
+               if (err < 0) {
+                       dev_err(&tj9->client->dev,
+                               "error clearing interrupt: %d\n", err);
+                       goto fail;
+               }
+       }
+
+       return 0;
+
+fail:
+       kxtj9_device_power_off(tj9);
+       return err;
+}
+
+static void kxtj9_disable(struct kxtj9_data *tj9)
+{
+       kxtj9_device_power_off(tj9);
+}
+
+static int kxtj9_input_open(struct input_dev *input)
+{
+       struct kxtj9_data *tj9 = input_get_drvdata(input);
+
+       return kxtj9_enable(tj9);
+}
+
+static void kxtj9_input_close(struct input_dev *dev)
+{
+       struct kxtj9_data *tj9 = input_get_drvdata(dev);
+
+       kxtj9_disable(tj9);
+}
+
+static void __devinit kxtj9_init_input_device(struct kxtj9_data *tj9,
+                                             struct input_dev *input_dev)
+{
+       __set_bit(EV_ABS, input_dev->evbit);
+       input_set_abs_params(input_dev, ABS_X, -G_MAX, G_MAX, FUZZ, FLAT);
+       input_set_abs_params(input_dev, ABS_Y, -G_MAX, G_MAX, FUZZ, FLAT);
+       input_set_abs_params(input_dev, ABS_Z, -G_MAX, G_MAX, FUZZ, FLAT);
+
+       input_dev->name = "kxtj9_accel";
+       input_dev->id.bustype = BUS_I2C;
+       input_dev->dev.parent = &tj9->client->dev;
+}
+
+static int __devinit kxtj9_setup_input_device(struct kxtj9_data *tj9)
+{
+       struct input_dev *input_dev;
+       int err;
+
+       input_dev = input_allocate_device();
+       if (!input_dev) {
+               dev_err(&tj9->client->dev, "input device allocate failed\n");
+               return -ENOMEM;
+       }
+
+       tj9->input_dev = input_dev;
+
+       input_dev->open = kxtj9_input_open;
+       input_dev->close = kxtj9_input_close;
+       input_set_drvdata(input_dev, tj9);
+
+       kxtj9_init_input_device(tj9, input_dev);
+
+       err = input_register_device(tj9->input_dev);
+       if (err) {
+               dev_err(&tj9->client->dev,
+                       "unable to register input polled device %s: %d\n",
+                       tj9->input_dev->name, err);
+               input_free_device(tj9->input_dev);
+               return err;
+       }
+
+       return 0;
+}
+
+/*
+ * When IRQ mode is selected, we need to provide an interface to allow the user
+ * to change the output data rate of the part.  For consistency, we are using
+ * the set_poll method, which accepts a poll interval in milliseconds, and then
+ * calls update_odr() while passing this value as an argument.  In IRQ mode, the
+ * data outputs will not be read AT the requested poll interval, rather, the
+ * lowest ODR that can support the requested interval.  The client application
+ * will be responsible for retrieving data from the input node at the desired
+ * interval.
+ */
+
+/* Returns currently selected poll interval (in ms) */
+static ssize_t kxtj9_get_poll(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct kxtj9_data *tj9 = i2c_get_clientdata(client);
+
+       return sprintf(buf, "%d\n", tj9->last_poll_interval);
+}
+
+/* Allow users to select a new poll interval (in ms) */
+static ssize_t kxtj9_set_poll(struct device *dev, struct device_attribute *attr,
+                                               const char *buf, size_t count)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct kxtj9_data *tj9 = i2c_get_clientdata(client);
+       struct input_dev *input_dev = tj9->input_dev;
+       unsigned int interval;
+       int error;
+
+       error = kstrtouint(buf, 10, &interval);
+       if (error < 0)
+               return error;
+
+       /* Lock the device to prevent races with open/close (and itself) */
+       mutex_lock(&input_dev->mutex);
+
+       disable_irq(client->irq);
+
+       /*
+        * Set current interval to the greater of the minimum interval or
+        * the requested interval
+        */
+       tj9->last_poll_interval = max(interval, tj9->pdata.min_interval);
+
+       kxtj9_update_odr(tj9, tj9->last_poll_interval);
+
+       enable_irq(client->irq);
+       mutex_unlock(&input_dev->mutex);
+
+       return count;
+}
+
+static DEVICE_ATTR(poll, S_IRUGO|S_IWUSR, kxtj9_get_poll, kxtj9_set_poll);
+
+static struct attribute *kxtj9_attributes[] = {
+       &dev_attr_poll.attr,
+       NULL
+};
+
+static struct attribute_group kxtj9_attribute_group = {
+       .attrs = kxtj9_attributes
+};
+
+
+#ifdef CONFIG_INPUT_KXTJ9_POLLED_MODE
+static void kxtj9_poll(struct input_polled_dev *dev)
+{
+       struct kxtj9_data *tj9 = dev->private;
+       unsigned int poll_interval = dev->poll_interval;
+
+       kxtj9_report_acceleration_data(tj9);
+
+       if (poll_interval != tj9->last_poll_interval) {
+               kxtj9_update_odr(tj9, poll_interval);
+               tj9->last_poll_interval = poll_interval;
+       }
+}
+
+static void kxtj9_polled_input_open(struct input_polled_dev *dev)
+{
+       struct kxtj9_data *tj9 = dev->private;
+
+       kxtj9_enable(tj9);
+}
+
+static void kxtj9_polled_input_close(struct input_polled_dev *dev)
+{
+       struct kxtj9_data *tj9 = dev->private;
+
+       kxtj9_disable(tj9);
+}
+
+static int __devinit kxtj9_setup_polled_device(struct kxtj9_data *tj9)
+{
+       int err;
+       struct input_polled_dev *poll_dev;
+       poll_dev = input_allocate_polled_device();
+
+       if (!poll_dev) {
+               dev_err(&tj9->client->dev,
+                       "Failed to allocate polled device\n");
+               return -ENOMEM;
+       }
+
+       tj9->poll_dev = poll_dev;
+       tj9->input_dev = poll_dev->input;
+
+       poll_dev->private = tj9;
+       poll_dev->poll = kxtj9_poll;
+       poll_dev->open = kxtj9_polled_input_open;
+       poll_dev->close = kxtj9_polled_input_close;
+
+       kxtj9_init_input_device(tj9, poll_dev->input);
+
+       err = input_register_polled_device(poll_dev);
+       if (err) {
+               dev_err(&tj9->client->dev,
+                       "Unable to register polled device, err=%d\n", err);
+               input_free_polled_device(poll_dev);
+               return err;
+       }
+
+       return 0;
+}
+
+static void __devexit kxtj9_teardown_polled_device(struct kxtj9_data *tj9)
+{
+       input_unregister_polled_device(tj9->poll_dev);
+       input_free_polled_device(tj9->poll_dev);
+}
+
+#else
+
+static inline int kxtj9_setup_polled_device(struct kxtj9_data *tj9)
+{
+       return -ENOSYS;
+}
+
+static inline void kxtj9_teardown_polled_device(struct kxtj9_data *tj9)
+{
+}
+
+#endif
+
+static int __devinit kxtj9_verify(struct kxtj9_data *tj9)
+{
+       int retval;
+
+       retval = kxtj9_device_power_on(tj9);
+       if (retval < 0)
+               return retval;
+
+       retval = i2c_smbus_read_byte_data(tj9->client, WHO_AM_I);
+       if (retval < 0) {
+               dev_err(&tj9->client->dev, "read err int source\n");
+               goto out;
+       }
+
+       retval = retval != 0x06 ? -EIO : 0;
+
+out:
+       kxtj9_device_power_off(tj9);
+       return retval;
+}
+
+static int __devinit kxtj9_probe(struct i2c_client *client,
+                                const struct i2c_device_id *id)
+{
+       const struct kxtj9_platform_data *pdata = client->dev.platform_data;
+       struct kxtj9_data *tj9;
+       int err;
+
+       if (!i2c_check_functionality(client->adapter,
+                               I2C_FUNC_I2C | I2C_FUNC_SMBUS_BYTE_DATA)) {
+               dev_err(&client->dev, "client is not i2c capable\n");
+               return -ENXIO;
+       }
+
+       if (!pdata) {
+               dev_err(&client->dev, "platform data is NULL; exiting\n");
+               return -EINVAL;
+       }
+
+       tj9 = kzalloc(sizeof(*tj9), GFP_KERNEL);
+       if (!tj9) {
+               dev_err(&client->dev,
+                       "failed to allocate memory for module data\n");
+               return -ENOMEM;
+       }
+
+       tj9->client = client;
+       tj9->pdata = *pdata;
+
+       if (pdata->init) {
+               err = pdata->init();
+               if (err < 0)
+                       goto err_free_mem;
+       }
+
+       err = kxtj9_verify(tj9);
+       if (err < 0) {
+               dev_err(&client->dev, "device not recognized\n");
+               goto err_pdata_exit;
+       }
+
+       i2c_set_clientdata(client, tj9);
+
+       tj9->ctrl_reg1 = tj9->pdata.res_12bit | tj9->pdata.g_range;
+       tj9->data_ctrl = tj9->pdata.data_odr_init;
+
+       if (client->irq) {
+               /* If in irq mode, populate INT_CTRL_REG1 and enable DRDY. */
+               tj9->int_ctrl |= KXTJ9_IEN | KXTJ9_IEA | KXTJ9_IEL;
+               tj9->ctrl_reg1 |= DRDYE;
+
+               err = kxtj9_setup_input_device(tj9);
+               if (err)
+                       goto err_pdata_exit;
+
+               err = request_threaded_irq(client->irq, NULL, kxtj9_isr,
+                                          IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+                                          "kxtj9-irq", tj9);
+               if (err) {
+                       dev_err(&client->dev, "request irq failed: %d\n", err);
+                       goto err_destroy_input;
+               }
+
+               err = sysfs_create_group(&client->dev.kobj, &kxtj9_attribute_group);
+               if (err) {
+                       dev_err(&client->dev, "sysfs create failed: %d\n", err);
+                       goto err_free_irq;
+               }
+
+       } else {
+               err = kxtj9_setup_polled_device(tj9);
+               if (err)
+                       goto err_pdata_exit;
+       }
+
+       return 0;
+
+err_free_irq:
+       free_irq(client->irq, tj9);
+err_destroy_input:
+       input_unregister_device(tj9->input_dev);
+err_pdata_exit:
+       if (tj9->pdata.exit)
+               tj9->pdata.exit();
+err_free_mem:
+       kfree(tj9);
+       return err;
+}
+
+static int __devexit kxtj9_remove(struct i2c_client *client)
+{
+       struct kxtj9_data *tj9 = i2c_get_clientdata(client);
+
+       if (client->irq) {
+               sysfs_remove_group(&client->dev.kobj, &kxtj9_attribute_group);
+               free_irq(client->irq, tj9);
+               input_unregister_device(tj9->input_dev);
+       } else {
+               kxtj9_teardown_polled_device(tj9);
+       }
+
+       if (tj9->pdata.exit)
+               tj9->pdata.exit();
+
+       kfree(tj9);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int kxtj9_suspend(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct kxtj9_data *tj9 = i2c_get_clientdata(client);
+       struct input_dev *input_dev = tj9->input_dev;
+
+       mutex_lock(&input_dev->mutex);
+
+       if (input_dev->users)
+               kxtj9_disable(tj9);
+
+       mutex_unlock(&input_dev->mutex);
+       return 0;
+}
+
+static int kxtj9_resume(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct kxtj9_data *tj9 = i2c_get_clientdata(client);
+       struct input_dev *input_dev = tj9->input_dev;
+       int retval = 0;
+
+       mutex_lock(&input_dev->mutex);
+
+       if (input_dev->users)
+               kxtj9_enable(tj9);
+
+       mutex_unlock(&input_dev->mutex);
+       return retval;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(kxtj9_pm_ops, kxtj9_suspend, kxtj9_resume);
+
+static const struct i2c_device_id kxtj9_id[] = {
+       { NAME, 0 },
+       { },
+};
+
+MODULE_DEVICE_TABLE(i2c, kxtj9_id);
+
+static struct i2c_driver kxtj9_driver = {
+       .driver = {
+               .name   = NAME,
+               .owner  = THIS_MODULE,
+               .pm     = &kxtj9_pm_ops,
+       },
+       .probe          = kxtj9_probe,
+       .remove         = __devexit_p(kxtj9_remove),
+       .id_table       = kxtj9_id,
+};
+
+static int __init kxtj9_init(void)
+{
+       return i2c_add_driver(&kxtj9_driver);
+}
+module_init(kxtj9_init);
+
+static void __exit kxtj9_exit(void)
+{
+       i2c_del_driver(&kxtj9_driver);
+}
+module_exit(kxtj9_exit);
+
+MODULE_DESCRIPTION("KXTJ9 accelerometer driver");
+MODULE_AUTHOR("Chris Hudson <chudson@kionix.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/misc/mma8450.c b/drivers/input/misc/mma8450.c
new file mode 100644 (file)
index 0000000..20f8f92
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+ *  Driver for Freescale's 3-Axis Accelerometer MMA8450
+ *
+ *  Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/input-polldev.h>
+
+#define MMA8450_DRV_NAME       "mma8450"
+
+#define MODE_CHANGE_DELAY_MS   100
+#define POLL_INTERVAL          100
+#define POLL_INTERVAL_MAX      500
+
+/* register definitions */
+#define MMA8450_STATUS         0x00
+#define MMA8450_STATUS_ZXYDR   0x08
+
+#define MMA8450_OUT_X8         0x01
+#define MMA8450_OUT_Y8         0x02
+#define MMA8450_OUT_Z8         0x03
+
+#define MMA8450_OUT_X_LSB      0x05
+#define MMA8450_OUT_X_MSB      0x06
+#define MMA8450_OUT_Y_LSB      0x07
+#define MMA8450_OUT_Y_MSB      0x08
+#define MMA8450_OUT_Z_LSB      0x09
+#define MMA8450_OUT_Z_MSB      0x0a
+
+#define MMA8450_XYZ_DATA_CFG   0x16
+
+#define MMA8450_CTRL_REG1      0x38
+#define MMA8450_CTRL_REG2      0x39
+
+/* mma8450 status */
+struct mma8450 {
+       struct i2c_client       *client;
+       struct input_polled_dev *idev;
+};
+
+static int mma8450_read(struct mma8450 *m, unsigned off)
+{
+       struct i2c_client *c = m->client;
+       int ret;
+
+       ret = i2c_smbus_read_byte_data(c, off);
+       if (ret < 0)
+               dev_err(&c->dev,
+                       "failed to read register 0x%02x, error %d\n",
+                       off, ret);
+
+       return ret;
+}
+
+static int mma8450_write(struct mma8450 *m, unsigned off, u8 v)
+{
+       struct i2c_client *c = m->client;
+       int error;
+
+       error = i2c_smbus_write_byte_data(c, off, v);
+       if (error < 0) {
+               dev_err(&c->dev,
+                       "failed to write to register 0x%02x, error %d\n",
+                       off, error);
+               return error;
+       }
+
+       return 0;
+}
+
+static int mma8450_read_xyz(struct mma8450 *m, int *x, int *y, int *z)
+{
+       struct i2c_client *c = m->client;
+       u8 buff[6];
+       int err;
+
+       err = i2c_smbus_read_i2c_block_data(c, MMA8450_OUT_X_LSB, 6, buff);
+       if (err < 0) {
+               dev_err(&c->dev,
+                       "failed to read block data at 0x%02x, error %d\n",
+                       MMA8450_OUT_X_LSB, err);
+               return err;
+       }
+
+       *x = ((buff[1] << 4) & 0xff0) | (buff[0] & 0xf);
+       *y = ((buff[3] << 4) & 0xff0) | (buff[2] & 0xf);
+       *z = ((buff[5] << 4) & 0xff0) | (buff[4] & 0xf);
+
+       return 0;
+}
+
+static void mma8450_poll(struct input_polled_dev *dev)
+{
+       struct mma8450 *m = dev->private;
+       int x, y, z;
+       int ret;
+       int err;
+
+       ret = mma8450_read(m, MMA8450_STATUS);
+       if (ret < 0)
+               return;
+
+       if (!(ret & MMA8450_STATUS_ZXYDR))
+               return;
+
+       err = mma8450_read_xyz(m, &x, &y, &z);
+       if (err)
+               return;
+
+       input_report_abs(dev->input, ABS_X, x);
+       input_report_abs(dev->input, ABS_Y, y);
+       input_report_abs(dev->input, ABS_Z, z);
+       input_sync(dev->input);
+}
+
+/* Initialize the MMA8450 chip */
+static void mma8450_open(struct input_polled_dev *dev)
+{
+       struct mma8450 *m = dev->private;
+       int err;
+
+       /* enable all events from X/Y/Z, no FIFO */
+       err = mma8450_write(m, MMA8450_XYZ_DATA_CFG, 0x07);
+       if (err)
+               return;
+
+       /*
+        * Sleep mode poll rate - 50Hz
+        * System output data rate - 400Hz
+        * Full scale selection - Active, +/- 2G
+        */
+       err = mma8450_write(m, MMA8450_CTRL_REG1, 0x01);
+       if (err < 0)
+               return;
+
+       msleep(MODE_CHANGE_DELAY_MS);
+}
+
+static void mma8450_close(struct input_polled_dev *dev)
+{
+       struct mma8450 *m = dev->private;
+
+       mma8450_write(m, MMA8450_CTRL_REG1, 0x00);
+       mma8450_write(m, MMA8450_CTRL_REG2, 0x01);
+}
+
+/*
+ * I2C init/probing/exit functions
+ */
+static int __devinit mma8450_probe(struct i2c_client *c,
+                                  const struct i2c_device_id *id)
+{
+       struct input_polled_dev *idev;
+       struct mma8450 *m;
+       int err;
+
+       m = kzalloc(sizeof(struct mma8450), GFP_KERNEL);
+       idev = input_allocate_polled_device();
+       if (!m || !idev) {
+               err = -ENOMEM;
+               goto err_free_mem;
+       }
+
+       m->client = c;
+       m->idev = idev;
+
+       idev->private           = m;
+       idev->input->name       = MMA8450_DRV_NAME;
+       idev->input->id.bustype = BUS_I2C;
+       idev->poll              = mma8450_poll;
+       idev->poll_interval     = POLL_INTERVAL;
+       idev->poll_interval_max = POLL_INTERVAL_MAX;
+       idev->open              = mma8450_open;
+       idev->close             = mma8450_close;
+
+       __set_bit(EV_ABS, idev->input->evbit);
+       input_set_abs_params(idev->input, ABS_X, -2048, 2047, 32, 32);
+       input_set_abs_params(idev->input, ABS_Y, -2048, 2047, 32, 32);
+       input_set_abs_params(idev->input, ABS_Z, -2048, 2047, 32, 32);
+
+       err = input_register_polled_device(idev);
+       if (err) {
+               dev_err(&c->dev, "failed to register polled input device\n");
+               goto err_free_mem;
+       }
+
+       return 0;
+
+err_free_mem:
+       input_free_polled_device(idev);
+       kfree(m);
+       return err;
+}
+
+static int __devexit mma8450_remove(struct i2c_client *c)
+{
+       struct mma8450 *m = i2c_get_clientdata(c);
+       struct input_polled_dev *idev = m->idev;
+
+       input_unregister_polled_device(idev);
+       input_free_polled_device(idev);
+       kfree(m);
+
+       return 0;
+}
+
+static const struct i2c_device_id mma8450_id[] = {
+       { MMA8450_DRV_NAME, 0 },
+       { },
+};
+MODULE_DEVICE_TABLE(i2c, mma8450_id);
+
+static struct i2c_driver mma8450_driver = {
+       .driver = {
+               .name   = MMA8450_DRV_NAME,
+               .owner  = THIS_MODULE,
+       },
+       .probe          = mma8450_probe,
+       .remove         = __devexit_p(mma8450_remove),
+       .id_table       = mma8450_id,
+};
+
+static int __init mma8450_init(void)
+{
+       return i2c_add_driver(&mma8450_driver);
+}
+module_init(mma8450_init);
+
+static void __exit mma8450_exit(void)
+{
+       i2c_del_driver(&mma8450_driver);
+}
+module_exit(mma8450_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("MMA8450 3-Axis Accelerometer Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/misc/mpu3050.c b/drivers/input/misc/mpu3050.c
new file mode 100644 (file)
index 0000000..b95fac1
--- /dev/null
@@ -0,0 +1,376 @@
+/*
+ * MPU3050 Tri-axis gyroscope driver
+ *
+ * Copyright (C) 2011 Wistron Co.Ltd
+ * Joseph Lai <joseph_lai@wistron.com>
+ *
+ * Trimmed down by Alan Cox <alan@linux.intel.com> to produce this version
+ *
+ * This is a 'lite' version of the driver, while we consider the right way
+ * to present the other features to user space. In particular it requires the
+ * device has an IRQ, and it only provides an input interface, so is not much
+ * use for device orientation. A fuller version is available from the Meego
+ * tree.
+ *
+ * This program is based on bma023.c.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+
+#define MPU3050_CHIP_ID_REG    0x00
+#define MPU3050_CHIP_ID                0x69
+#define MPU3050_XOUT_H         0x1D
+#define MPU3050_PWR_MGM                0x3E
+#define MPU3050_PWR_MGM_POS    6
+#define MPU3050_PWR_MGM_MASK   0x40
+
+#define MPU3050_AUTO_DELAY     1000
+
+#define MPU3050_MIN_VALUE      -32768
+#define MPU3050_MAX_VALUE      32767
+
+struct axis_data {
+       s16 x;
+       s16 y;
+       s16 z;
+};
+
+struct mpu3050_sensor {
+       struct i2c_client *client;
+       struct device *dev;
+       struct input_dev *idev;
+};
+
+/**
+ *     mpu3050_xyz_read_reg    -       read the axes values
+ *     @buffer: provide register addr and get register
+ *     @length: length of register
+ *
+ *     Reads the register values in one transaction or returns a negative
+ *     error code on failure.
+ */
+static int mpu3050_xyz_read_reg(struct i2c_client *client,
+                              u8 *buffer, int length)
+{
+       /*
+        * Annoying we can't make this const because the i2c layer doesn't
+        * declare input buffers const.
+        */
+       char cmd = MPU3050_XOUT_H;
+       struct i2c_msg msg[] = {
+               {
+                       .addr = client->addr,
+                       .flags = 0,
+                       .len = 1,
+                       .buf = &cmd,
+               },
+               {
+                       .addr = client->addr,
+                       .flags = I2C_M_RD,
+                       .len = length,
+                       .buf = buffer,
+               },
+       };
+
+       return i2c_transfer(client->adapter, msg, 2);
+}
+
+/**
+ *     mpu3050_read_xyz        -       get co-ordinates from device
+ *     @client: i2c address of sensor
+ *     @coords: co-ordinates to update
+ *
+ *     Return the converted X Y and Z co-ordinates from the sensor device
+ */
+static void mpu3050_read_xyz(struct i2c_client *client,
+                            struct axis_data *coords)
+{
+       u16 buffer[3];
+
+       mpu3050_xyz_read_reg(client, (u8 *)buffer, 6);
+       coords->x = be16_to_cpu(buffer[0]);
+       coords->y = be16_to_cpu(buffer[1]);
+       coords->z = be16_to_cpu(buffer[2]);
+       dev_dbg(&client->dev, "%s: x %d, y %d, z %d\n", __func__,
+                                       coords->x, coords->y, coords->z);
+}
+
+/**
+ *     mpu3050_set_power_mode  -       set the power mode
+ *     @client: i2c client for the sensor
+ *     @val: value to switch on/off of power, 1: normal power, 0: low power
+ *
+ *     Put device to normal-power mode or low-power mode.
+ */
+static void mpu3050_set_power_mode(struct i2c_client *client, u8 val)
+{
+       u8 value;
+
+       value = i2c_smbus_read_byte_data(client, MPU3050_PWR_MGM);
+       value = (value & ~MPU3050_PWR_MGM_MASK) |
+               (((val << MPU3050_PWR_MGM_POS) & MPU3050_PWR_MGM_MASK) ^
+                MPU3050_PWR_MGM_MASK);
+       i2c_smbus_write_byte_data(client, MPU3050_PWR_MGM, value);
+}
+
+/**
+ *     mpu3050_input_open      -       called on input event open
+ *     @input: input dev of opened device
+ *
+ *     The input layer calls this function when input event is opened. The
+ *     function will push the device to resume. Then, the device is ready
+ *     to provide data.
+ */
+static int mpu3050_input_open(struct input_dev *input)
+{
+       struct mpu3050_sensor *sensor = input_get_drvdata(input);
+
+       pm_runtime_get(sensor->dev);
+
+       return 0;
+}
+
+/**
+ *     mpu3050_input_close     -       called on input event close
+ *     @input: input dev of closed device
+ *
+ *     The input layer calls this function when input event is closed. The
+ *     function will push the device to suspend.
+ */
+static void mpu3050_input_close(struct input_dev *input)
+{
+       struct mpu3050_sensor *sensor = input_get_drvdata(input);
+
+       pm_runtime_put(sensor->dev);
+}
+
+/**
+ *     mpu3050_interrupt_thread        -       handle an IRQ
+ *     @irq: interrupt numner
+ *     @data: the sensor
+ *
+ *     Called by the kernel single threaded after an interrupt occurs. Read
+ *     the sensor data and generate an input event for it.
+ */
+static irqreturn_t mpu3050_interrupt_thread(int irq, void *data)
+{
+       struct mpu3050_sensor *sensor = data;
+       struct axis_data axis;
+
+       mpu3050_read_xyz(sensor->client, &axis);
+
+       input_report_abs(sensor->idev, ABS_X, axis.x);
+       input_report_abs(sensor->idev, ABS_Y, axis.y);
+       input_report_abs(sensor->idev, ABS_Z, axis.z);
+       input_sync(sensor->idev);
+
+       return IRQ_HANDLED;
+}
+
+/**
+ *     mpu3050_probe   -       device detection callback
+ *     @client: i2c client of found device
+ *     @id: id match information
+ *
+ *     The I2C layer calls us when it believes a sensor is present at this
+ *     address. Probe to see if this is correct and to validate the device.
+ *
+ *     If present install the relevant sysfs interfaces and input device.
+ */
+static int __devinit mpu3050_probe(struct i2c_client *client,
+                                  const struct i2c_device_id *id)
+{
+       struct mpu3050_sensor *sensor;
+       struct input_dev *idev;
+       int ret;
+       int error;
+
+       sensor = kzalloc(sizeof(struct mpu3050_sensor), GFP_KERNEL);
+       idev = input_allocate_device();
+       if (!sensor || !idev) {
+               dev_err(&client->dev, "failed to allocate driver data\n");
+               error = -ENOMEM;
+               goto err_free_mem;
+       }
+
+       sensor->client = client;
+       sensor->dev = &client->dev;
+       sensor->idev = idev;
+
+       mpu3050_set_power_mode(client, 1);
+       msleep(10);
+
+       ret = i2c_smbus_read_byte_data(client, MPU3050_CHIP_ID_REG);
+       if (ret < 0) {
+               dev_err(&client->dev, "failed to detect device\n");
+               error = -ENXIO;
+               goto err_free_mem;
+       }
+
+       if (ret != MPU3050_CHIP_ID) {
+               dev_err(&client->dev, "unsupported chip id\n");
+               error = -ENXIO;
+               goto err_free_mem;
+       }
+
+       idev->name = "MPU3050";
+       idev->id.bustype = BUS_I2C;
+       idev->dev.parent = &client->dev;
+
+       idev->open = mpu3050_input_open;
+       idev->close = mpu3050_input_close;
+
+       __set_bit(EV_ABS, idev->evbit);
+       input_set_abs_params(idev, ABS_X,
+                            MPU3050_MIN_VALUE, MPU3050_MAX_VALUE, 0, 0);
+       input_set_abs_params(idev, ABS_Y,
+                            MPU3050_MIN_VALUE, MPU3050_MAX_VALUE, 0, 0);
+       input_set_abs_params(idev, ABS_Z,
+                            MPU3050_MIN_VALUE, MPU3050_MAX_VALUE, 0, 0);
+
+       input_set_drvdata(idev, sensor);
+
+       pm_runtime_set_active(&client->dev);
+
+       error = request_threaded_irq(client->irq,
+                                    NULL, mpu3050_interrupt_thread,
+                                    IRQF_TRIGGER_RISING,
+                                    "mpu_int", sensor);
+       if (error) {
+               dev_err(&client->dev,
+                       "can't get IRQ %d, error %d\n", client->irq, error);
+               goto err_pm_set_suspended;
+       }
+
+       error = input_register_device(idev);
+       if (error) {
+               dev_err(&client->dev, "failed to register input device\n");
+               goto err_free_irq;
+       }
+
+       pm_runtime_enable(&client->dev);
+       pm_runtime_set_autosuspend_delay(&client->dev, MPU3050_AUTO_DELAY);
+
+       return 0;
+
+err_free_irq:
+       free_irq(client->irq, sensor);
+err_pm_set_suspended:
+       pm_runtime_set_suspended(&client->dev);
+err_free_mem:
+       input_unregister_device(idev);
+       kfree(sensor);
+       return error;
+}
+
+/**
+ *     mpu3050_remove  -       remove a sensor
+ *     @client: i2c client of sensor being removed
+ *
+ *     Our sensor is going away, clean up the resources.
+ */
+static int __devexit mpu3050_remove(struct i2c_client *client)
+{
+       struct mpu3050_sensor *sensor = i2c_get_clientdata(client);
+
+       pm_runtime_disable(&client->dev);
+       pm_runtime_set_suspended(&client->dev);
+
+       free_irq(client->irq, sensor);
+       input_unregister_device(sensor->idev);
+       kfree(sensor);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+/**
+ *     mpu3050_suspend         -       called on device suspend
+ *     @dev: device being suspended
+ *
+ *     Put the device into sleep mode before we suspend the machine.
+ */
+static int mpu3050_suspend(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+
+       mpu3050_set_power_mode(client, 0);
+
+       return 0;
+}
+
+/**
+ *     mpu3050_resume          -       called on device resume
+ *     @dev: device being resumed
+ *
+ *     Put the device into powered mode on resume.
+ */
+static int mpu3050_resume(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+
+       mpu3050_set_power_mode(client, 1);
+       msleep(100);  /* wait for gyro chip resume */
+
+       return 0;
+}
+#endif
+
+static UNIVERSAL_DEV_PM_OPS(mpu3050_pm, mpu3050_suspend, mpu3050_resume, NULL);
+
+static const struct i2c_device_id mpu3050_ids[] = {
+       { "mpu3050", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, mpu3050_ids);
+
+static struct i2c_driver mpu3050_i2c_driver = {
+       .driver = {
+               .name   = "mpu3050",
+               .owner  = THIS_MODULE,
+               .pm     = &mpu3050_pm,
+       },
+       .probe          = mpu3050_probe,
+       .remove         = __devexit_p(mpu3050_remove),
+       .id_table       = mpu3050_ids,
+};
+
+static int __init mpu3050_init(void)
+{
+       return i2c_add_driver(&mpu3050_i2c_driver);
+}
+module_init(mpu3050_init);
+
+static void __exit mpu3050_exit(void)
+{
+       i2c_del_driver(&mpu3050_i2c_driver);
+}
+module_exit(mpu3050_exit);
+
+MODULE_AUTHOR("Wistron Corp.");
+MODULE_DESCRIPTION("MPU3050 Tri-axis gyroscope driver");
+MODULE_LICENSE("GPL");
index 62bae99..ad2e51c 100644 (file)
@@ -373,7 +373,7 @@ static struct xenbus_driver xenkbd_driver = {
 
 static int __init xenkbd_init(void)
 {
-       if (!xen_pv_domain())
+       if (!xen_domain())
                return -ENODEV;
 
        /* Nothing to do if running in dom0. */
index 7b6ce17..58902fb 100644 (file)
@@ -191,7 +191,7 @@ static void __exit gpio_mouse_exit(void)
 }
 module_exit(gpio_mouse_exit);
 
-MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>");
+MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>");
 MODULE_DESCRIPTION("GPIO mouse driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:gpio_mouse"); /* work with hotplug and coldplug */
index c31ad11..83bcaba 100644 (file)
@@ -33,7 +33,7 @@ static const char *desired_serio_phys;
 static int lifebook_limit_serio3(const struct dmi_system_id *d)
 {
        desired_serio_phys = "isa0060/serio3";
-       return 0;
+       return 1;
 }
 
 static bool lifebook_use_6byte_proto;
@@ -41,7 +41,7 @@ static bool lifebook_use_6byte_proto;
 static int lifebook_set_6byte_proto(const struct dmi_system_id *d)
 {
        lifebook_use_6byte_proto = true;
-       return 0;
+       return 1;
 }
 
 static const struct dmi_system_id __initconst lifebook_dmi_table[] = {
index 943cfec..6c5d84f 100644 (file)
@@ -12,7 +12,6 @@
 
 #include <linux/init.h>
 #include <linux/input.h>
-#include <linux/version.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
index 1242775..2fc887a 100644 (file)
@@ -20,7 +20,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/version.h>
 #include <linux/input.h>
 #include <linux/ctype.h>
 #include <linux/libps2.h>
index e06e045..5538fc6 100644 (file)
@@ -207,27 +207,37 @@ static int synaptics_identify(struct psmouse *psmouse)
 static int synaptics_resolution(struct psmouse *psmouse)
 {
        struct synaptics_data *priv = psmouse->private;
-       unsigned char res[3];
-       unsigned char max[3];
+       unsigned char resp[3];
 
        if (SYN_ID_MAJOR(priv->identity) < 4)
                return 0;
 
-       if (synaptics_send_cmd(psmouse, SYN_QUE_RESOLUTION, res) == 0) {
-               if (res[0] != 0 && (res[1] & 0x80) && res[2] != 0) {
-                       priv->x_res = res[0]; /* x resolution in units/mm */
-                       priv->y_res = res[2]; /* y resolution in units/mm */
+       if (synaptics_send_cmd(psmouse, SYN_QUE_RESOLUTION, resp) == 0) {
+               if (resp[0] != 0 && (resp[1] & 0x80) && resp[2] != 0) {
+                       priv->x_res = resp[0]; /* x resolution in units/mm */
+                       priv->y_res = resp[2]; /* y resolution in units/mm */
                }
        }
 
        if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 5 &&
            SYN_CAP_MAX_DIMENSIONS(priv->ext_cap_0c)) {
-               if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_DIMENSIONS, max)) {
-                       printk(KERN_ERR "Synaptics claims to have dimensions query,"
-                              " but I'm not able to read it.\n");
+               if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MAX_COORDS, resp)) {
+                       printk(KERN_ERR "Synaptics claims to have max coordinates"
+                              " query, but I'm not able to read it.\n");
+               } else {
+                       priv->x_max = (resp[0] << 5) | ((resp[1] & 0x0f) << 1);
+                       priv->y_max = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3);
+               }
+       }
+
+       if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 7 &&
+           SYN_CAP_MIN_DIMENSIONS(priv->ext_cap_0c)) {
+               if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MIN_COORDS, resp)) {
+                       printk(KERN_ERR "Synaptics claims to have min coordinates"
+                              " query, but I'm not able to read it.\n");
                } else {
-                       priv->x_max = (max[0] << 5) | ((max[1] & 0x0f) << 1);
-                       priv->y_max = (max[2] << 5) | ((max[1] & 0xf0) >> 3);
+                       priv->x_min = (resp[0] << 5) | ((resp[1] & 0x0f) << 1);
+                       priv->y_min = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3);
                }
        }
 
@@ -406,26 +416,10 @@ static int synaptics_parse_hw_state(const unsigned char buf[],
        memset(hw, 0, sizeof(struct synaptics_hw_state));
 
        if (SYN_MODEL_NEWABS(priv->model_id)) {
-               hw->x = (((buf[3] & 0x10) << 8) |
-                        ((buf[1] & 0x0f) << 8) |
-                        buf[4]);
-               hw->y = (((buf[3] & 0x20) << 7) |
-                        ((buf[1] & 0xf0) << 4) |
-                        buf[5]);
-
-               hw->z = buf[2];
                hw->w = (((buf[0] & 0x30) >> 2) |
                         ((buf[0] & 0x04) >> 1) |
                         ((buf[3] & 0x04) >> 2));
 
-               if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) && hw->w == 2) {
-                       /* Gesture packet: (x, y, z) at half resolution */
-                       priv->mt.x = (((buf[4] & 0x0f) << 8) | buf[1]) << 1;
-                       priv->mt.y = (((buf[4] & 0xf0) << 4) | buf[2]) << 1;
-                       priv->mt.z = ((buf[3] & 0x30) | (buf[5] & 0x0f)) << 1;
-                       return 1;
-               }
-
                hw->left  = (buf[0] & 0x01) ? 1 : 0;
                hw->right = (buf[0] & 0x02) ? 1 : 0;
 
@@ -448,6 +442,22 @@ static int synaptics_parse_hw_state(const unsigned char buf[],
                        hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0;
                }
 
+               if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) && hw->w == 2) {
+                       /* Gesture packet: (x, y, z) at half resolution */
+                       priv->mt.x = (((buf[4] & 0x0f) << 8) | buf[1]) << 1;
+                       priv->mt.y = (((buf[4] & 0xf0) << 4) | buf[2]) << 1;
+                       priv->mt.z = ((buf[3] & 0x30) | (buf[5] & 0x0f)) << 1;
+                       return 1;
+               }
+
+               hw->x = (((buf[3] & 0x10) << 8) |
+                        ((buf[1] & 0x0f) << 8) |
+                        buf[4]);
+               hw->y = (((buf[3] & 0x20) << 7) |
+                        ((buf[1] & 0xf0) << 4) |
+                        buf[5]);
+               hw->z = buf[2];
+
                if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) &&
                    ((buf[0] ^ buf[3]) & 0x02)) {
                        switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) {
@@ -485,7 +495,8 @@ static int synaptics_parse_hw_state(const unsigned char buf[],
        return 0;
 }
 
-static void set_slot(struct input_dev *dev, int slot, bool active, int x, int y)
+static void synaptics_report_semi_mt_slot(struct input_dev *dev, int slot,
+                                         bool active, int x, int y)
 {
        input_mt_slot(dev, slot);
        input_mt_report_slot_state(dev, MT_TOOL_FINGER, active);
@@ -502,14 +513,16 @@ static void synaptics_report_semi_mt_data(struct input_dev *dev,
                                          int num_fingers)
 {
        if (num_fingers >= 2) {
-               set_slot(dev, 0, true, min(a->x, b->x), min(a->y, b->y));
-               set_slot(dev, 1, true, max(a->x, b->x), max(a->y, b->y));
+               synaptics_report_semi_mt_slot(dev, 0, true, min(a->x, b->x),
+                                             min(a->y, b->y));
+               synaptics_report_semi_mt_slot(dev, 1, true, max(a->x, b->x),
+                                             max(a->y, b->y));
        } else if (num_fingers == 1) {
-               set_slot(dev, 0, true, a->x, a->y);
-               set_slot(dev, 1, false, 0, 0);
+               synaptics_report_semi_mt_slot(dev, 0, true, a->x, a->y);
+               synaptics_report_semi_mt_slot(dev, 1, false, 0, 0);
        } else {
-               set_slot(dev, 0, false, 0, 0);
-               set_slot(dev, 1, false, 0, 0);
+               synaptics_report_semi_mt_slot(dev, 0, false, 0, 0);
+               synaptics_report_semi_mt_slot(dev, 1, false, 0, 0);
        }
 }
 
@@ -684,23 +697,36 @@ static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse)
 static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
 {
        int i;
+       int fuzz = SYN_CAP_REDUCED_FILTERING(priv->ext_cap_0c) ?
+                       SYN_REDUCED_FILTER_FUZZ : 0;
 
        __set_bit(INPUT_PROP_POINTER, dev->propbit);
 
        __set_bit(EV_ABS, dev->evbit);
        input_set_abs_params(dev, ABS_X,
-                            XMIN_NOMINAL, priv->x_max ?: XMAX_NOMINAL, 0, 0);
+                            priv->x_min ?: XMIN_NOMINAL,
+                            priv->x_max ?: XMAX_NOMINAL,
+                            fuzz, 0);
        input_set_abs_params(dev, ABS_Y,
-                            YMIN_NOMINAL, priv->y_max ?: YMAX_NOMINAL, 0, 0);
+                            priv->y_min ?: YMIN_NOMINAL,
+                            priv->y_max ?: YMAX_NOMINAL,
+                            fuzz, 0);
        input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0);
 
        if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) {
                __set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
                input_mt_init_slots(dev, 2);
-               input_set_abs_params(dev, ABS_MT_POSITION_X, XMIN_NOMINAL,
-                                    priv->x_max ?: XMAX_NOMINAL, 0, 0);
-               input_set_abs_params(dev, ABS_MT_POSITION_Y, YMIN_NOMINAL,
-                                    priv->y_max ?: YMAX_NOMINAL, 0, 0);
+               input_set_abs_params(dev, ABS_MT_POSITION_X,
+                                    priv->x_min ?: XMIN_NOMINAL,
+                                    priv->x_max ?: XMAX_NOMINAL,
+                                    fuzz, 0);
+               input_set_abs_params(dev, ABS_MT_POSITION_Y,
+                                    priv->y_min ?: YMIN_NOMINAL,
+                                    priv->y_max ?: YMAX_NOMINAL,
+                                    fuzz, 0);
+
+               input_abs_set_res(dev, ABS_MT_POSITION_X, priv->x_res);
+               input_abs_set_res(dev, ABS_MT_POSITION_Y, priv->y_res);
        }
 
        if (SYN_CAP_PALMDETECT(priv->capabilities))
@@ -971,4 +997,3 @@ bool synaptics_supported(void)
 }
 
 #endif /* CONFIG_MOUSE_PS2_SYNAPTICS */
-
index 7453938..ca040aa 100644 (file)
@@ -19,7 +19,8 @@
 #define SYN_QUE_RESOLUTION             0x08
 #define SYN_QUE_EXT_CAPAB              0x09
 #define SYN_QUE_EXT_CAPAB_0C           0x0c
-#define SYN_QUE_EXT_DIMENSIONS         0x0d
+#define SYN_QUE_EXT_MAX_COORDS         0x0d
+#define SYN_QUE_EXT_MIN_COORDS         0x0f
 
 /* synatics modes */
 #define SYN_BIT_ABSOLUTE_MODE          (1 << 7)
  * 1   0x60    multifinger mode        identifies firmware finger counting
  *                                     (not reporting!) algorithm.
  *                                     Not particularly meaningful
- * 1   0x80    covered pad             W clipped to 14, 15 == pad mostly covered
- * 2   0x01    clickpad bit 1          2-button ClickPad
- * 2   0x02    deluxe LED controls     touchpad support LED commands
+ * 1   0x80    covered pad             W clipped to 14, 15 == pad mostly covered
+ * 2   0x01    clickpad bit 1          2-button ClickPad
+ * 2   0x02    deluxe LED controls     touchpad support LED commands
  *                                     ala multimedia control bar
  * 2   0x04    reduced filtering       firmware does less filtering on
  *                                     position data, driver should watch
  *                                     for noise.
+ * 2   0x20    report min              query 0x0f gives min coord reported
  */
 #define SYN_CAP_CLICKPAD(ex0c)         ((ex0c) & 0x100000) /* 1-button ClickPad */
 #define SYN_CAP_CLICKPAD2BTN(ex0c)     ((ex0c) & 0x000100) /* 2-button ClickPad */
 #define SYN_CAP_MAX_DIMENSIONS(ex0c)   ((ex0c) & 0x020000)
+#define SYN_CAP_MIN_DIMENSIONS(ex0c)   ((ex0c) & 0x002000)
 #define SYN_CAP_ADV_GESTURE(ex0c)      ((ex0c) & 0x080000)
+#define SYN_CAP_REDUCED_FILTERING(ex0c)        ((ex0c) & 0x000400)
 
 /* synaptics modes query bits */
 #define SYN_MODE_ABSOLUTE(m)           ((m) & (1 << 7))
 #define SYN_NEWABS_RELAXED             2
 #define SYN_OLDABS                     3
 
+/* amount to fuzz position data when touchpad reports reduced filtering */
+#define SYN_REDUCED_FILTER_FUZZ                8
+
 /*
  * A structure to describe the state of the touchpad hardware (buttons and pad)
  */
@@ -130,7 +137,8 @@ struct synaptics_data {
        unsigned long int ext_cap_0c;           /* Ext Caps from 0x0c query */
        unsigned long int identity;             /* Identification */
        unsigned int x_res, y_res;              /* X/Y resolution in units/mm */
-       unsigned int x_max, y_max;              /* Max dimensions (from FW) */
+       unsigned int x_max, y_max;              /* Max coordinates (from FW) */
+       unsigned int x_min, y_min;              /* Min coordinates (from FW) */
 
        unsigned char pkt_type;                 /* packet type - old, new, etc */
        unsigned char mode;                     /* current mode byte */
index 6ee8f0d..95280f9 100644 (file)
@@ -372,6 +372,6 @@ static void __exit psif_exit(void)
 module_init(psif_init);
 module_exit(psif_exit);
 
-MODULE_AUTHOR("Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com>");
+MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>");
 MODULE_DESCRIPTION("Atmel AVR32 PSIF PS/2 driver");
 MODULE_LICENSE("GPL");
index 4220620..979c443 100644 (file)
@@ -795,7 +795,7 @@ int hp_sdc_release_cooked_irq(hp_sdc_irqhook *callback)
 
 /************************* Keepalive timer task *********************/
 
-void hp_sdc_kicker (unsigned long data)
+static void hp_sdc_kicker(unsigned long data)
 {
        tasklet_schedule(&hp_sdc.task);
        /* Re-insert the periodic task. */
index 0a619c5..6d89fd1 100644 (file)
        /* toolMode codes
         */
 #define AIPTEK_TOOL_BUTTON_PEN_MODE                    BTN_TOOL_PEN
-#define AIPTEK_TOOL_BUTTON_PEN_MODE                    BTN_TOOL_PEN
 #define AIPTEK_TOOL_BUTTON_PENCIL_MODE                 BTN_TOOL_PENCIL
 #define AIPTEK_TOOL_BUTTON_BRUSH_MODE                  BTN_TOOL_BRUSH
 #define AIPTEK_TOOL_BUTTON_AIRBRUSH_MODE               BTN_TOOL_AIRBRUSH
index 08ba5ad..03ebcc8 100644 (file)
@@ -15,6 +15,7 @@
 #include "wacom_wac.h"
 #include "wacom.h"
 #include <linux/input/mt.h>
+#include <linux/hid.h>
 
 /* resolution for penabled devices */
 #define WACOM_PL_RES           20
@@ -264,6 +265,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom)
                        wacom->id[0] = 0;
                input_report_abs(input, ABS_MISC, wacom->id[0]); /* report tool id */
                input_report_key(input, wacom->tool[0], prox);
+               input_event(input, EV_MSC, MSC_SERIAL, 1);
                input_sync(input); /* sync last event */
        }
 
@@ -273,11 +275,10 @@ static int wacom_graphire_irq(struct wacom_wac *wacom)
                prox = data[7] & 0xf8;
                if (prox || wacom->id[1]) {
                        wacom->id[1] = PAD_DEVICE_ID;
-                       input_report_key(input, BTN_0, (data[7] & 0x40));
-                       input_report_key(input, BTN_4, (data[7] & 0x80));
+                       input_report_key(input, BTN_BACK, (data[7] & 0x40));
+                       input_report_key(input, BTN_FORWARD, (data[7] & 0x80));
                        rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3);
                        input_report_rel(input, REL_WHEEL, rw);
-                       input_report_key(input, BTN_TOOL_FINGER, 0xf0);
                        if (!prox)
                                wacom->id[1] = 0;
                        input_report_abs(input, ABS_MISC, wacom->id[1]);
@@ -290,18 +291,17 @@ static int wacom_graphire_irq(struct wacom_wac *wacom)
                prox = (data[7] & 0xf8) || data[8];
                if (prox || wacom->id[1]) {
                        wacom->id[1] = PAD_DEVICE_ID;
-                       input_report_key(input, BTN_0, (data[7] & 0x08));
-                       input_report_key(input, BTN_1, (data[7] & 0x20));
-                       input_report_key(input, BTN_4, (data[7] & 0x10));
-                       input_report_key(input, BTN_5, (data[7] & 0x40));
+                       input_report_key(input, BTN_BACK, (data[7] & 0x08));
+                       input_report_key(input, BTN_LEFT, (data[7] & 0x20));
+                       input_report_key(input, BTN_FORWARD, (data[7] & 0x10));
+                       input_report_key(input, BTN_RIGHT, (data[7] & 0x40));
                        input_report_abs(input, ABS_WHEEL, (data[8] & 0x7f));
-                       input_report_key(input, BTN_TOOL_FINGER, 0xf0);
                        if (!prox)
                                wacom->id[1] = 0;
                        input_report_abs(input, ABS_MISC, wacom->id[1]);
                        input_event(input, EV_MSC, MSC_SERIAL, 0xf0);
+                       retval = 1;
                }
-               retval = 1;
                break;
        }
 exit:
@@ -494,10 +494,6 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
 
        /* pad packets. Works as a second tool and is always in prox */
        if (data[0] == WACOM_REPORT_INTUOSPAD) {
-               /* initiate the pad as a device */
-               if (wacom->tool[1] != BTN_TOOL_FINGER)
-                       wacom->tool[1] = BTN_TOOL_FINGER;
-
                if (features->type >= INTUOS4S && features->type <= INTUOS4L) {
                        input_report_key(input, BTN_0, (data[2] & 0x01));
                        input_report_key(input, BTN_1, (data[3] & 0x01));
@@ -1080,18 +1076,14 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
 
        switch (wacom_wac->features.type) {
        case WACOM_MO:
-               __set_bit(BTN_1, input_dev->keybit);
-               __set_bit(BTN_5, input_dev->keybit);
-
                input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
                /* fall through */
 
        case WACOM_G4:
                input_set_capability(input_dev, EV_MSC, MSC_SERIAL);
 
-               __set_bit(BTN_TOOL_FINGER, input_dev->keybit);
-               __set_bit(BTN_0, input_dev->keybit);
-               __set_bit(BTN_4, input_dev->keybit);
+               __set_bit(BTN_BACK, input_dev->keybit);
+               __set_bit(BTN_FORWARD, input_dev->keybit);
                /* fall through */
 
        case GRAPHIRE:
@@ -1127,10 +1119,12 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
        case CINTIQ:
                for (i = 0; i < 8; i++)
                        __set_bit(BTN_0 + i, input_dev->keybit);
-               __set_bit(BTN_TOOL_FINGER, input_dev->keybit);
 
-               input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0);
-               input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0);
+               if (wacom_wac->features.type != WACOM_21UX2) {
+                       input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0);
+                       input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0);
+               }
+
                input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
                wacom_setup_cintiq(wacom_wac);
                break;
@@ -1151,8 +1145,6 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
                __set_bit(BTN_2, input_dev->keybit);
                __set_bit(BTN_3, input_dev->keybit);
 
-               __set_bit(BTN_TOOL_FINGER, input_dev->keybit);
-
                input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0);
                input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
                /* fall through */
@@ -1170,7 +1162,6 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
        case INTUOS4S:
                for (i = 0; i < 7; i++)
                        __set_bit(BTN_0 + i, input_dev->keybit);
-               __set_bit(BTN_TOOL_FINGER, input_dev->keybit);
 
                input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
                wacom_setup_intuos(wacom_wac);
@@ -1295,6 +1286,12 @@ static const struct wacom_features wacom_features_0x65 =
 static const struct wacom_features wacom_features_0x69 =
        { "Wacom Bamboo1",        WACOM_PKGLEN_GRAPHIRE,   5104,  3712,  511,
          63, GRAPHIRE, WACOM_PENPRTN_RES, WACOM_PENPRTN_RES };
+static const struct wacom_features wacom_features_0x6A =
+       { "Wacom Bamboo1 4x6",    WACOM_PKGLEN_GRAPHIRE,  14760,  9225, 1023,
+         63, GRAPHIRE, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x6B =
+       { "Wacom Bamboo1 5x8",    WACOM_PKGLEN_GRAPHIRE,  21648, 13530, 1023,
+         63, GRAPHIRE, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0x20 =
        { "Wacom Intuos 4x5",     WACOM_PKGLEN_INTUOS,    12700, 10600, 1023,
          31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
@@ -1427,6 +1424,9 @@ static const struct wacom_features wacom_features_0x90 =
 static const struct wacom_features wacom_features_0x93 =
        { "Wacom ISDv4 93",       WACOM_PKGLEN_GRAPHIRE,  26202, 16325,  255,
          0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x97 =
+       { "Wacom ISDv4 97",       WACOM_PKGLEN_GRAPHIRE,  26202, 16325,  511,
+         0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0x9A =
        { "Wacom ISDv4 9A",       WACOM_PKGLEN_GRAPHIRE,  26202, 16325,  255,
          0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
@@ -1458,7 +1458,7 @@ static const struct wacom_features wacom_features_0xD3 =
        { "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN,     21648, 13530, 1023,
          63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0xD4 =
-       { "Wacom Bamboo Pen",     WACOM_PKGLEN_BBFUN,     14720,  9200,  255,
+       { "Wacom Bamboo Pen",     WACOM_PKGLEN_BBFUN,     14720,  9200, 1023,
          63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0xD6 =
        { "Wacom BambooPT 2FG 4x5", WACOM_PKGLEN_BBFUN,   14720,  9200, 1023,
@@ -1483,6 +1483,11 @@ static const struct wacom_features wacom_features_0x6004 =
        USB_DEVICE(USB_VENDOR_ID_WACOM, prod),                  \
        .driver_info = (kernel_ulong_t)&wacom_features_##prod
 
+#define USB_DEVICE_DETAILED(prod, class, sub, proto)                   \
+       USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_WACOM, prod, class, \
+                                     sub, proto),                      \
+       .driver_info = (kernel_ulong_t)&wacom_features_##prod
+
 #define USB_DEVICE_LENOVO(prod)                                        \
        USB_DEVICE(USB_VENDOR_ID_LENOVO, prod),                 \
        .driver_info = (kernel_ulong_t)&wacom_features_##prod
@@ -1506,6 +1511,8 @@ const struct usb_device_id wacom_ids[] = {
        { USB_DEVICE_WACOM(0x64) },
        { USB_DEVICE_WACOM(0x65) },
        { USB_DEVICE_WACOM(0x69) },
+       { USB_DEVICE_WACOM(0x6A) },
+       { USB_DEVICE_WACOM(0x6B) },
        { USB_DEVICE_WACOM(0x20) },
        { USB_DEVICE_WACOM(0x21) },
        { USB_DEVICE_WACOM(0x22) },
@@ -1545,7 +1552,13 @@ const struct usb_device_id wacom_ids[] = {
        { USB_DEVICE_WACOM(0xC5) },
        { USB_DEVICE_WACOM(0xC6) },
        { USB_DEVICE_WACOM(0xC7) },
-       { USB_DEVICE_WACOM(0xCE) },
+       /*
+        * DTU-2231 has two interfaces on the same configuration,
+        * only one is used.
+        */
+       { USB_DEVICE_DETAILED(0xCE, USB_CLASS_HID,
+                             USB_INTERFACE_SUBCLASS_BOOT,
+                             USB_INTERFACE_PROTOCOL_MOUSE) },
        { USB_DEVICE_WACOM(0xD0) },
        { USB_DEVICE_WACOM(0xD1) },
        { USB_DEVICE_WACOM(0xD2) },
@@ -1560,6 +1573,7 @@ const struct usb_device_id wacom_ids[] = {
        { USB_DEVICE_WACOM(0xCC) },
        { USB_DEVICE_WACOM(0x90) },
        { USB_DEVICE_WACOM(0x93) },
+       { USB_DEVICE_WACOM(0x97) },
        { USB_DEVICE_WACOM(0x9A) },
        { USB_DEVICE_WACOM(0x9F) },
        { USB_DEVICE_WACOM(0xE2) },
index 5196861..d507b9b 100644 (file)
@@ -967,17 +967,12 @@ static int __devinit ads7846_setup_pendown(struct spi_device *spi, struct ads784
                ts->get_pendown_state = pdata->get_pendown_state;
        } else if (gpio_is_valid(pdata->gpio_pendown)) {
 
-               err = gpio_request(pdata->gpio_pendown, "ads7846_pendown");
+               err = gpio_request_one(pdata->gpio_pendown, GPIOF_IN,
+                                      "ads7846_pendown");
                if (err) {
-                       dev_err(&spi->dev, "failed to request pendown GPIO%d\n",
-                               pdata->gpio_pendown);
-                       return err;
-               }
-               err = gpio_direction_input(pdata->gpio_pendown);
-               if (err) {
-                       dev_err(&spi->dev, "failed to setup pendown GPIO%d\n",
-                               pdata->gpio_pendown);
-                       gpio_free(pdata->gpio_pendown);
+                       dev_err(&spi->dev,
+                               "failed to request/setup pendown GPIO%d: %d\n",
+                               pdata->gpio_pendown, err);
                        return err;
                }
 
index fa8e56b..8034cbb 100644 (file)
@@ -164,7 +164,7 @@ static irqreturn_t atmel_wm97xx_channel_b_interrupt(int irq, void *dev_id)
 
                data = ac97c_readl(atmel_wm97xx, CBRHR);
                value = data & 0x0fff;
-               source = data & WM97XX_ADCSRC_MASK;
+               source = data & WM97XX_ADCSEL_MASK;
                pen_down = (data & WM97XX_PEN_DOWN) >> 8;
 
                if (source == WM97XX_ADCSEL_X)
@@ -442,6 +442,6 @@ static void __exit atmel_wm97xx_exit(void)
 }
 module_exit(atmel_wm97xx_exit);
 
-MODULE_AUTHOR("Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com>");
+MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>");
 MODULE_DESCRIPTION("wm97xx continuous touch driver for Atmel AT91 and AVR32");
 MODULE_LICENSE("GPL");
index 1e61387..ae00604 100644 (file)
 #define MXT_OBJECT_SIZE                6
 
 /* Object types */
-#define MXT_DEBUG_DIAGNOSTIC   37
-#define MXT_GEN_MESSAGE                5
-#define MXT_GEN_COMMAND                6
-#define MXT_GEN_POWER          7
-#define MXT_GEN_ACQUIRE                8
-#define MXT_TOUCH_MULTI                9
-#define MXT_TOUCH_KEYARRAY     15
-#define MXT_TOUCH_PROXIMITY    23
-#define MXT_PROCI_GRIPFACE     20
-#define MXT_PROCG_NOISE                22
-#define MXT_PROCI_ONETOUCH     24
-#define MXT_PROCI_TWOTOUCH     27
-#define MXT_PROCI_GRIP         40
-#define MXT_PROCI_PALM         41
-#define MXT_SPT_COMMSCONFIG    18
-#define MXT_SPT_GPIOPWM                19
-#define MXT_SPT_SELFTEST       25
-#define MXT_SPT_CTECONFIG      28
-#define MXT_SPT_USERDATA       38
-#define MXT_SPT_DIGITIZER      43
-#define MXT_SPT_MESSAGECOUNT   44
-
-/* MXT_GEN_COMMAND field */
+#define MXT_DEBUG_DIAGNOSTIC_T37       37
+#define MXT_GEN_MESSAGE_T5             5
+#define MXT_GEN_COMMAND_T6             6
+#define MXT_GEN_POWER_T7               7
+#define MXT_GEN_ACQUIRE_T8             8
+#define MXT_GEN_DATASOURCE_T53         53
+#define MXT_TOUCH_MULTI_T9             9
+#define MXT_TOUCH_KEYARRAY_T15         15
+#define MXT_TOUCH_PROXIMITY_T23                23
+#define MXT_TOUCH_PROXKEY_T52          52
+#define MXT_PROCI_GRIPFACE_T20         20
+#define MXT_PROCG_NOISE_T22            22
+#define MXT_PROCI_ONETOUCH_T24         24
+#define MXT_PROCI_TWOTOUCH_T27         27
+#define MXT_PROCI_GRIP_T40             40
+#define MXT_PROCI_PALM_T41             41
+#define MXT_PROCI_TOUCHSUPPRESSION_T42 42
+#define MXT_PROCI_STYLUS_T47           47
+#define MXT_PROCG_NOISESUPPRESSION_T48 48
+#define MXT_SPT_COMMSCONFIG_T18                18
+#define MXT_SPT_GPIOPWM_T19            19
+#define MXT_SPT_SELFTEST_T25           25
+#define MXT_SPT_CTECONFIG_T28          28
+#define MXT_SPT_USERDATA_T38           38
+#define MXT_SPT_DIGITIZER_T43          43
+#define MXT_SPT_MESSAGECOUNT_T44       44
+#define MXT_SPT_CTECONFIG_T46          46
+
+/* MXT_GEN_COMMAND_T6 field */
 #define MXT_COMMAND_RESET      0
 #define MXT_COMMAND_BACKUPNV   1
 #define MXT_COMMAND_CALIBRATE  2
 #define MXT_COMMAND_REPORTALL  3
 #define MXT_COMMAND_DIAGNOSTIC 5
 
-/* MXT_GEN_POWER field */
+/* MXT_GEN_POWER_T7 field */
 #define MXT_POWER_IDLEACQINT   0
 #define MXT_POWER_ACTVACQINT   1
 #define MXT_POWER_ACTV2IDLETO  2
 
-/* MXT_GEN_ACQUIRE field */
+/* MXT_GEN_ACQUIRE_T8 field */
 #define MXT_ACQUIRE_CHRGTIME   0
 #define MXT_ACQUIRE_TCHDRIFT   2
 #define MXT_ACQUIRE_DRIFTST    3
@@ -91,7 +97,7 @@
 #define MXT_ACQUIRE_ATCHCALST  6
 #define MXT_ACQUIRE_ATCHCALSTHR        7
 
-/* MXT_TOUCH_MULTI field */
+/* MXT_TOUCH_MULTI_T9 field */
 #define MXT_TOUCH_CTRL         0
 #define MXT_TOUCH_XORIGIN      1
 #define MXT_TOUCH_YORIGIN      2
 #define MXT_TOUCH_YEDGEDIST    29
 #define MXT_TOUCH_JUMPLIMIT    30
 
-/* MXT_PROCI_GRIPFACE field */
+/* MXT_PROCI_GRIPFACE_T20 field */
 #define MXT_GRIPFACE_CTRL      0
 #define MXT_GRIPFACE_XLOGRIP   1
 #define MXT_GRIPFACE_XHIGRIP   2
 #define MXT_NOISE_FREQ4                15
 #define MXT_NOISE_IDLEGCAFVALID        16
 
-/* MXT_SPT_COMMSCONFIG */
+/* MXT_SPT_COMMSCONFIG_T18 */
 #define MXT_COMMS_CTRL         0
 #define MXT_COMMS_CMD          1
 
-/* MXT_SPT_CTECONFIG field */
+/* MXT_SPT_CTECONFIG_T28 field */
 #define MXT_CTE_CTRL           0
 #define MXT_CTE_CMD            1
 #define MXT_CTE_MODE           2
 #define MXT_VOLTAGE_DEFAULT    2700000
 #define MXT_VOLTAGE_STEP       10000
 
-/* Define for MXT_GEN_COMMAND */
+/* Define for MXT_GEN_COMMAND_T6 */
 #define MXT_BOOT_VALUE         0xa5
 #define MXT_BACKUP_VALUE       0x55
 #define MXT_BACKUP_TIME                25      /* msec */
@@ -256,24 +262,31 @@ struct mxt_data {
 static bool mxt_object_readable(unsigned int type)
 {
        switch (type) {
-       case MXT_GEN_MESSAGE:
-       case MXT_GEN_COMMAND:
-       case MXT_GEN_POWER:
-       case MXT_GEN_ACQUIRE:
-       case MXT_TOUCH_MULTI:
-       case MXT_TOUCH_KEYARRAY:
-       case MXT_TOUCH_PROXIMITY:
-       case MXT_PROCI_GRIPFACE:
-       case MXT_PROCG_NOISE:
-       case MXT_PROCI_ONETOUCH:
-       case MXT_PROCI_TWOTOUCH:
-       case MXT_PROCI_GRIP:
-       case MXT_PROCI_PALM:
-       case MXT_SPT_COMMSCONFIG:
-       case MXT_SPT_GPIOPWM:
-       case MXT_SPT_SELFTEST:
-       case MXT_SPT_CTECONFIG:
-       case MXT_SPT_USERDATA:
+       case MXT_GEN_MESSAGE_T5:
+       case MXT_GEN_COMMAND_T6:
+       case MXT_GEN_POWER_T7:
+       case MXT_GEN_ACQUIRE_T8:
+       case MXT_GEN_DATASOURCE_T53:
+       case MXT_TOUCH_MULTI_T9:
+       case MXT_TOUCH_KEYARRAY_T15:
+       case MXT_TOUCH_PROXIMITY_T23:
+       case MXT_TOUCH_PROXKEY_T52:
+       case MXT_PROCI_GRIPFACE_T20:
+       case MXT_PROCG_NOISE_T22:
+       case MXT_PROCI_ONETOUCH_T24:
+       case MXT_PROCI_TWOTOUCH_T27:
+       case MXT_PROCI_GRIP_T40:
+       case MXT_PROCI_PALM_T41:
+       case MXT_PROCI_TOUCHSUPPRESSION_T42:
+       case MXT_PROCI_STYLUS_T47:
+       case MXT_PROCG_NOISESUPPRESSION_T48:
+       case MXT_SPT_COMMSCONFIG_T18:
+       case MXT_SPT_GPIOPWM_T19:
+       case MXT_SPT_SELFTEST_T25:
+       case MXT_SPT_CTECONFIG_T28:
+       case MXT_SPT_USERDATA_T38:
+       case MXT_SPT_DIGITIZER_T43:
+       case MXT_SPT_CTECONFIG_T46:
                return true;
        default:
                return false;
@@ -283,21 +296,28 @@ static bool mxt_object_readable(unsigned int type)
 static bool mxt_object_writable(unsigned int type)
 {
        switch (type) {
-       case MXT_GEN_COMMAND:
-       case MXT_GEN_POWER:
-       case MXT_GEN_ACQUIRE:
-       case MXT_TOUCH_MULTI:
-       case MXT_TOUCH_KEYARRAY:
-       case MXT_TOUCH_PROXIMITY:
-       case MXT_PROCI_GRIPFACE:
-       case MXT_PROCG_NOISE:
-       case MXT_PROCI_ONETOUCH:
-       case MXT_PROCI_TWOTOUCH:
-       case MXT_PROCI_GRIP:
-       case MXT_PROCI_PALM:
-       case MXT_SPT_GPIOPWM:
-       case MXT_SPT_SELFTEST:
-       case MXT_SPT_CTECONFIG:
+       case MXT_GEN_COMMAND_T6:
+       case MXT_GEN_POWER_T7:
+       case MXT_GEN_ACQUIRE_T8:
+       case MXT_TOUCH_MULTI_T9:
+       case MXT_TOUCH_KEYARRAY_T15:
+       case MXT_TOUCH_PROXIMITY_T23:
+       case MXT_TOUCH_PROXKEY_T52:
+       case MXT_PROCI_GRIPFACE_T20:
+       case MXT_PROCG_NOISE_T22:
+       case MXT_PROCI_ONETOUCH_T24:
+       case MXT_PROCI_TWOTOUCH_T27:
+       case MXT_PROCI_GRIP_T40:
+       case MXT_PROCI_PALM_T41:
+       case MXT_PROCI_TOUCHSUPPRESSION_T42:
+       case MXT_PROCI_STYLUS_T47:
+       case MXT_PROCG_NOISESUPPRESSION_T48:
+       case MXT_SPT_COMMSCONFIG_T18:
+       case MXT_SPT_GPIOPWM_T19:
+       case MXT_SPT_SELFTEST_T25:
+       case MXT_SPT_CTECONFIG_T28:
+       case MXT_SPT_DIGITIZER_T43:
+       case MXT_SPT_CTECONFIG_T46:
                return true;
        default:
                return false;
@@ -455,7 +475,7 @@ static int mxt_read_message(struct mxt_data *data,
        struct mxt_object *object;
        u16 reg;
 
-       object = mxt_get_object(data, MXT_GEN_MESSAGE);
+       object = mxt_get_object(data, MXT_GEN_MESSAGE_T5);
        if (!object)
                return -EINVAL;
 
@@ -597,8 +617,8 @@ static irqreturn_t mxt_interrupt(int irq, void *dev_id)
 
                reportid = message.reportid;
 
-               /* whether reportid is thing of MXT_TOUCH_MULTI */
-               object = mxt_get_object(data, MXT_TOUCH_MULTI);
+               /* whether reportid is thing of MXT_TOUCH_MULTI_T9 */
+               object = mxt_get_object(data, MXT_TOUCH_MULTI_T9);
                if (!object)
                        goto end;
 
@@ -635,7 +655,9 @@ static int mxt_check_reg_init(struct mxt_data *data)
                if (!mxt_object_writable(object->type))
                        continue;
 
-               for (j = 0; j < object->size + 1; j++) {
+               for (j = 0;
+                    j < (object->size + 1) * (object->instances + 1);
+                    j++) {
                        config_offset = index + j;
                        if (config_offset > pdata->config_length) {
                                dev_err(dev, "Not enough config data!\n");
@@ -644,7 +666,7 @@ static int mxt_check_reg_init(struct mxt_data *data)
                        mxt_write_object(data, object->type, j,
                                         pdata->config[config_offset]);
                }
-               index += object->size + 1;
+               index += (object->size + 1) * (object->instances + 1);
        }
 
        return 0;
@@ -678,31 +700,31 @@ static void mxt_handle_pdata(struct mxt_data *data)
        u8 voltage;
 
        /* Set touchscreen lines */
-       mxt_write_object(data, MXT_TOUCH_MULTI, MXT_TOUCH_XSIZE,
+       mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_XSIZE,
                        pdata->x_line);
-       mxt_write_object(data, MXT_TOUCH_MULTI, MXT_TOUCH_YSIZE,
+       mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_YSIZE,
                        pdata->y_line);
 
        /* Set touchscreen orient */
-       mxt_write_object(data, MXT_TOUCH_MULTI, MXT_TOUCH_ORIENT,
+       mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_ORIENT,
                        pdata->orient);
 
        /* Set touchscreen burst length */
-       mxt_write_object(data, MXT_TOUCH_MULTI,
+       mxt_write_object(data, MXT_TOUCH_MULTI_T9,
                        MXT_TOUCH_BLEN, pdata->blen);
 
        /* Set touchscreen threshold */
-       mxt_write_object(data, MXT_TOUCH_MULTI,
+       mxt_write_object(data, MXT_TOUCH_MULTI_T9,
                        MXT_TOUCH_TCHTHR, pdata->threshold);
 
        /* Set touchscreen resolution */
-       mxt_write_object(data, MXT_TOUCH_MULTI,
+       mxt_write_object(data, MXT_TOUCH_MULTI_T9,
                        MXT_TOUCH_XRANGE_LSB, (pdata->x_size - 1) & 0xff);
-       mxt_write_object(data, MXT_TOUCH_MULTI,
+       mxt_write_object(data, MXT_TOUCH_MULTI_T9,
                        MXT_TOUCH_XRANGE_MSB, (pdata->x_size - 1) >> 8);
-       mxt_write_object(data, MXT_TOUCH_MULTI,
+       mxt_write_object(data, MXT_TOUCH_MULTI_T9,
                        MXT_TOUCH_YRANGE_LSB, (pdata->y_size - 1) & 0xff);
-       mxt_write_object(data, MXT_TOUCH_MULTI,
+       mxt_write_object(data, MXT_TOUCH_MULTI_T9,
                        MXT_TOUCH_YRANGE_MSB, (pdata->y_size - 1) >> 8);
 
        /* Set touchscreen voltage */
@@ -715,7 +737,7 @@ static void mxt_handle_pdata(struct mxt_data *data)
                        voltage = (pdata->voltage - MXT_VOLTAGE_DEFAULT) /
                                MXT_VOLTAGE_STEP;
 
-               mxt_write_object(data, MXT_SPT_CTECONFIG,
+               mxt_write_object(data, MXT_SPT_CTECONFIG_T28,
                                MXT_CTE_VOLTAGE, voltage);
        }
 }
@@ -819,13 +841,13 @@ static int mxt_initialize(struct mxt_data *data)
        mxt_handle_pdata(data);
 
        /* Backup to memory */
-       mxt_write_object(data, MXT_GEN_COMMAND,
+       mxt_write_object(data, MXT_GEN_COMMAND_T6,
                        MXT_COMMAND_BACKUPNV,
                        MXT_BACKUP_VALUE);
        msleep(MXT_BACKUP_TIME);
 
        /* Soft reset */
-       mxt_write_object(data, MXT_GEN_COMMAND,
+       mxt_write_object(data, MXT_GEN_COMMAND_T6,
                        MXT_COMMAND_RESET, 1);
        msleep(MXT_RESET_TIME);
 
@@ -921,7 +943,7 @@ static int mxt_load_fw(struct device *dev, const char *fn)
        }
 
        /* Change to the bootloader mode */
-       mxt_write_object(data, MXT_GEN_COMMAND,
+       mxt_write_object(data, MXT_GEN_COMMAND_T6,
                        MXT_COMMAND_RESET, MXT_BOOT_VALUE);
        msleep(MXT_RESET_TIME);