Merge branch 'akpm' (patches from Andrew Morton)
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 14 Oct 2014 01:54:50 +0000 (03:54 +0200)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 14 Oct 2014 01:54:50 +0000 (03:54 +0200)
Merge second patch-bomb from Andrew Morton:
 - a few hotfixes
 - drivers/dma updates
 - MAINTAINERS updates
 - Quite a lot of lib/ updates
 - checkpatch updates
 - binfmt updates
 - autofs4
 - drivers/rtc/
 - various small tweaks to less used filesystems
 - ipc/ updates
 - kernel/watchdog.c changes

* emailed patches from Andrew Morton <akpm@linux-foundation.org>: (135 commits)
  mm: softdirty: enable write notifications on VMAs after VM_SOFTDIRTY cleared
  kernel/param: consolidate __{start,stop}___param[] in <linux/moduleparam.h>
  ia64: remove duplicate declarations of __per_cpu_start[] and __per_cpu_end[]
  frv: remove unused declarations of __start___ex_table and __stop___ex_table
  kvm: ensure hard lockup detection is disabled by default
  kernel/watchdog.c: control hard lockup detection default
  staging: rtl8192u: use %*pEn to escape buffer
  staging: rtl8192e: use %*pEn to escape buffer
  staging: wlan-ng: use %*pEhp to print SN
  lib80211: remove unused print_ssid()
  wireless: hostap: proc: print properly escaped SSID
  wireless: ipw2x00: print SSID via %*pE
  wireless: libertas: print esaped string via %*pE
  lib/vsprintf: add %*pE[achnops] format specifier
  lib / string_helpers: introduce string_escape_mem()
  lib / string_helpers: refactoring the test suite
  lib / string_helpers: move documentation to c-file
  include/linux: remove strict_strto* definitions
  arch/x86/mm/numa.c: fix boot failure when all nodes are hotpluggable
  fs: check bh blocknr earlier when searching lru
  ...

150 files changed:
Documentation/binfmt_misc.txt
Documentation/devicetree/bindings/i2c/ti,bq32k.txt [new file with mode: 0644]
Documentation/devicetree/bindings/i2c/trivial-devices.txt
Documentation/devicetree/bindings/rtc/dallas,ds1339.txt [new file with mode: 0644]
Documentation/devicetree/bindings/rtc/s3c-rtc.txt
Documentation/filesystems/autofs4.txt [new file with mode: 0644]
Documentation/printk-formats.txt
Documentation/sysctl/kernel.txt
MAINTAINERS
arch/arm/boot/dts/exynos3250.dtsi
arch/arm/mach-pxa/lpd270.c
arch/frv/mm/extable.c
arch/ia64/include/asm/sections.h
arch/x86/kernel/cpu/common.c
arch/x86/kernel/crash.c
arch/x86/kernel/kexec-bzimage64.c
arch/x86/kernel/kvm.c
arch/x86/mm/ioremap.c
arch/x86/mm/numa.c
arch/x86/purgatory/Makefile
drivers/base/dma-coherent.c
drivers/base/dma-contiguous.c
drivers/clk/Kconfig
drivers/clk/Makefile
drivers/clk/clk-rk808.c [new file with mode: 0644]
drivers/infiniband/ulp/srpt/ib_srpt.c
drivers/input/touchscreen/edt-ft5x06.c
drivers/memstick/host/r592.c
drivers/misc/altera-stapl/altera.c
drivers/net/wireless/hostap/hostap_proc.c
drivers/net/wireless/ipw2x00/ipw2100.c
drivers/net/wireless/ipw2x00/ipw2200.c
drivers/net/wireless/ipw2x00/libipw_rx.c
drivers/net/wireless/ipw2x00/libipw_wx.c
drivers/net/wireless/libertas/cfg.c
drivers/net/wireless/libertas/mesh.c
drivers/platform/x86/thinkpad_acpi.c
drivers/pnp/interface.c
drivers/rtc/Kconfig
drivers/rtc/Makefile
drivers/rtc/rtc-bq32k.c
drivers/rtc/rtc-cmos.c
drivers/rtc/rtc-ds1307.c
drivers/rtc/rtc-isl12022.c
drivers/rtc/rtc-max77686.c
drivers/rtc/rtc-max77802.c [new file with mode: 0644]
drivers/rtc/rtc-mpc5121.c
drivers/rtc/rtc-pcf8563.c
drivers/rtc/rtc-pcf8583.c
drivers/rtc/rtc-rk808.c [new file with mode: 0644]
drivers/rtc/rtc-rs5c372.c
drivers/rtc/rtc-s3c.c
drivers/s390/cio/chp.c
drivers/scsi/ips.c
drivers/scsi/scsi_debug.c
drivers/staging/rtl8188eu/os_dep/rtw_android.c
drivers/staging/rtl8192e/rtllib.h
drivers/staging/rtl8192u/ieee80211/ieee80211.h
drivers/staging/wlan-ng/prism2sta.c
drivers/thermal/thermal_core.c
drivers/video/fbdev/pvr2fb.c
drivers/video/fbdev/s3c2410fb.c
drivers/video/fbdev/sis/sis_main.c
drivers/video/fbdev/sm501fb.c
fs/affs/amigaffs.c
fs/affs/file.c
fs/affs/inode.c
fs/affs/super.c
fs/autofs4/autofs_i.h
fs/autofs4/dev-ioctl.c
fs/autofs4/expire.c
fs/autofs4/root.c
fs/befs/btree.c
fs/binfmt_misc.c
fs/buffer.c
fs/cifs/cifs_dfs_ref.c
fs/cifs/connect.c
fs/coredump.c
fs/fat/misc.c
fs/hfs/hfs_fs.h
fs/isofs/inode.c
fs/ncpfs/dir.c
fs/nilfs2/file.c
fs/nilfs2/inode.c
fs/nilfs2/ioctl.c
fs/nilfs2/nilfs.h
fs/nilfs2/segment.c
fs/nilfs2/super.c
fs/nilfs2/the_nilfs.h
fs/ocfs2/cluster/heartbeat.c
fs/ocfs2/cluster/masklog.c
fs/omfs/inode.c
fs/omfs/omfs_fs.h
fs/proc/task_mmu.c
fs/reiserfs/journal.c
fs/ufs/balloc.c
include/asm-generic/pgtable.h
include/linux/cma.h
include/linux/compiler-gcc5.h [new file with mode: 0644]
include/linux/kernel.h
include/linux/kexec.h
include/linux/list.h
include/linux/mm.h
include/linux/moduleparam.h
include/linux/nmi.h
include/linux/prio_heap.h [deleted file]
include/linux/rbtree_augmented.h
include/linux/signal.h
include/linux/string.h
include/linux/string_helpers.h
include/net/lib80211.h
init/Kconfig
init/initramfs.c
init/main.c
ipc/compat.c
ipc/ipc_sysctl.c
ipc/shm.c
ipc/util.c
kernel/debug/kdb/kdb_bp.c
kernel/kallsyms.c
kernel/kexec.c
kernel/params.c
kernel/printk/printk.c
kernel/resource.c
kernel/watchdog.c
lib/Kconfig.debug
lib/Makefile
lib/dynamic_debug.c
lib/prio_heap.c [deleted file]
lib/string.c
lib/string_helpers.c
lib/test-string_helpers.c
lib/textsearch.c
lib/vsprintf.c
mm/cma.c
mm/memory.c
mm/mmap.c
mm/mprotect.c
mm/slab.c
net/batman-adv/gateway_common.c
net/netfilter/ipvs/ip_vs_ftp.c
net/netfilter/nf_conntrack_ftp.c
net/netfilter/nf_conntrack_sip.c
net/netfilter/nf_log.c
net/netfilter/nf_nat_sip.c
net/wireless/lib80211.c
scripts/checkpatch.pl
scripts/headers_install.sh
scripts/sortextable.h
scripts/spelling.txt [new file with mode: 0644]

index c1ed6948ba80e7f16fd313b9bab431118e18f31e..6b1de70583715d7728a7a31b4612564b0178679b 100644 (file)
@@ -15,39 +15,50 @@ First you must mount binfmt_misc:
        mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc 
 
 To actually register a new binary type, you have to set up a string looking like
-:name:type:offset:magic:mask:interpreter:flags (where you can choose the ':' upon
-your needs) and echo it to /proc/sys/fs/binfmt_misc/register.
+:name:type:offset:magic:mask:interpreter:flags (where you can choose the ':'
+upon your needs) and echo it to /proc/sys/fs/binfmt_misc/register.
+
 Here is what the fields mean:
  - 'name' is an identifier string. A new /proc file will be created with this
-   name below /proc/sys/fs/binfmt_misc
+   name below /proc/sys/fs/binfmt_misc; cannot contain slashes '/' for obvious
+   reasons.
  - 'type' is the type of recognition. Give 'M' for magic and 'E' for extension.
  - 'offset' is the offset of the magic/mask in the file, counted in bytes. This
-   defaults to 0 if you omit it (i.e. you write ':name:type::magic...')
+   defaults to 0 if you omit it (i.e. you write ':name:type::magic...'). Ignored
+   when using filename extension matching.
  - 'magic' is the byte sequence binfmt_misc is matching for. The magic string
-   may contain hex-encoded characters like \x0a or \xA4. In a shell environment
-   you will have to write \\x0a to prevent the shell from eating your \.
+   may contain hex-encoded characters like \x0a or \xA4. Note that you must
+   escape any NUL bytes; parsing halts at the first one. In a shell environment
+   you might have to write \\x0a to prevent the shell from eating your \.
    If you chose filename extension matching, this is the extension to be
    recognised (without the '.', the \x0a specials are not allowed). Extension
-   matching is case sensitive!
+   matching is case sensitive, and slashes '/' are not allowed!
  - 'mask' is an (optional, defaults to all 0xff) mask. You can mask out some
    bits from matching by supplying a string like magic and as long as magic.
-   The mask is anded with the byte sequence of the file.
+   The mask is anded with the byte sequence of the file. Note that you must
+   escape any NUL bytes; parsing halts at the first one. Ignored when using
+   filename extension matching.
  - 'interpreter' is the program that should be invoked with the binary as first
    argument (specify the full path)
  - 'flags' is an optional field that controls several aspects of the invocation
-   of the interpreter. It is a string of capital letters, each controls a certain
-   aspect. The following flags are supported -
-      'P' - preserve-argv[0].  Legacy behavior of binfmt_misc is to overwrite the
-            original argv[0] with the full path to the binary.  When this flag is
-            included, binfmt_misc will add an argument to the argument vector for
-            this purpose, thus preserving the original argv[0].
+   of the interpreter. It is a string of capital letters, each controls a
+   certain aspect. The following flags are supported -
+      'P' - preserve-argv[0]. Legacy behavior of binfmt_misc is to overwrite
+            the original argv[0] with the full path to the binary. When this
+            flag is included, binfmt_misc will add an argument to the argument
+            vector for this purpose, thus preserving the original argv[0].
+            e.g. If your interp is set to /bin/foo and you run `blah` (which is
+            in /usr/local/bin), then the kernel will execute /bin/foo with
+            argv[] set to ["/bin/foo", "/usr/local/bin/blah", "blah"].  The
+            interp has to be aware of this so it can execute /usr/local/bin/blah
+            with argv[] set to ["blah"].
       'O' - open-binary. Legacy behavior of binfmt_misc is to pass the full path
             of the binary to the interpreter as an argument. When this flag is
             included, binfmt_misc will open the file for reading and pass its
             descriptor as an argument, instead of the full path, thus allowing
-            the interpreter to execute non-readable binaries. This feature should
-            be used with care - the interpreter has to be trusted not to emit
-            the contents of the non-readable binary.
+            the interpreter to execute non-readable binaries. This feature
+            should be used with care - the interpreter has to be trusted not to
+            emit the contents of the non-readable binary.
       'C' - credentials. Currently, the behavior of binfmt_misc is to calculate
             the credentials and security token of the new process according to
             the interpreter. When this flag is included, these attributes are
@@ -58,7 +69,7 @@ Here is what the fields mean:
 
 
 There are some restrictions:
- - the whole register string may not exceed 255 characters
+ - the whole register string may not exceed 1920 characters
  - the magic must reside in the first 128 bytes of the file, i.e.
    offset+size(magic) has to be less than 128
  - the interpreter string may not exceed 127 characters
@@ -110,7 +121,4 @@ passes it the full filename (or the file descriptor) to use.  Using $PATH can
 cause unexpected behaviour and can be a security hazard.
 
 
-There is a web page about binfmt_misc at
-http://www.tat.physik.uni-tuebingen.de
-
 Richard G√ľnther <rguenth@tat.physik.uni-tuebingen.de>
diff --git a/Documentation/devicetree/bindings/i2c/ti,bq32k.txt b/Documentation/devicetree/bindings/i2c/ti,bq32k.txt
new file mode 100644 (file)
index 0000000..e204906
--- /dev/null
@@ -0,0 +1,18 @@
+* TI BQ32000                I2C Serial Real-Time Clock
+
+Required properties:
+- compatible: Should contain "ti,bq32000".
+- reg: I2C address for chip
+
+Optional properties:
+- trickle-resistor-ohms : Selected resistor for trickle charger
+       Values usable are 1120 and 20180
+       Should be given if trickle charger should be enabled
+- trickle-diode-disable : Do not use internal trickle charger diode
+       Should be given if internal trickle charger diode should be disabled
+Example:
+       bq32000: rtc@68 {
+               compatible = "ti,bq32000";
+               trickle-resistor-ohms = <1120>;
+               reg = <0x68>;
+       };
index 5af3d9df6ecb05c5da5dbeff969bcfba18a09a9a..fbde415078e6845cc5ff862a758959d64810c316 100644 (file)
@@ -35,7 +35,6 @@ catalyst,24c32                i2c serial eeprom
 cirrus,cs42l51         Cirrus Logic CS42L51 audio codec
 dallas,ds1307          64 x 8, Serial, I2C Real-Time Clock
 dallas,ds1338          I2C RTC with 56-Byte NV RAM
-dallas,ds1339          I2C Serial Real-Time Clock
 dallas,ds1340          I2C RTC with Trickle Charger
 dallas,ds1374          I2C, 32-Bit Binary Counter Watchdog RTC with Trickle Charger and Reset Input/Output
 dallas,ds1631          High-Precision Digital Thermometer
diff --git a/Documentation/devicetree/bindings/rtc/dallas,ds1339.txt b/Documentation/devicetree/bindings/rtc/dallas,ds1339.txt
new file mode 100644 (file)
index 0000000..916f576
--- /dev/null
@@ -0,0 +1,18 @@
+* Dallas DS1339                I2C Serial Real-Time Clock
+
+Required properties:
+- compatible: Should contain "dallas,ds1339".
+- reg: I2C address for chip
+
+Optional properties:
+- trickle-resistor-ohms : Selected resistor for trickle charger
+       Values usable for ds1339 are 250, 2000, 4000
+       Should be given if trickle charger should be enabled
+- trickle-diode-disable : Do not use internal trickle charger diode
+       Should be given if internal trickle charger diode should be disabled
+Example:
+       ds1339: rtc@68 {
+               compatible = "dallas,ds1339";
+               trickle-resistor-ohms = <250>;
+               reg = <0x68>;
+       };
index 7ac7259fe9ea9d61eb208064c364b0998221aa11..ab757b84daa7edab473d2ec907cb0da3386d0b0a 100644 (file)
@@ -3,7 +3,10 @@
 Required properties:
 - compatible: should be one of the following.
     * "samsung,s3c2410-rtc" - for controllers compatible with s3c2410 rtc.
+    * "samsung,s3c2416-rtc" - for controllers compatible with s3c2416 rtc.
+    * "samsung,s3c2443-rtc" - for controllers compatible with s3c2443 rtc.
     * "samsung,s3c6410-rtc" - for controllers compatible with s3c6410 rtc.
+    * "samsung,exynos3250-rtc" - for controllers compatible with exynos3250 rtc.
 - reg: physical base address of the controller and length of memory mapped
   region.
 - interrupts: Two interrupt numbers to the cpu should be specified. First
diff --git a/Documentation/filesystems/autofs4.txt b/Documentation/filesystems/autofs4.txt
new file mode 100644 (file)
index 0000000..39d02e1
--- /dev/null
@@ -0,0 +1,520 @@
+<head>
+<style> p { max-width:50em} ol, ul {max-width: 40em}</style>
+</head>
+
+autofs - how it works
+=====================
+
+Purpose
+-------
+
+The goal of autofs is to provide on-demand mounting and race free
+automatic unmounting of various other filesystems.  This provides two
+key advantages:
+
+1. There is no need to delay boot until all filesystems that
+   might be needed are mounted.  Processes that try to access those
+   slow filesystems might be delayed but other processes can
+   continue freely.  This is particularly important for
+   network filesystems (e.g. NFS) or filesystems stored on
+   media with a media-changing robot.
+
+2. The names and locations of filesystems can be stored in
+   a remote database and can change at any time.  The content
+   in that data base at the time of access will be used to provide
+   a target for the access.  The interpretation of names in the
+   filesystem can even be programmatic rather than database-backed,
+   allowing wildcards for example, and can vary based on the user who
+   first accessed a name.
+
+Context
+-------
+
+The "autofs4" filesystem module is only one part of an autofs system.
+There also needs to be a user-space program which looks up names
+and mounts filesystems.  This will often be the "automount" program,
+though other tools including "systemd" can make use of "autofs4".
+This document describes only the kernel module and the interactions
+required with any user-space program.  Subsequent text refers to this
+as the "automount daemon" or simply "the daemon".
+
+"autofs4" is a Linux kernel module with provides the "autofs"
+filesystem type.  Several "autofs" filesystems can be mounted and they
+can each be managed separately, or all managed by the same daemon.
+
+Content
+-------
+
+An autofs filesystem can contain 3 sorts of objects: directories,
+symbolic links and mount traps.  Mount traps are directories with
+extra properties as described in the next section.
+
+Objects can only be created by the automount daemon: symlinks are
+created with a regular `symlink` system call, while directories and
+mount traps are created with `mkdir`.  The determination of whether a
+directory should be a mount trap or not is quite _ad hoc_, largely for
+historical reasons, and is determined in part by the
+*direct*/*indirect*/*offset* mount options, and the *maxproto* mount option.
+
+If neither the *direct* or *offset* mount options are given (so the
+mount is considered to be *indirect*), then the root directory is
+always a regular directory, otherwise it is a mount trap when it is
+empty and a regular directory when not empty.  Note that *direct* and
+*offset* are treated identically so a concise summary is that the root
+directory is a mount trap only if the filesystem is mounted *direct*
+and the root is empty.
+
+Directories created in the root directory are mount traps only if the
+filesystem is mounted  *indirect* and they are empty.
+
+Directories further down the tree depend on the *maxproto* mount
+option and particularly whether it is less than five or not.
+When *maxproto* is five, no directories further down the
+tree are ever mount traps, they are always regular directories.  When
+the *maxproto* is four (or three), these directories are mount traps
+precisely when they are empty.
+
+So: non-empty (i.e. non-leaf) directories are never mount traps. Empty
+directories are sometimes mount traps, and sometimes not depending on
+where in the tree they are (root, top level, or lower), the *maxproto*,
+and whether the mount was *indirect* or not.
+
+Mount Traps
+---------------
+
+A core element of the implementation of autofs is the Mount Traps
+which are provided by the Linux VFS.  Any directory provided by a
+filesystem can be designated as a trap.  This involves two separate
+features that work together to allow autofs to do its job.
+
+**DCACHE_NEED_AUTOMOUNT**
+
+If a dentry has the DCACHE_NEED_AUTOMOUNT flag set (which gets set if
+the inode has S_AUTOMOUNT set, or can be set directly) then it is
+(potentially) a mount trap.  Any access to this directory beyond a
+"`stat`" will (normally) cause the `d_op->d_automount()` dentry operation
+to be called. The task of this method is to find the filesystem that
+should be mounted on the directory and to return it.  The VFS is
+responsible for actually mounting the root of this filesystem on the
+directory.
+
+autofs doesn't find the filesystem itself but sends a message to the
+automount daemon asking it to find and mount the filesystem.  The
+autofs `d_automount` method then waits for the daemon to report that
+everything is ready.  It will then return "`NULL`" indicating that the
+mount has already happened.  The VFS doesn't try to mount anything but
+follows down the mount that is already there.
+
+This functionality is sufficient for some users of mount traps such
+as NFS which creates traps so that mountpoints on the server can be
+reflected on the client.  However it is not sufficient for autofs.  As
+mounting onto a directory is considered to be "beyond a `stat`", the
+automount daemon would not be able to mount a filesystem on the 'trap'
+directory without some way to avoid getting caught in the trap.  For
+that purpose there is another flag.
+
+**DCACHE_MANAGE_TRANSIT**
+
+If a dentry has DCACHE_MANAGE_TRANSIT set then two very different but
+related behaviors are invoked, both using the `d_op->d_manage()`
+dentry operation.
+
+Firstly, before checking to see if any filesystem is mounted on the
+directory, d_manage() will be called with the `rcu_walk` parameter set
+to `false`.  It may return one of three things:
+
+-  A return value of zero indicates that there is nothing special
+   about this dentry and normal checks for mounts and automounts
+   should proceed.
+
+   autofs normally returns zero, but first waits for any
+   expiry (automatic unmounting of the mounted filesystem) to
+   complete.  This avoids races.
+
+-  A return value of `-EISDIR` tells the VFS to ignore any mounts
+   on the directory and to not consider calling `->d_automount()`.
+   This effectively disables the **DCACHE_NEED_AUTOMOUNT** flag
+   causing the directory not be a mount trap after all.
+
+   autofs returns this if it detects that the process performing the
+   lookup is the automount daemon and that the mount has been
+   requested but has not yet completed.  How it determines this is
+   discussed later.  This allows the automount daemon not to get
+   caught in the mount trap.
+
+   There is a subtlety here.  It is possible that a second autofs
+   filesystem can be mounted below the first and for both of them to
+   be managed by the same daemon.  For the daemon to be able to mount
+   something on the second it must be able to "walk" down past the
+   first.  This means that d_manage cannot *always* return -EISDIR for
+   the automount daemon.  It must only return it when a mount has
+   been requested, but has not yet completed.
+
+   `d_manage` also returns `-EISDIR` if the dentry shouldn't be a
+   mount trap, either because it is a symbolic link or because it is
+   not empty.
+
+-  Any other negative value is treated as an error and returned
+   to the caller.
+
+   autofs can return
+
+   - -ENOENT if the automount daemon failed to mount anything,
+   - -ENOMEM if it ran out of memory,
+   - -EINTR if a signal arrived while waiting for expiry to
+     complete
+   - or any other error sent down by the automount daemon.
+
+
+The second use case only occurs during an "RCU-walk" and so `rcu_walk`
+will be set.
+
+An RCU-walk is a fast and lightweight process for walking down a
+filename path (i.e. it is like running on tip-toes).  RCU-walk cannot
+cope with all situations so when it finds a difficulty it falls back
+to "REF-walk", which is slower but more robust.
+
+RCU-walk will never call `->d_automount`; the filesystems must already
+be mounted or RCU-walk cannot handle the path.
+To determine if a mount-trap is safe for RCU-walk mode it calls
+`->d_manage()` with `rcu_walk` set to `true`.
+
+In this case `d_manage()` must avoid blocking and should avoid taking
+spinlocks if at all possible.  Its sole purpose is to determine if it
+would be safe to follow down into any mounted directory and the only
+reason that it might not be is if an expiry of the mount is
+underway.
+
+In the `rcu_walk` case, `d_manage()` cannot return -EISDIR to tell the
+VFS that this is a directory that doesn't require d_automount.  If
+`rcu_walk` sees a dentry with DCACHE_NEED_AUTOMOUNT set but nothing
+mounted, it *will* fall back to REF-walk.  `d_manage()` cannot make the
+VFS remain in RCU-walk mode, but can only tell it to get out of
+RCU-walk mode by returning `-ECHILD`.
+
+So `d_manage()`, when called with `rcu_walk` set, should either return
+-ECHILD if there is any reason to believe it is unsafe to end the
+mounted filesystem, and otherwise should return 0.
+
+autofs will return `-ECHILD` if an expiry of the filesystem has been
+initiated or is being considered, otherwise it returns 0.
+
+
+Mountpoint expiry
+-----------------
+
+The VFS has a mechansim for automatically expiring unused mounts,
+much as it can expire any unused dentry information from the dcache.
+This is guided by the MNT_SHRINKABLE flag.  This  only applies to
+mounts that were created by `d_automount()` returning a filesystem to be
+mounted.  As autofs doesn't return such a filesystem but leaves the
+mounting to the automount daemon, it must involve the automount daemon
+in unmounting as well.  This also means that autofs has more control
+of expiry.
+
+The VFS also supports "expiry" of mounts using the MNT_EXPIRE flag to
+the `umount` system call.  Unmounting with MNT_EXPIRE will fail unless
+a previous attempt had been made, and the filesystem has been inactive
+and untouched since that previous attempt.  autofs4 does not depend on
+this but has its own internal tracking of whether filesystems were
+recently used.  This allows individual names in the autofs directory
+to expire separately.
+
+With version 4 of the protocol, the automount daemon can try to
+unmount any filesystems mounted on the autofs filesystem or remove any
+symbolic links or empty directories any time it likes.  If the unmount
+or removal is successful the filesystem will be returned to the state
+it was before the mount or creation, so that any access of the name
+will trigger normal auto-mount processing.  In particlar, `rmdir` and
+`unlink` do not leave negative entries in the dcache as a normal
+filesystem would, so an attempt to access a recently-removed object is
+passed to autofs for handling.
+
+With version 5, this is not safe except for unmounting from top-level
+directories.  As lower-level directories are never mount traps, other
+processes will see an empty directory as soon as the filesystem is
+unmounted.  So it is generally safest to use the autofs expiry
+protocol described below.
+
+Normally the daemon only wants to remove entries which haven't been
+used for a while.  For this purpose autofs maintains a "`last_used`"
+time stamp on each directory or symlink.  For symlinks it genuinely
+does record the last time the symlink was "used" or followed to find
+out where it points to.  For directories the field is a slight
+misnomer.  It actually records the last time that autofs checked if
+the directory or one of its descendents was busy and found that it
+was.  This is just as useful and doesn't require updating the field so
+often.
+
+The daemon is able to ask autofs if anything is due to be expired,
+using an `ioctl` as discussed later.  For a *direct* mount, autofs
+considers if the entire mount-tree can be unmounted or not.  For an
+*indirect* mount, autofs considers each of the names in the top level
+directory to determine if any of those can be unmounted and cleaned
+up.
+
+There is an option with indirect mounts to consider each of the leaves
+that has been mounted on instead of considering the top-level names.
+This is intended for compatability with version 4 of autofs and should
+be considered as deprecated.
+
+When autofs considers a directory it checks the `last_used` time and
+compares it with the "timeout" value set when the filesystem was
+mounted, though this check is ignored in some cases. It also checks if
+the directory or anything below it is in use.  For symbolic links,
+only the `last_used` time is ever considered.
+
+If both appear to support expiring the directory or symlink, an action
+is taken.
+
+There are two ways to ask autofs to consider expiry.  The first is to
+use the **AUTOFS_IOC_EXPIRE** ioctl.  This only works for indirect
+mounts.  If it finds something in the root directory to expire it will
+return the name of that thing.  Once a name has been returned the
+automount daemon needs to unmount any filesystems mounted below the
+name normally.  As described above, this is unsafe for non-toplevel
+mounts in a version-5 autofs.  For this reason the current `automountd`
+does not use this ioctl.
+
+The second mechanism uses either the **AUTOFS_DEV_IOCTL_EXPIRE_CMD** or
+the **AUTOFS_IOC_EXPIRE_MULTI** ioctl.  This will work for both direct and
+indirect mounts.  If it selects an object to expire, it will notify
+the daemon using the notification mechanism described below.  This
+will block until the daemon acknowledges the expiry notification.
+This implies that the "`EXPIRE`" ioctl must be sent from a different
+thread than the one which handles notification.
+
+While the ioctl is blocking, the entry is marked as "expiring" and
+`d_manage` will block until the daemon affirms that the unmount has
+completed (together with removing any directories that might have been
+necessary), or has been aborted.
+
+Communicating with autofs: detecting the daemon
+-----------------------------------------------
+
+There are several forms of communication between the automount daemon
+and the filesystem.  As we have already seen, the daemon can create and
+remove directories and symlinks using normal filesystem operations.
+autofs knows whether a process requesting some operation is the daemon
+or not based on its process-group id number (see getpgid(1)).
+
+When an autofs filesystem it mounted the pgid of the mounting
+processes is recorded unless the "pgrp=" option is given, in which
+case that number is recorded instead.  Any request arriving from a
+process in that process group is considered to come from the daemon.
+If the daemon ever has to be stopped and restarted a new pgid can be
+provided through an ioctl as will be described below.
+
+Communicating with autofs: the event pipe
+-----------------------------------------
+
+When an autofs filesystem is mounted, the 'write' end of a pipe must
+be passed using the 'fd=' mount option.  autofs will write
+notification messages to this pipe for the daemon to respond to.
+For version 5, the format of the message is:
+
+        struct autofs_v5_packet {
+                int proto_version;                /* Protocol version */
+                int type;                        /* Type of packet */
+                autofs_wqt_t wait_queue_token;
+                __u32 dev;
+                __u64 ino;
+                __u32 uid;
+                __u32 gid;
+                __u32 pid;
+                __u32 tgid;
+                __u32 len;
+                char name[NAME_MAX+1];
+        };
+
+where the type is one of
+
+        autofs_ptype_missing_indirect
+        autofs_ptype_expire_indirect
+        autofs_ptype_missing_direct
+        autofs_ptype_expire_direct
+
+so messages can indicate that a name is missing (something tried to
+access it but it isn't there) or that it has been selected for expiry.
+
+The pipe will be set to "packet mode" (equivalent to passing
+`O_DIRECT`) to _pipe2(2)_ so that a read from the pipe will return at
+most one packet, and any unread portion of a packet will be discarded.
+
+The `wait_queue_token` is a unique number which can identify a
+particular request to be acknowledged.  When a message is sent over
+the pipe the affected dentry is marked as either "active" or
+"expiring" and other accesses to it block until the message is
+acknowledged using one of the ioctls below and the relevant
+`wait_queue_token`.
+
+Communicating with autofs: root directory ioctls
+------------------------------------------------
+
+The root directory of an autofs filesystem will respond to a number of
+ioctls.   The process issuing the ioctl must have the CAP_SYS_ADMIN
+capability, or must be the automount daemon.
+
+The available ioctl commands are:
+
+- **AUTOFS_IOC_READY**: a notification has been handled.  The argument
+    to the ioctl command is the "wait_queue_token" number
+    corresponding to the notification being acknowledged.
+- **AUTOFS_IOC_FAIL**: similar to above, but indicates failure with
+    the error code `ENOENT`.
+- **AUTOFS_IOC_CATATONIC**: Causes the autofs to enter "catatonic"
+    mode meaning that it stops sending notifications to the daemon.
+    This mode is also entered if a write to the pipe fails.
+- **AUTOFS_IOC_PROTOVER**:  This returns the protocol version in use.
+- **AUTOFS_IOC_PROTOSUBVER**: Returns the protocol sub-version which
+    is really a version number for the implementation.  It is
+    currently 2.
+- **AUTOFS_IOC_SETTIMEOUT**:  This passes a pointer to an unsigned
+    long.  The value is used to set the timeout for expiry, and
+    the current timeout value is stored back through the pointer.
+- **AUTOFS_IOC_ASKUMOUNT**:  Returns, in the pointed-to `int`, 1 if
+    the filesystem could be unmounted.  This is only a hint as
+    the situation could change at any instant.  This call can be
+    use to avoid a more expensive full unmount attempt.
+- **AUTOFS_IOC_EXPIRE**: as described above, this asks if there is
+    anything suitable to expire.  A pointer to a packet:
+
+        struct autofs_packet_expire_multi {
+                int proto_version;              /* Protocol version */
+                int type;                       /* Type of packet */
+                autofs_wqt_t wait_queue_token;
+                int len;
+                char name[NAME_MAX+1];
+        };
+
+     is required.  This is filled in with the name of something
+     that can be unmounted or removed.  If nothing can be expired,
+     `errno` is set to `EAGAIN`.  Even though a `wait_queue_token`
+     is present in the structure, no "wait queue" is established
+     and no acknowledgment is needed.
+- **AUTOFS_IOC_EXPIRE_MULTI**:  This is similar to
+     **AUTOFS_IOC_EXPIRE** except that it causes notification to be
+     sent to the daemon, and it blocks until the daemon acknowledges.
+     The argument is an integer which can contain two different flags.
+
+     **AUTOFS_EXP_IMMEDIATE** causes `last_used` time to be ignored
+     and objects are expired if the are not in use.
+
+     **AUTOFS_EXP_LEAVES** will select a leaf rather than a top-level
+     name to expire.  This is only safe when *maxproto* is 4.
+
+Communicating with autofs: char-device ioctls
+---------------------------------------------
+
+It is not always possible to open the root of an autofs filesystem,
+particularly a *direct* mounted filesystem.  If the automount daemon
+is restarted there is no way for it to regain control of existing
+mounts using any of the above communication channels.  To address this
+need there is a "miscellaneous" character device (major 10, minor 235)
+which can be used to communicate directly with the autofs filesystem.
+It requires CAP_SYS_ADMIN for access.
+
+The `ioctl`s that can be used on this device are described in a separate
+document `autofs4-mount-control.txt`, and are summarized briefly here.
+Each ioctl is passed a pointer to an `autofs_dev_ioctl` structure:
+
+        struct autofs_dev_ioctl {
+                __u32 ver_major;
+                __u32 ver_minor;
+                __u32 size;             /* total size of data passed in
+                                         * including this struct */
+                __s32 ioctlfd;          /* automount command fd */
+
+                __u32 arg1;             /* Command parameters */
+                __u32 arg2;
+
+                char path[0];
+        };
+
+For the **OPEN_MOUNT** and **IS_MOUNTPOINT** commands, the target
+filesystem is identified by the `path`.  All other commands identify
+the filesystem by the `ioctlfd` which is a file descriptor open on the
+root, and which can be returned by **OPEN_MOUNT**.
+
+The `ver_major` and `ver_minor` are in/out parameters which check that
+the requested version is supported, and report the maximum version
+that the kernel module can support.
+
+Commands are:
+
+- **AUTOFS_DEV_IOCTL_VERSION_CMD**: does nothing, except validate and
+    set version numbers.
+- **AUTOFS_DEV_IOCTL_OPENMOUNT_CMD**: return an open file descriptor
+    on the root of an autofs filesystem.  The filesystem is identified
+    by name and device number, which is stored in `arg1`.  Device
+    numbers for existing filesystems can be found in
+    `/proc/self/mountinfo`.
+- **AUTOFS_DEV_IOCTL_CLOSEMOUNT_CMD**: same as `close(ioctlfd)`.
+- **AUTOFS_DEV_IOCTL_SETPIPEFD_CMD**: if the  filesystem is in
+    catatonic mode, this can provide the write end of a new pipe
+    in `arg1` to re-establish communication with a daemon.  The
+    process group of the calling process is used to identify the
+    daemon.
+- **AUTOFS_DEV_IOCTL_REQUESTER_CMD**: `path` should be a
+    name within the filesystem that has been auto-mounted on.
+    arg1 is the dev number of the underlying autofs.  On successful
+    return, `arg1` and `arg2` will be the UID and GID of the process
+    which triggered that mount.
+
+- **AUTOFS_DEV_IOCTL_ISMOUNTPOINT_CMD**: Check if path is a
+    mountpoint of a particular type - see separate documentation for
+    details.
+
+- **AUTOFS_DEV_IOCTL_PROTOVER_CMD**:
+- **AUTOFS_DEV_IOCTL_PROTOSUBVER_CMD**:
+- **AUTOFS_DEV_IOCTL_READY_CMD**:
+- **AUTOFS_DEV_IOCTL_FAIL_CMD**:
+- **AUTOFS_DEV_IOCTL_CATATONIC_CMD**:
+- **AUTOFS_DEV_IOCTL_TIMEOUT_CMD**:
+- **AUTOFS_DEV_IOCTL_EXPIRE_CMD**:
+- **AUTOFS_DEV_IOCTL_ASKUMOUNT_CMD**:  These all have the same
+    function as the similarly named **AUTOFS_IOC** ioctls, except
+    that **FAIL** can be given an explicit error number in `arg1`
+    instead of assuming `ENOENT`, and this **EXPIRE** command
+    corresponds to **AUTOFS_IOC_EXPIRE_MULTI**.
+
+Catatonic mode
+--------------
+
+As mentioned, an autofs mount can enter "catatonic" mode.  This
+happens if a write to the notification pipe fails, or if it is
+explicitly requested by an `ioctl`.
+
+When entering catatonic mode, the pipe is closed and any pending
+notifications are acknowledged with the error `ENOENT`.
+
+Once in catatonic mode attempts to access non-existing names will
+result in `ENOENT` while attempts to access existing directories will
+be treated in the same way as if they came from the daemon, so mount
+traps will not fire.
+
+When the filesystem is mounted a _uid_ and _gid_ can be given which
+set the ownership of directories and symbolic links.  When the
+filesystem is in catatonic mode, any process with a matching UID can
+create directories or symlinks in the root directory, but not in other
+directories.
+
+Catatonic mode can only be left via the
+**AUTOFS_DEV_IOCTL_OPENMOUNT_CMD** ioctl on the `/dev/autofs`.
+
+autofs, name spaces, and shared mounts
+--------------------------------------
+
+With bind mounts and name spaces it is possible for an autofs
+filesystem to appear at multiple places in one or more filesystem
+name spaces.  For this to work sensibly, the autofs filesystem should
+always be mounted "shared". e.g.
+
+> `mount --make-shared /autofs/mount/point`
+
+The automount daemon is only able to mange a single mount location for
+an autofs filesystem and if mounts on that are not 'shared', other
+locations will not behave as expected.  In particular access to those
+other locations will likely result in the `ELOOP` error
+
+> Too many levels of symbolic links
index b4498218c4744213bbe57609c7532fa4bd64bd54..5a615c14f75da79133db306179ccdd355bb0b4c4 100644 (file)
@@ -70,6 +70,38 @@ DMA addresses types dma_addr_t:
        For printing a dma_addr_t type which can vary based on build options,
        regardless of the width of the CPU data path. Passed by reference.
 
+Raw buffer as an escaped string:
+
+       %*pE[achnops]
+
+       For printing raw buffer as an escaped string. For the following buffer
+
+               1b 62 20 5c 43 07 22 90 0d 5d
+
+       few examples show how the conversion would be done (the result string
+       without surrounding quotes):
+
+               %*pE            "\eb \C\a"\220\r]"
+               %*pEhp          "\x1bb \C\x07"\x90\x0d]"
+               %*pEa           "\e\142\040\\\103\a\042\220\r\135"
+
+       The conversion rules are applied according to an optional combination
+       of flags (see string_escape_mem() kernel documentation for the
+       details):
+               a - ESCAPE_ANY
+               c - ESCAPE_SPECIAL
+               h - ESCAPE_HEX
+               n - ESCAPE_NULL
+               o - ESCAPE_OCTAL
+               p - ESCAPE_NP
+               s - ESCAPE_SPACE
+       By default ESCAPE_ANY_NP is used.
+
+       ESCAPE_ANY_NP is the sane choice for many cases, in particularly for
+       printing SSIDs.
+
+       If field width is omitted the 1 byte only will be escaped.
+
 Raw buffer as a hex string:
        %*ph    00 01 02  ...  3f
        %*phC   00:01:02: ... :3f
index f79eb96663790f1c116f6a44d706af048bdedc88..57baff5bdb806b3b725bdc7859c385fbdc1cac54 100644 (file)
@@ -190,6 +190,8 @@ core_pattern is used to specify a core dumpfile pattern name.
        %%      output one '%'
        %p      pid
        %P      global pid (init PID namespace)
+       %i      tid
+       %I      global tid (init PID namespace)
        %u      uid
        %g      gid
        %d      dump mode, matches PR_SET_DUMPABLE and
index f413abff3807d72a7a1b1f574169936245038872..c52367997fb5bcca51b1483667918bff36383017 100644 (file)
@@ -1338,8 +1338,7 @@ ARM/SAMSUNG MOBILE MACHINE SUPPORT
 M:     Kyungmin Park <kyungmin.park@samsung.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
-F:     arch/arm/mach-s5pv210/mach-aquila.c
-F:     arch/arm/mach-s5pv210/mach-goni.c
+F:     arch/arm/mach-s5pv210/
 
 ARM/SAMSUNG S5P SERIES 2D GRAPHICS ACCELERATION (G2D) SUPPORT
 M:     Kyungmin Park <kyungmin.park@samsung.com>
@@ -1550,6 +1549,7 @@ T:        git git://git.xilinx.com/linux-xlnx.git
 S:     Supported
 F:     arch/arm/mach-zynq/
 F:     drivers/cpuidle/cpuidle-zynq.c
+F:     drivers/block/xsysace.c
 N:     zynq
 N:     xilinx
 F:     drivers/clocksource/cadence_ttc_timer.c
@@ -1738,6 +1738,12 @@ M:       Nicolas Ferre <nicolas.ferre@atmel.com>
 S:     Supported
 F:     drivers/net/ethernet/cadence/
 
+ATMEL NAND DRIVER
+M:     Josh Wu <josh.wu@atmel.com>
+L:     linux-mtd@lists.infradead.org
+S:     Supported
+F:     drivers/mtd/nand/atmel_nand*
+
 ATMEL SPI DRIVER
 M:     Nicolas Ferre <nicolas.ferre@atmel.com>
 S:     Supported
@@ -3048,7 +3054,7 @@ M:        Sumit Semwal <sumit.semwal@linaro.org>
 S:     Maintained
 L:     linux-media@vger.kernel.org
 L:     dri-devel@lists.freedesktop.org
-L:     linaro-mm-sig@lists.linaro.org
+L:     linaro-mm-sig@lists.linaro.org (moderated for non-subscribers)
 F:     drivers/dma-buf/
 F:     include/linux/dma-buf*
 F:     include/linux/reservation.h
@@ -4297,9 +4303,8 @@ S:        Maintained
 F:     drivers/media/dvb-frontends/hd29l2*
 
 HEWLETT-PACKARD SMART2 RAID DRIVER
-M:     Chirag Kantharia <chirag.kantharia@hp.com>
 L:     iss_storagedev@hp.com
-S:     Maintained
+S:     Orphan
 F:     Documentation/blockdev/cpqarray.txt
 F:     drivers/block/cpqarray.*
 
@@ -5300,6 +5305,13 @@ F:       include/linux/lockd/
 F:     include/linux/sunrpc/
 F:     include/uapi/linux/sunrpc/
 
+KERNEL SELFTEST FRAMEWORK
+M:     Shuah Khan <shuahkh@osg.samsung.com>
+L:     linux-api@vger.kernel.org
+T:     git git://git.kernel.org/pub/scm/shuah/linux-kselftest
+S:     Maintained
+F:     tools/testing/selftests
+
 KERNEL VIRTUAL MACHINE (KVM)
 M:     Gleb Natapov <gleb@kernel.org>
 M:     Paolo Bonzini <pbonzini@redhat.com>
@@ -5746,11 +5758,8 @@ T:       git git://github.com/linux-test-project/ltp.git
 S:     Maintained
 
 M32R ARCHITECTURE
-M:     Hirokazu Takata <takata@linux-m32r.org>
-L:     linux-m32r@ml.linux-m32r.org (moderated for non-subscribers)
-L:     linux-m32r-ja@ml.linux-m32r.org (in Japanese)
 W:     http://www.linux-m32r.org/
-S:     Maintained
+S:     Orphan
 F:     arch/m32r/
 
 M68K ARCHITECTURE
@@ -7974,7 +7983,6 @@ S:        Supported
 F:     drivers/mfd/sec*.c
 F:     drivers/regulator/s2m*.c
 F:     drivers/regulator/s5m*.c
-F:     drivers/rtc/rtc-sec.c
 F:     include/linux/mfd/samsung/
 
 SAMSUNG S5P/EXYNOS4 SOC SERIES CAMERA SUBSYSTEM DRIVERS
@@ -10315,10 +10323,6 @@ M:     John Linn <John.Linn@xilinx.com>
 S:     Maintained
 F:     drivers/net/ethernet/xilinx/xilinx_axienet*
 
-XILINX SYSTEMACE DRIVER
-S:     Orphan
-F:     drivers/block/xsysace.c
-
 XILINX UARTLITE SERIAL DRIVER
 M:     Peter Korsgaard <jacmet@sunsite.dk>
 L:     linux-serial@vger.kernel.org
index 1d52de6370d58a65022b0bc59bf2f07516066308..429a6c6cfcf95156df66fe8082a6e0a2ac2d8a73 100644 (file)
                };
 
                rtc: rtc@10070000 {
-                       compatible = "samsung,s3c6410-rtc";
+                       compatible = "samsung,exynos3250-rtc";
                        reg = <0x10070000 0x100>;
                        interrupts = <0 73 0>, <0 74 0>;
                        status = "disabled";
index 9f6ec167902a6bc1c2db823d257e006550a3c3b0..ad777b353bd5234797d93031ab6815747b65e363 100644 (file)
@@ -416,17 +416,17 @@ static struct pxafb_mach_info *lpd270_lcd_to_use;
 
 static int __init lpd270_set_lcd(char *str)
 {
-       if (!strnicmp(str, "lq057q3dc02", 11)) {
+       if (!strncasecmp(str, "lq057q3dc02", 11)) {
                lpd270_lcd_to_use = &sharp_lq057q3dc02;
-       } else if (!strnicmp(str, "lq121s1dg31", 11)) {
+       } else if (!strncasecmp(str, "lq121s1dg31", 11)) {
                lpd270_lcd_to_use = &sharp_lq121s1dg31;
-       } else if (!strnicmp(str, "lq036q1da01", 11)) {
+       } else if (!strncasecmp(str, "lq036q1da01", 11)) {
                lpd270_lcd_to_use = &sharp_lq036q1da01;
-       } else if (!strnicmp(str, "lq64d343", 8)) {
+       } else if (!strncasecmp(str, "lq64d343", 8)) {
                lpd270_lcd_to_use = &sharp_lq64d343;
-       } else if (!strnicmp(str, "lq10d368", 8)) {
+       } else if (!strncasecmp(str, "lq10d368", 8)) {
                lpd270_lcd_to_use = &sharp_lq10d368;
-       } else if (!strnicmp(str, "lq035q7db02-20", 14)) {
+       } else if (!strncasecmp(str, "lq035q7db02-20", 14)) {
                lpd270_lcd_to_use = &sharp_lq035q7db02_20;
        } else {
                printk(KERN_INFO "lpd270: unknown lcd panel [%s]\n", str);
index 6aea124f574db5a19d6dac8ec3aafff8d4df7246..2fb9b3ab57b9d624883fb5dd8d53944b12bb1556 100644 (file)
@@ -6,8 +6,6 @@
 #include <linux/spinlock.h>
 #include <asm/uaccess.h>
 
-extern const struct exception_table_entry __attribute__((aligned(8))) __start___ex_table[];
-extern const struct exception_table_entry __attribute__((aligned(8))) __stop___ex_table[];
 extern const void __memset_end, __memset_user_error_lr, __memset_user_error_handler;
 extern const void __memcpy_end, __memcpy_user_error_lr, __memcpy_user_error_handler;
 extern spinlock_t modlist_lock;
index 1a873b36a4a1cd75f94bb196f1a7997d9ef621f3..2ab2003698ef6acd2fa7e5ffd5cabb31be3317b4 100644 (file)
@@ -10,7 +10,7 @@
 #include <linux/uaccess.h>
 #include <asm-generic/sections.h>
 
-extern char __per_cpu_start[], __per_cpu_end[], __phys_per_cpu_start[];
+extern char __phys_per_cpu_start[];
 #ifdef CONFIG_SMP
 extern char __cpu0_per_cpu[];
 #endif
index 700f958652f8ac1edc9e642b44f6cb61452c48cb..3eff36f719fb62dbb78ef64f37421b73a90c95ac 100644 (file)
@@ -964,6 +964,7 @@ static void vgetcpu_set_mode(void)
                vgetcpu_mode = VGETCPU_LSL;
 }
 
+#ifdef CONFIG_IA32_EMULATION
 /* May not be __init: called during resume */
 static void syscall32_cpu_init(void)
 {
@@ -975,7 +976,8 @@ static void syscall32_cpu_init(void)
 
        wrmsrl(MSR_CSTAR, ia32_cstar_target);
 }
-#endif
+#endif         /* CONFIG_IA32_EMULATION */
+#endif         /* CONFIG_X86_64 */
 
 #ifdef CONFIG_X86_32
 void enable_sep_cpu(void)
index a618fcd2c07d3d54062a8558a7f9941b16859203..f5ab56d1428718f6327c91012d5373cc200438a2 100644 (file)
@@ -237,7 +237,7 @@ static void fill_up_crash_elf_data(struct crash_elf_data *ced,
        ced->max_nr_ranges++;
 
        /* If crashk_low_res is not 0, another range split possible */
-       if (crashk_low_res.end != 0)
+       if (crashk_low_res.end)
                ced->max_nr_ranges++;
 }
 
@@ -335,9 +335,11 @@ static int elf_header_exclude_ranges(struct crash_elf_data *ced,
        if (ret)
                return ret;
 
-       ret = exclude_mem_range(cmem, crashk_low_res.start, crashk_low_res.end);
-       if (ret)
-               return ret;
+       if (crashk_low_res.end) {
+               ret = exclude_mem_range(cmem, crashk_low_res.start, crashk_low_res.end);
+               if (ret)
+                       return ret;
+       }
 
        /* Exclude GART region */
        if (ced->gart_end) {
index 9642b9b33655a739880fd5105473c81ff1696c9e..ca05f86481aace3a37cd6bf3fbe0e7d7ce3bb33a 100644 (file)
@@ -26,6 +26,7 @@
 #include <asm/setup.h>
 #include <asm/crash.h>
 #include <asm/efi.h>
+#include <asm/kexec-bzimage64.h>
 
 #define MAX_ELFCOREHDR_STR_LEN 30      /* elfcorehdr=0x<64bit-value> */
 
@@ -267,7 +268,7 @@ setup_boot_parameters(struct kimage *image, struct boot_params *params,
        return ret;
 }
 
-int bzImage64_probe(const char *buf, unsigned long len)
+static int bzImage64_probe(const char *buf, unsigned long len)
 {
        int ret = -ENOEXEC;
        struct setup_header *header;
@@ -325,10 +326,10 @@ int bzImage64_probe(const char *buf, unsigned long len)
        return ret;
 }
 
-void *bzImage64_load(struct kimage *image, char *kernel,
-                    unsigned long kernel_len, char *initrd,
-                    unsigned long initrd_len, char *cmdline,
-                    unsigned long cmdline_len)
+static void *bzImage64_load(struct kimage *image, char *kernel,
+                           unsigned long kernel_len, char *initrd,
+                           unsigned long initrd_len, char *cmdline,
+                           unsigned long cmdline_len)
 {
 
        struct setup_header *header;
@@ -514,7 +515,7 @@ out_free_params:
 }
 
 /* This cleanup function is called after various segments have been loaded */
-int bzImage64_cleanup(void *loader_data)
+static int bzImage64_cleanup(void *loader_data)
 {
        struct bzimage64_data *ldata = loader_data;
 
@@ -528,7 +529,7 @@ int bzImage64_cleanup(void *loader_data)
 }
 
 #ifdef CONFIG_KEXEC_BZIMAGE_VERIFY_SIG
-int bzImage64_verify_sig(const char *kernel, unsigned long kernel_len)
+static int bzImage64_verify_sig(const char *kernel, unsigned long kernel_len)
 {
        bool trusted;
        int ret;
index 3dd8e2c4d74a9ed4a124baf36a83de78be1be02d..95c3cb16af3e59e74d8a890bc59c2e35cb0fc014 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/slab.h>
 #include <linux/kprobes.h>
 #include <linux/debugfs.h>
+#include <linux/nmi.h>
 #include <asm/timer.h>
 #include <asm/cpu.h>
 #include <asm/traps.h>
@@ -499,6 +500,13 @@ void __init kvm_guest_init(void)
 #else
        kvm_guest_cpu_init();
 #endif
+
+       /*
+        * Hard lockup detection is enabled by default. Disable it, as guests
+        * can get false positives too easily, for example if the host is
+        * overcommitted.
+        */
+       watchdog_enable_hardlockup_detector(false);
 }
 
 static noinline uint32_t __kvm_cpuid_base(void)
index baff1da354e0ecfaf371b4e9f30ac6533d657a28..af78e50ca6cee7e4b7293075171986ab6f7166d5 100644 (file)
@@ -86,6 +86,7 @@ static void __iomem *__ioremap_caller(resource_size_t phys_addr,
        pgprot_t prot;
        int retval;
        void __iomem *ret_addr;
+       int ram_region;
 
        /* Don't allow wraparound or zero size */
        last_addr = phys_addr + size - 1;
@@ -108,12 +109,23 @@ static void __iomem *__ioremap_caller(resource_size_t phys_addr,
        /*
         * Don't allow anybody to remap normal RAM that we're using..
         */
-       pfn      = phys_addr >> PAGE_SHIFT;
-       last_pfn = last_addr >> PAGE_SHIFT;
-       if (walk_system_ram_range(pfn, last_pfn - pfn + 1, NULL,
-                                 __ioremap_check_ram) == 1)
+       /* First check if whole region can be identified as RAM or not */
+       ram_region = region_is_ram(phys_addr, size);
+       if (ram_region > 0) {
+               WARN_ONCE(1, "ioremap on RAM at 0x%lx - 0x%lx\n",
+                               (unsigned long int)phys_addr,
+                               (unsigned long int)last_addr);
                return NULL;
+       }
 
+       /* If could not be identified(-1), check page by page */
+       if (ram_region < 0) {
+               pfn      = phys_addr >> PAGE_SHIFT;
+               last_pfn = last_addr >> PAGE_SHIFT;
+               if (walk_system_ram_range(pfn, last_pfn - pfn + 1, NULL,
+                                         __ioremap_check_ram) == 1)
+                       return NULL;
+       }
        /*
         * Mappings have to be page-aligned
         */
index d221374d5ce82fa769dc31d864a4b72145ae8b42..1a883705a12a8a12410914be93b2ee65807cc423 100644 (file)
@@ -463,6 +463,42 @@ static bool __init numa_meminfo_cover_memory(const struct numa_meminfo *mi)
        return true;
 }
 
+static void __init numa_clear_kernel_node_hotplug(void)
+{
+       int i, nid;
+       nodemask_t numa_kernel_nodes = NODE_MASK_NONE;
+       unsigned long start, end;
+       struct memblock_region *r;
+
+       /*
+        * At this time, all memory regions reserved by memblock are
+        * used by the kernel. Set the nid in memblock.reserved will
+        * mark out all the nodes the kernel resides in.
+        */
+       for (i = 0; i < numa_meminfo.nr_blks; i++) {
+               struct numa_memblk *mb = &numa_meminfo.blk[i];
+
+               memblock_set_node(mb->start, mb->end - mb->start,
+                                 &memblock.reserved, mb->nid);
+       }
+
+       /* Mark all kernel nodes. */
+       for_each_memblock(reserved, r)
+               node_set(r->nid, numa_kernel_nodes);
+
+       /* Clear MEMBLOCK_HOTPLUG flag for memory in kernel nodes. */
+       for (i = 0; i < numa_meminfo.nr_blks; i++) {
+               nid = numa_meminfo.blk[i].nid;
+               if (!node_isset(nid, numa_kernel_nodes))
+                       continue;
+
+               start = numa_meminfo.blk[i].start;
+               end = numa_meminfo.blk[i].end;
+
+               memblock_clear_hotplug(start, end - start);
+       }
+}
+
 static int __init numa_register_memblks(struct numa_meminfo *mi)
 {
        unsigned long uninitialized_var(pfn_align);
@@ -480,6 +516,15 @@ static int __init numa_register_memblks(struct numa_meminfo *mi)
                                  &memblock.memory, mb->nid);
        }
 
+       /*
+        * At very early time, the kernel have to use some memory such as
+        * loading the kernel image. We cannot prevent this anyway. So any
+        * node the kernel resides in should be un-hotpluggable.
+        *
+        * And when we come here, alloc node data won't fail.
+        */
+       numa_clear_kernel_node_hotplug();
+
        /*
         * If sections array is gonna be used for pfn -> nid mapping, check
         * whether its granularity is fine enough.
@@ -548,41 +593,6 @@ static void __init numa_init_array(void)
        }
 }
 
-static void __init numa_clear_kernel_node_hotplug(void)
-{
-       int i, nid;
-       nodemask_t numa_kernel_nodes = NODE_MASK_NONE;
-       unsigned long start, end;
-       struct memblock_region *r;
-
-       /*
-        * At this time, all memory regions reserved by memblock are
-        * used by the kernel. Set the nid in memblock.reserved will
-        * mark out all the nodes the kernel resides in.
-        */
-       for (i = 0; i < numa_meminfo.nr_blks; i++) {
-               struct numa_memblk *mb = &numa_meminfo.blk[i];
-               memblock_set_node(mb->start, mb->end - mb->start,
-                                 &memblock.reserved, mb->nid);
-       }
-
-       /* Mark all kernel nodes. */
-       for_each_memblock(reserved, r)
-               node_set(r->nid, numa_kernel_nodes);
-
-       /* Clear MEMBLOCK_HOTPLUG flag for memory in kernel nodes. */
-       for (i = 0; i < numa_meminfo.nr_blks; i++) {
-               nid = numa_meminfo.blk[i].nid;
-               if (!node_isset(nid, numa_kernel_nodes))
-                       continue;
-
-               start = numa_meminfo.blk[i].start;
-               end = numa_meminfo.blk[i].end;
-
-               memblock_clear_hotplug(start, end - start);
-       }
-}
-
 static int __init numa_init(int (*init_func)(void))
 {
        int i;
@@ -637,15 +647,6 @@ static int __init numa_init(int (*init_func)(void))
        }
        numa_init_array();
 
-       /*
-        * At very early time, the kernel have to use some memory such as
-        * loading the kernel image. We cannot prevent this anyway. So any
-        * node the kernel resides in should be un-hotpluggable.
-        *
-        * And when we come here, numa_init() won't fail.
-        */
-       numa_clear_kernel_node_hotplug();
-
        return 0;
 }
 
index 899dd24542568de85e815e4b9f206d66286bca8c..f52e033557c9e0b54c41248101e0d7d7ed7cb76f 100644 (file)
@@ -18,8 +18,9 @@ $(obj)/purgatory.ro: $(PURGATORY_OBJS) FORCE
 
 targets += kexec-purgatory.c
 
+CMD_BIN2C = $(objtree)/scripts/basic/bin2c
 quiet_cmd_bin2c = BIN2C   $@
-      cmd_bin2c = cat $(obj)/purgatory.ro | $(objtree)/scripts/basic/bin2c kexec_purgatory > $(obj)/kexec-purgatory.c
+      cmd_bin2c = $(CMD_BIN2C) kexec_purgatory < $< > $@
 
 $(obj)/kexec-purgatory.c: $(obj)/purgatory.ro FORCE
        $(call if_changed,bin2c)
index 7d6e84a51424b269d6bfffa401f6788ac44997ed..55b83983a9c00c8b5984c887a0435ffb6e03fe1d 100644 (file)
@@ -14,11 +14,14 @@ struct dma_coherent_mem {
        int             size;
        int             flags;
        unsigned long   *bitmap;
+       spinlock_t      spinlock;
 };
 
-int dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr,
-                               dma_addr_t device_addr, size_t size, int flags)
+static int dma_init_coherent_memory(phys_addr_t phys_addr, dma_addr_t device_addr,
+                            size_t size, int flags,
+                            struct dma_coherent_mem **mem)
 {
+       struct dma_coherent_mem *dma_mem = NULL;
        void __iomem *mem_base = NULL;
        int pages = size >> PAGE_SHIFT;
        int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
@@ -27,40 +30,77 @@ int dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr,
                goto out;
        if (!size)
                goto out;
-       if (dev->dma_mem)
-               goto out;
-
-       /* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */
 
        mem_base = ioremap(phys_addr, size);
        if (!mem_base)
                goto out;
 
-       dev->dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
-       if (!dev->dma_mem)
+       dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
+       if (!dma_mem)
                goto out;
-       dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
-       if (!dev->dma_mem->bitmap)
-               goto free1_out;
+       dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
+       if (!dma_mem->bitmap)
+               goto out;
+
+       dma_mem->virt_base = mem_base;
+       dma_mem->device_base = device_addr;
+       dma_mem->pfn_base = PFN_DOWN(phys_addr);
+       dma_mem->size = pages;
+       dma_mem->flags = flags;
+       spin_lock_init(&dma_mem->spinlock);
 
-       dev->dma_mem->virt_base = mem_base;
-       dev->dma_mem->device_base = device_addr;
-       dev->dma_mem->pfn_base = PFN_DOWN(phys_addr);
-       dev->dma_mem->size = pages;
-       dev->dma_mem->flags = flags;
+       *mem = dma_mem;
 
        if (flags & DMA_MEMORY_MAP)
                return DMA_MEMORY_MAP;
 
        return DMA_MEMORY_IO;
 
- free1_out:
-       kfree(dev->dma_mem);
- out:
+out:
+       kfree(dma_mem);
        if (mem_base)
                iounmap(mem_base);
        return 0;
 }
+
+static void dma_release_coherent_memory(struct dma_coherent_mem *mem)
+{
+       if (!mem)
+               return;
+       iounmap(mem->virt_base);
+       kfree(mem->bitmap);
+       kfree(mem);
+}
+
+static int dma_assign_coherent_memory(struct device *dev,
+                                     struct dma_coherent_mem *mem)
+{
+       if (dev->dma_mem)
+               return -EBUSY;
+
+       dev->dma_mem = mem;
+       /* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */
+
+       return 0;
+}
+
+int dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr,
+                               dma_addr_t device_addr, size_t size, int flags)
+{
+       struct dma_coherent_mem *mem;
+       int ret;
+
+       ret = dma_init_coherent_memory(phys_addr, device_addr, size, flags,
+                                      &mem);
+       if (ret == 0)
+               return 0;
+
+       if (dma_assign_coherent_memory(dev, mem) == 0)
+               return ret;
+
+       dma_release_coherent_memory(mem);
+       return 0;
+}
 EXPORT_SYMBOL(dma_declare_coherent_memory);
 
 void dma_release_declared_memory(struct device *dev)
@@ -69,10 +109,8 @@ void dma_release_declared_memory(struct device *dev)
 
        if (!mem)
                return;
+       dma_release_coherent_memory(mem);
        dev->dma_mem = NULL;
-       iounmap(mem->virt_base);
-       kfree(mem->bitmap);
-       kfree(mem);
 }
 EXPORT_SYMBOL(dma_release_declared_memory);
 
@@ -80,6 +118,7 @@ void *dma_mark_declared_memory_occupied(struct device *dev,
                                        dma_addr_t device_addr, size_t size)
 {
        struct dma_coherent_mem *mem = dev->dma_mem;
+       unsigned long flags;
        int pos, err;
 
        size += device_addr & ~PAGE_MASK;
@@ -87,8 +126,11 @@ void *dma_mark_declared_memory_occupied(struct device *dev,
        if (!mem)
                return ERR_PTR(-EINVAL);
 
+       spin_lock_irqsave(&mem->spinlock, flags);
        pos = (device_addr - mem->device_base) >> PAGE_SHIFT;
        err = bitmap_allocate_region(mem->bitmap, pos, get_order(size));
+       spin_unlock_irqrestore(&mem->spinlock, flags);
+
        if (err != 0)
                return ERR_PTR(err);
        return mem->virt_base + (pos << PAGE_SHIFT);
@@ -115,6 +157,7 @@ int dma_alloc_from_coherent(struct device *dev, ssize_t size,
 {
        struct dma_coherent_mem *mem;
        int order = get_order(size);
+       unsigned long flags;
        int pageno;
 
        if (!dev)
@@ -124,6 +167,7 @@ int dma_alloc_from_coherent(struct device *dev, ssize_t size,
                return 0;
 
        *ret = NULL;
+       spin_lock_irqsave(&mem->spinlock, flags);
 
        if (unlikely(size > (mem->size << PAGE_SHIFT)))
                goto err;
@@ -138,10 +182,12 @@ int dma_alloc_from_coherent(struct device *dev, ssize_t size,
        *dma_handle = mem->device_base + (pageno << PAGE_SHIFT);
        *ret = mem->virt_base + (pageno << PAGE_SHIFT);
        memset(*ret, 0, size);
+       spin_unlock_irqrestore(&mem->spinlock, flags);
 
        return 1;
 
 err:
+       spin_unlock_irqrestore(&mem->spinlock, flags);
        /*
         * In the case where the allocation can not be satisfied from the
         * per-device area, try to fall back to generic memory if the
@@ -171,8 +217,11 @@ int dma_release_from_coherent(struct device *dev, int order, void *vaddr)
        if (mem && vaddr >= mem->virt_base && vaddr <
                   (mem->virt_base + (mem->size << PAGE_SHIFT))) {
                int page = (vaddr - mem->virt_base) >> PAGE_SHIFT;
+               unsigned long flags;
 
+               spin_lock_irqsave(&mem->spinlock, flags);
                bitmap_release_region(mem->bitmap, page, order);
+               spin_unlock_irqrestore(&mem->spinlock, flags);
                return 1;
        }
        return 0;
@@ -218,3 +267,61 @@ int dma_mmap_from_coherent(struct device *dev, struct vm_area_struct *vma,
        return 0;
 }
 EXPORT_SYMBOL(dma_mmap_from_coherent);
+
+/*
+ * Support for reserved memory regions defined in device tree
+ */
+#ifdef CONFIG_OF_RESERVED_MEM
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/of_reserved_mem.h>
+
+static int rmem_dma_device_init(struct reserved_mem *rmem, struct device *dev)
+{
+       struct dma_coherent_mem *mem = rmem->priv;
+
+       if (!mem &&
+           dma_init_coherent_memory(rmem->base, rmem->base, rmem->size,
+                                    DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE,
+                                    &mem) != DMA_MEMORY_MAP) {
+               pr_err("Reserved memory: failed to init DMA memory pool at %pa, size %ld MiB\n",
+                       &rmem->base, (unsigned long)rmem->size / SZ_1M);
+               return -ENODEV;
+       }
+       rmem->priv = mem;
+       dma_assign_coherent_memory(dev, mem);
+       return 0;
+}
+
+static void rmem_dma_device_release(struct reserved_mem *rmem,
+                                   struct device *dev)
+{
+       dev->dma_mem = NULL;
+}
+
+static const struct reserved_mem_ops rmem_dma_ops = {
+       .device_init    = rmem_dma_device_init,
+       .device_release = rmem_dma_device_release,
+};
+
+static int __init rmem_dma_setup(struct reserved_mem *rmem)
+{
+       unsigned long node = rmem->fdt_node;
+
+       if (of_get_flat_dt_prop(node, "reusable", NULL))
+               return -EINVAL;
+
+#ifdef CONFIG_ARM
+       if (!of_get_flat_dt_prop(node, "no-map", NULL)) {
+               pr_err("Reserved memory: regions without no-map are not yet supported\n");
+               return -EINVAL;
+       }
+#endif
+
+       rmem->ops = &rmem_dma_ops;
+       pr_info("Reserved memory: created DMA memory pool at %pa, size %ld MiB\n",
+               &rmem->base, (unsigned long)rmem->size / SZ_1M);
+       return 0;
+}
+RESERVEDMEM_OF_DECLARE(dma, "shared-dma-pool", rmem_dma_setup);
+#endif
index 6606abdf880c816ce407c486fbabcc27d602cef9..473ff48924015f07daee1c81ebe3d6436727493e 100644 (file)
@@ -211,3 +211,69 @@ bool dma_release_from_contiguous(struct device *dev, struct page *pages,
 {
        return cma_release(dev_get_cma_area(dev), pages, count);
 }
+
+/*
+ * Support for reserved memory regions defined in device tree
+ */
+#ifdef CONFIG_OF_RESERVED_MEM
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/of_reserved_mem.h>
+
+#undef pr_fmt
+#define pr_fmt(fmt) fmt
+
+static void rmem_cma_device_init(struct reserved_mem *rmem, struct device *dev)
+{
+       dev_set_cma_area(dev, rmem->priv);
+}
+
+static void rmem_cma_device_release(struct reserved_mem *rmem,
+                                   struct device *dev)
+{
+       dev_set_cma_area(dev, NULL);
+}
+
+static const struct reserved_mem_ops rmem_cma_ops = {
+       .device_init    = rmem_cma_device_init,
+       .device_release = rmem_cma_device_release,
+};
+
+static int __init rmem_cma_setup(struct reserved_mem *rmem)
+{
+       phys_addr_t align = PAGE_SIZE << max(MAX_ORDER - 1, pageblock_order);
+       phys_addr_t mask = align - 1;
+       unsigned long node = rmem->fdt_node;
+       struct cma *cma;
+       int err;
+
+       if (!of_get_flat_dt_prop(node, "reusable", NULL) ||
+           of_get_flat_dt_prop(node, "no-map", NULL))
+               return -EINVAL;
+
+       if ((rmem->base & mask) || (rmem->size & mask)) {
+               pr_err("Reserved memory: incorrect alignment of CMA region\n");
+               return -EINVAL;
+       }
+
+       err = cma_init_reserved_mem(rmem->base, rmem->size, 0, &cma);
+       if (err) {
+               pr_err("Reserved memory: unable to setup CMA region\n");
+               return err;
+       }
+       /* Architecture specific contiguous memory fixup. */
+       dma_contiguous_early_fixup(rmem->base, rmem->size);
+
+       if (of_get_flat_dt_prop(node, "linux,cma-default", NULL))
+               dma_contiguous_set_default(cma);
+
+       rmem->ops = &rmem_cma_ops;
+       rmem->priv = cma;
+
+       pr_info("Reserved memory: created CMA memory pool at %pa, size %ld MiB\n",
+               &rmem->base, (unsigned long)rmem->size / SZ_1M);
+
+       return 0;
+}
+RESERVEDMEM_OF_DECLARE(cma, "shared-dma-pool", rmem_cma_setup);
+#endif
index cfd3af7b2cbd16cec12c23cf0767cc787c66a812..84e0590e31dc754fd1562d8bd99d2c3273090f3f 100644 (file)
@@ -38,6 +38,15 @@ config COMMON_CLK_MAX77686
        ---help---
          This driver supports Maxim 77686 crystal oscillator clock. 
 
+config COMMON_CLK_RK808
+       tristate "Clock driver for RK808"
+       depends on MFD_RK808
+       ---help---
+         This driver supports RK808 crystal oscillator clock. These
+         multi-function devices have two fixed-rate oscillators,
+         clocked at 32KHz each. Clkout1 is always on, Clkout2 can off
+         by control register.
+
 config COMMON_CLK_SI5351
        tristate "Clock driver for SiLabs 5351A/B/C"
        depends on I2C
index f537a0b1f798159824aa1d90ffd4378d1bff908d..99f53d5f876618be908525c3cbc4b9c3803119a2 100644 (file)
@@ -28,6 +28,7 @@ obj-$(CONFIG_ARCH_NOMADIK)            += clk-nomadik.o
 obj-$(CONFIG_ARCH_NSPIRE)              += clk-nspire.o
 obj-$(CONFIG_COMMON_CLK_PALMAS)                += clk-palmas.o
 obj-$(CONFIG_CLK_PPC_CORENET)          += clk-ppc-corenet.o
+obj-$(CONFIG_COMMON_CLK_RK808)         += clk-rk808.o
 obj-$(CONFIG_COMMON_CLK_S2MPS11)       += clk-s2mps11.o
 obj-$(CONFIG_COMMON_CLK_SI5351)                += clk-si5351.o
 obj-$(CONFIG_COMMON_CLK_SI570)         += clk-si570.o
diff --git a/drivers/clk/clk-rk808.c b/drivers/clk/clk-rk808.c
new file mode 100644 (file)
index 0000000..83902b9
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * Clkout driver for Rockchip RK808
+ *
+ * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
+ *
+ * Author:Chris Zhong <zyw@rock-chips.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/rk808.h>
+#include <linux/i2c.h>
+
+#define RK808_NR_OUTPUT 2
+
+struct rk808_clkout {
+       struct rk808 *rk808;
+       struct clk_onecell_data clk_data;
+       struct clk_hw           clkout1_hw;
+       struct clk_hw           clkout2_hw;
+};
+
+static unsigned long rk808_clkout_recalc_rate(struct clk_hw *hw,
+                                             unsigned long parent_rate)
+{
+       return 32768;
+}
+
+static int rk808_clkout2_enable(struct clk_hw *hw, bool enable)
+{
+       struct rk808_clkout *rk808_clkout = container_of(hw,
+                                                        struct rk808_clkout,
+                                                        clkout2_hw);
+       struct rk808 *rk808 = rk808_clkout->rk808;
+
+       return regmap_update_bits(rk808->regmap, RK808_CLK32OUT_REG,
+                                 CLK32KOUT2_EN, enable ? CLK32KOUT2_EN : 0);
+}
+
+static int rk808_clkout2_prepare(struct clk_hw *hw)
+{
+       return rk808_clkout2_enable(hw, true);
+}
+
+static void rk808_clkout2_unprepare(struct clk_hw *hw)
+{
+       rk808_clkout2_enable(hw, false);
+}
+
+static int rk808_clkout2_is_prepared(struct clk_hw *hw)
+{
+       struct rk808_clkout *rk808_clkout = container_of(hw,
+                                                        struct rk808_clkout,
+                                                        clkout2_hw);
+       struct rk808 *rk808 = rk808_clkout->rk808;
+       uint32_t val;
+
+       int ret = regmap_read(rk808->regmap, RK808_CLK32OUT_REG, &val);
+
+       if (ret < 0)
+               return ret;
+
+       return (val & CLK32KOUT2_EN) ? 1 : 0;
+}
+
+static const struct clk_ops rk808_clkout1_ops = {
+       .recalc_rate = rk808_clkout_recalc_rate,
+};
+
+static const struct clk_ops rk808_clkout2_ops = {
+       .prepare = rk808_clkout2_prepare,
+       .unprepare = rk808_clkout2_unprepare,
+       .is_prepared = rk808_clkout2_is_prepared,
+       .recalc_rate = rk808_clkout_recalc_rate,
+};
+
+static int rk808_clkout_probe(struct platform_device *pdev)
+{
+       struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent);
+       struct i2c_client *client = rk808->i2c;
+       struct device_node *node = client->dev.of_node;
+       struct clk_init_data init = {};
+       struct clk **clk_table;
+       struct rk808_clkout *rk808_clkout;
+
+       rk808_clkout = devm_kzalloc(&client->dev,
+                                   sizeof(*rk808_clkout), GFP_KERNEL);
+       if (!rk808_clkout)
+               return -ENOMEM;
+
+       rk808_clkout->rk808 = rk808;
+
+       clk_table = devm_kcalloc(&client->dev, RK808_NR_OUTPUT,
+                                sizeof(struct clk *), GFP_KERNEL);
+       if (!clk_table)
+               return -ENOMEM;
+
+       init.flags = CLK_IS_ROOT;
+       init.parent_names = NULL;
+       init.num_parents = 0;
+       init.name = "rk808-clkout1";
+       init.ops = &rk808_clkout1_ops;
+       rk808_clkout->clkout1_hw.init = &init;
+
+       /* optional override of the clockname */
+       of_property_read_string_index(node, "clock-output-names",
+                                     0, &init.name);
+
+       clk_table[0] = devm_clk_register(&client->dev,
+                                        &rk808_clkout->clkout1_hw);
+       if (IS_ERR(clk_table[0]))
+               return PTR_ERR(clk_table[0]);
+
+       init.name = "rk808-clkout2";
+       init.ops = &rk808_clkout2_ops;
+       rk808_clkout->clkout2_hw.init = &init;
+
+       /* optional override of the clockname */
+       of_property_read_string_index(node, "clock-output-names",
+                                     1, &init.name);
+
+       clk_table[1] = devm_clk_register(&client->dev,
+                                        &rk808_clkout->clkout2_hw);
+       if (IS_ERR(clk_table[1]))
+               return PTR_ERR(clk_table[1]);
+
+       rk808_clkout->clk_data.clks = clk_table;
+       rk808_clkout->clk_data.clk_num = RK808_NR_OUTPUT;
+
+       return of_clk_add_provider(node, of_clk_src_onecell_get,
+                                  &rk808_clkout->clk_data);
+}
+
+static int rk808_clkout_remove(struct platform_device *pdev)
+{
+       struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent);
+       struct i2c_client *client = rk808->i2c;
+       struct device_node *node = client->dev.of_node;
+
+       of_clk_del_provider(node);
+
+       return 0;
+}
+
+static struct platform_driver rk808_clkout_driver = {
+       .probe = rk808_clkout_probe,
+       .remove = rk808_clkout_remove,
+       .driver         = {
+               .name   = "rk808-clkout",
+       },
+};
+
+module_platform_driver(rk808_clkout_driver);
+
+MODULE_DESCRIPTION("Clkout driver for the rk808 series PMICs");
+MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:rk808-clkout");
index d28a8c284da90d57092577f648964d7bdb5731d1..7206547c13ce0dc8dda59458658d843d64520327 100644 (file)
@@ -3574,7 +3574,7 @@ static int srpt_parse_i_port_id(u8 i_port_id[16], const char *name)
        int ret, rc;
 
        p = name;
-       if (strnicmp(p, "0x", 2) == 0)
+       if (strncasecmp(p, "0x", 2) == 0)
                p += 2;
        ret = -EINVAL;
        len = strlen(p);
index 8857d5b9be71dc03d4494562383fc76c779003ef..ee3434f1e949200ba9224669dd3a1c68045ad557 100644 (file)
@@ -812,7 +812,7 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client,
        /* if we find something consistent, stay with that assumption
         * at least M09 won't send 3 bytes here
         */
-       if (!(strnicmp(rdbuf + 1, "EP0", 3))) {
+       if (!(strncasecmp(rdbuf + 1, "EP0", 3))) {
                tsdata->version = M06;
 
                /* remove last '$' end marker */
index 31727bf285d0de164d00024a5c34fe539403c94d..e2a4f5f415b2be30d0b223d7fac1e423dec411cf 100644 (file)
@@ -188,6 +188,7 @@ static void r592_host_reset(struct r592_device *dev)
        r592_set_mode(dev, dev->parallel_mode);
 }
 
+#ifdef CONFIG_PM_SLEEP
 /* Disable all hardware interrupts */
 static void r592_clear_interrupts(struct r592_device *dev)
 {
@@ -195,6 +196,7 @@ static void r592_clear_interrupts(struct r592_device *dev)
        r592_clear_reg_mask(dev, R592_REG_MSC, IRQ_ALL_ACK_MASK);
        r592_clear_reg_mask(dev, R592_REG_MSC, IRQ_ALL_EN_MASK);
 }
+#endif
 
 /* Tests if there is an CRC error */
 static int r592_test_io_error(struct r592_device *dev)
index 24272e022bec926f729d6cf26fd5953e63316ad7..bca2630d006f4d088b4873e08a399983bc845615 100644 (file)
@@ -454,7 +454,7 @@ exit_done:
 
                                name = &p[str_table + name_id];
 
-                               if (strnicmp(aconf->action, name, strlen(name)) == 0) {
+                               if (strncasecmp(aconf->action, name, strlen(name)) == 0) {
                                        action_found = 1;
                                        current_proc =
                                                get_unaligned_be32(&p[action_table +
@@ -2176,7 +2176,7 @@ static int altera_get_note(u8 *p, s32 program_size,
                        key_ptr = &p[note_strings +
                                        get_unaligned_be32(
                                        &p[note_table + (8 * i)])];
-                       if ((strnicmp(key, key_ptr, strlen(key_ptr)) == 0) &&
+                       if ((strncasecmp(key, key_ptr, strlen(key_ptr)) == 0) &&
                                                (key != NULL)) {
                                status = 0;
 
index 8efd17c52f65c5307b6136f14fcd94e2def45b2b..dd84557cf957e37d5a07ebce0b985f5e27d0d3a8 100644 (file)
@@ -168,7 +168,6 @@ static int prism2_bss_list_proc_show(struct seq_file *m, void *v)
        local_info_t *local = m->private;
        struct list_head *ptr = v;
        struct hostap_bss_info *bss;
-       int i;
 
        if (ptr == &local->bss_list) {
                seq_printf(m, "#BSSID\tlast_update\tcount\tcapab_info\tSSID(txt)\t"
@@ -181,9 +180,7 @@ static int prism2_bss_list_proc_show(struct seq_file *m, void *v)
                   bss->bssid, bss->last_update,
                   bss->count, bss->capab_info);
 
-       for (i = 0; i < bss->ssid_len; i++)
-               seq_putc(m,bss->ssid[i] >= 32 && bss->ssid[i] < 127 ?
-                          bss->ssid[i] : '_');
+       seq_printf(m, "%*pE", (int)bss->ssid_len, bss->ssid);
 
        seq_putc(m, '\t');
        seq_printf(m, "%*phN", (int)bss->ssid_len, bss->ssid);
index c3d726f334e33c27c7a14f9a4266ba4f4a1aa783..6fabea0309dd9a208d82be0451e07d24af45ab16 100644 (file)
@@ -2005,7 +2005,6 @@ static void isr_indicate_associated(struct ipw2100_priv *priv, u32 status)
        u32 chan;
        char *txratename;
        u8 bssid[ETH_ALEN];
-       DECLARE_SSID_BUF(ssid);
 
        /*
         * TBD: BSSID is usually 00:00:00:00:00:00 here and not
@@ -2067,8 +2066,8 @@ static void isr_indicate_associated(struct ipw2100_priv *priv, u32 status)
                break;
        }
 
-       IPW_DEBUG_INFO("%s: Associated with '%s' at %s, channel %d (BSSID=%pM)\n",
-                      priv->net_dev->name, print_ssid(ssid, essid, essid_len),
+       IPW_DEBUG_INFO("%s: Associated with '%*pE' at %s, channel %d (BSSID=%pM)\n",
+                      priv->net_dev->name, essid_len, essid,
                       txratename, chan, bssid);
 
        /* now we copy read ssid into dev */
@@ -2095,9 +2094,8 @@ static int ipw2100_set_essid(struct ipw2100_priv *priv, char *essid,
                .host_command_length = ssid_len
        };
        int err;
-       DECLARE_SSID_BUF(ssid);
 
-       IPW_DEBUG_HC("SSID: '%s'\n", print_ssid(ssid, essid, ssid_len));
+       IPW_DEBUG_HC("SSID: '%*pE'\n", ssid_len, essid);
 
        if (ssid_len)
                memcpy(cmd.host_command_parameters, essid, ssid_len);
@@ -2138,11 +2136,8 @@ static int ipw2100_set_essid(struct ipw2100_priv *priv, char *essid,
 
 static void isr_indicate_association_lost(struct ipw2100_priv *priv, u32 status)
 {
-       DECLARE_SSID_BUF(ssid);
-
        IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | IPW_DL_ASSOC,
-                 "disassociated: '%s' %pM\n",
-                 print_ssid(ssid, priv->essid, priv->essid_len),
+                 "disassociated: '%*pE' %pM\n", priv->essid_len, priv->essid,
                  priv->bssid);
 
        priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING);
@@ -6975,7 +6970,6 @@ static int ipw2100_wx_set_essid(struct net_device *dev,
        char *essid = "";       /* ANY */
        int length = 0;
        int err = 0;
-       DECLARE_SSID_BUF(ssid);
 
        mutex_lock(&priv->action_mutex);
        if (!(priv->status & STATUS_INITIALIZED)) {
@@ -7005,8 +6999,7 @@ static int ipw2100_wx_set_essid(struct net_device *dev,
                goto done;
        }
 
-       IPW_DEBUG_WX("Setting ESSID: '%s' (%d)\n",
-                    print_ssid(ssid, essid, length), length);
+       IPW_DEBUG_WX("Setting ESSID: '%*pE' (%d)\n", length, essid, length);
 
        priv->essid_len = length;
        memcpy(priv->essid, essid, priv->essid_len);
@@ -7027,13 +7020,12 @@ static int ipw2100_wx_get_essid(struct net_device *dev,
         */
 
        struct ipw2100_priv *priv = libipw_priv(dev);
-       DECLARE_SSID_BUF(ssid);
 
        /* If we are associated, trying to associate, or have a statically
         * configured ESSID then return that; otherwise return ANY */
        if (priv->config & CFG_STATIC_ESSID || priv->status & STATUS_ASSOCIATED) {
-               IPW_DEBUG_WX("Getting essid: '%s'\n",
-                            print_ssid(ssid, priv->essid, priv->essid_len));
+               IPW_DEBUG_WX("Getting essid: '%*pE'\n",
+                            priv->essid_len, priv->essid);
                memcpy(extra, priv->essid, priv->essid_len);
                wrqu->essid.length = priv->essid_len;
                wrqu->essid.flags = 1;  /* active */
index f0c3c77a48d38eb7e2318280ab9492582091c39f..edc344334a7547006901de8e3b5dcd79db66c0a9 100644 (file)
@@ -4496,7 +4496,6 @@ static void handle_scan_event(struct ipw_priv *priv)
 static void ipw_rx_notification(struct ipw_priv *priv,
                                       struct ipw_rx_notification *notif)
 {
-       DECLARE_SSID_BUF(ssid);
        u16 size = le16_to_cpu(notif->size);
 
        IPW_DEBUG_NOTIF("type = %i (%d bytes)\n", notif->subtype, size);
@@ -4509,9 +4508,8 @@ static void ipw_rx_notification(struct ipw_priv *priv,
                        case CMAS_ASSOCIATED:{
                                        IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
                                                  IPW_DL_ASSOC,
-                                                 "associated: '%s' %pM\n",
-                                                 print_ssid(ssid, priv->essid,
-                                                            priv->essid_len),
+                                                 "associated: '%*pE' %pM\n",
+                                                 priv->essid_len, priv->essid,
                                                  priv->bssid);
 
                                        switch (priv->ieee->iw_mode) {
@@ -4585,14 +4583,9 @@ static void ipw_rx_notification(struct ipw_priv *priv,
                                                IPW_DEBUG(IPW_DL_NOTIF |
                                                          IPW_DL_STATE |
                                                          IPW_DL_ASSOC,
-                                                         "deauthenticated: '%s' "
-                                                         "%pM"
-                                                         ": (0x%04X) - %s\n",
-                                                         print_ssid(ssid,
-                                                                    priv->
-                                                                    essid,
-                                                                    priv->
-                                                                    essid_len),
+                                                         "deauthenticated: '%*pE' %pM: (0x%04X) - %s\n",
+                                                         priv->essid_len,
+                                                         priv->essid,
                                                          priv->bssid,
                                                          le16_to_cpu(auth->status),
                                                          ipw_get_status_code
@@ -4610,9 +4603,8 @@ static void ipw_rx_notification(struct ipw_priv *priv,
 
                                        IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
                                                  IPW_DL_ASSOC,
-                                                 "authenticated: '%s' %pM\n",
-                                                 print_ssid(ssid, priv->essid,
-                                                            priv->essid_len),
+                                                 "authenticated: '%*pE' %pM\n",
+                                                 priv->essid_len, priv->essid,
                                                  priv->bssid);
                                        break;
                                }
@@ -4638,9 +4630,8 @@ static void ipw_rx_notification(struct ipw_priv *priv,
 
                                        IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
                                                  IPW_DL_ASSOC,
-                                                 "disassociated: '%s' %pM\n",
-                                                 print_ssid(ssid, priv->essid,
-                                                            priv->essid_len),
+                                                 "disassociated: '%*pE' %pM\n",
+                                                 priv->essid_len, priv->essid,
                                                  priv->bssid);
 
                                        priv->status &=
@@ -4676,9 +4667,8 @@ static void ipw_rx_notification(struct ipw_priv *priv,
                        switch (auth->state) {
                        case CMAS_AUTHENTICATED:
                                IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE,
-                                         "authenticated: '%s' %pM\n",
-                                         print_ssid(ssid, priv->essid,
-                                                    priv->essid_len),
+                                         "authenticated: '%*pE' %pM\n",
+                                         priv->essid_len, priv->essid,
                                          priv->bssid);
                                priv->status |= STATUS_AUTH;
                                break;
@@ -4695,9 +4685,8 @@ static void ipw_rx_notification(struct ipw_priv *priv,
                                }
                                IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
                                          IPW_DL_ASSOC,
-                                         "deauthenticated: '%s' %pM\n",
-                                         print_ssid(ssid, priv->essid,
-                                                    priv->essid_len),
+                                         "deauthenticated: '%*pE' %pM\n",
+                                         priv->essid_len, priv->essid,
                                          priv->bssid);
 
                                priv->status &= ~(STATUS_ASSOCIATING |
@@ -5516,16 +5505,13 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
                                  int roaming)
 {
        struct ipw_supported_rates rates;
-       DECLARE_SSID_BUF(ssid);
 
        /* Verify that this network's capability is compatible with the
         * current mode (AdHoc or Infrastructure) */
        if ((priv->ieee->iw_mode == IW_MODE_ADHOC &&
             !(network->capability & WLAN_CAPABILITY_IBSS))) {
-               IPW_DEBUG_MERGE("Network '%s (%pM)' excluded due to "
-                               "capability mismatch.\n",
-                               print_ssid(ssid, network->ssid,
-                                          network->ssid_len),
+               IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded due to capability mismatch.\n",
+                               network->ssid_len, network->ssid,
                                network->bssid);
                return 0;
        }
@@ -5536,10 +5522,8 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
                if ((network->ssid_len != match->network->ssid_len) ||
                    memcmp(network->ssid, match->network->ssid,
                           network->ssid_len)) {
-                       IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
-                                       "because of non-network ESSID.\n",
-                                       print_ssid(ssid, network->ssid,
-                                                  network->ssid_len),
+                       IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of non-network ESSID.\n",
+                                       network->ssid_len, network->ssid,
                                        network->bssid);
                        return 0;
                }
@@ -5550,17 +5534,10 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
                    ((network->ssid_len != priv->essid_len) ||
                     memcmp(network->ssid, priv->essid,
                            min(network->ssid_len, priv->essid_len)))) {
-                       char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
-
-                       strlcpy(escaped,
-                               print_ssid(ssid, network->ssid,
-                                          network->ssid_len),
-                               sizeof(escaped));
-                       IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
-                                       "because of ESSID mismatch: '%s'.\n",
-                                       escaped, network->bssid,
-                                       print_ssid(ssid, priv->essid,
-                                                  priv->essid_len));
+                       IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of ESSID mismatch: '%*pE'.\n",
+                                       network->ssid_len, network->ssid,
+                                       network->bssid, priv->essid_len,
+                                       priv->essid);
                        return 0;
                }
        }
@@ -5569,26 +5546,20 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
         * testing everything else. */
 
        if (network->time_stamp[0] < match->network->time_stamp[0]) {
-               IPW_DEBUG_MERGE("Network '%s excluded because newer than "
-                               "current network.\n",
-                               print_ssid(ssid, match->network->ssid,
-                                          match->network->ssid_len));
+               IPW_DEBUG_MERGE("Network '%*pE excluded because newer than current network.\n",
+                               match->network->ssid_len, match->network->ssid);
                return 0;
        } else if (network->time_stamp[1] < match->network->time_stamp[1]) {
-               IPW_DEBUG_MERGE("Network '%s excluded because newer than "
-                               "current network.\n",
-                               print_ssid(ssid, match->network->ssid,
-                                          match->network->ssid_len));
+               IPW_DEBUG_MERGE("Network '%*pE excluded because newer than current network.\n",
+                               match->network->ssid_len, match->network->ssid);
                return 0;
        }
 
        /* Now go through and see if the requested network is valid... */
        if (priv->ieee->scan_age != 0 &&
            time_after(jiffies, network->last_scanned + priv->ieee->scan_age)) {
-               IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
-                               "because of age: %ums.\n",
-                               print_ssid(ssid, network->ssid,
-                                          network->ssid_len),
+               IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of age: %ums.\n",
+                               network->ssid_len, network->ssid,
                                network->bssid,
                                jiffies_to_msecs(jiffies -
                                                 network->last_scanned));
@@ -5597,10 +5568,8 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
 
        if ((priv->config & CFG_STATIC_CHANNEL) &&
            (network->channel != priv->channel)) {
-               IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
-                               "because of channel mismatch: %d != %d.\n",
-                               print_ssid(ssid, network->ssid,
-                                          network->ssid_len),
+               IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of channel mismatch: %d != %d.\n",
+                               network->ssid_len, network->ssid,
                                network->bssid,
                                network->channel, priv->channel);
                return 0;
@@ -5609,10 +5578,8 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
        /* Verify privacy compatibility */
        if (((priv->capability & CAP_PRIVACY_ON) ? 1 : 0) !=
            ((network->capability & WLAN_CAPABILITY_PRIVACY) ? 1 : 0)) {
-               IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
-                               "because of privacy mismatch: %s != %s.\n",
-                               print_ssid(ssid, network->ssid,
-                                          network->ssid_len),
+               IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of privacy mismatch: %s != %s.\n",
+                               network->ssid_len, network->ssid,
                                network->bssid,
                                priv->
                                capability & CAP_PRIVACY_ON ? "on" : "off",
@@ -5623,22 +5590,16 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
        }
 
        if (ether_addr_equal(network->bssid, priv->bssid)) {
-               IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
-                               "because of the same BSSID match: %pM"
-                               ".\n", print_ssid(ssid, network->ssid,
-                                                 network->ssid_len),
-                               network->bssid,
-                               priv->bssid);
+               IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of the same BSSID match: %pM.\n",
+                               network->ssid_len, network->ssid,
+                               network->bssid, priv->bssid);
                return 0;
        }
 
        /* Filter out any incompatible freq / mode combinations */
        if (!libipw_is_valid_mode(priv->ieee, network->mode)) {
-               IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
-                               "because of invalid frequency/mode "
-                               "combination.\n",
-                               print_ssid(ssid, network->ssid,
-                                          network->ssid_len),
+               IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of invalid frequency/mode combination.\n",
+                               network->ssid_len, network->ssid,
                                network->bssid);
                return 0;
        }
@@ -5646,20 +5607,15 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
        /* Ensure that the rates supported by the driver are compatible with
         * this AP, including verification of basic rates (mandatory) */
        if (!ipw_compatible_rates(priv, network, &rates)) {
-               IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
-                               "because configured rate mask excludes "
-                               "AP mandatory rate.\n",
-                               print_ssid(ssid, network->ssid,
-                                          network->ssid_len),
+               IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because configured rate mask excludes AP mandatory rate.\n",
+                               network->ssid_len, network->ssid,
                                network->bssid);
                return 0;
        }
 
        if (rates.num_rates == 0) {
-               IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
-                               "because of no compatible rates.\n",
-                               print_ssid(ssid, network->ssid,
-                                          network->ssid_len),
+               IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of no compatible rates.\n",
+                               network->ssid_len, network->ssid,
                                network->bssid);
                return 0;
        }
@@ -5671,16 +5627,14 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
        /* Set up 'new' AP to this network */
        ipw_copy_rates(&match->rates, &rates);
        match->network = network;
-       IPW_DEBUG_MERGE("Network '%s (%pM)' is a viable match.\n",
-                       print_ssid(ssid, network->ssid, network->ssid_len),
-                       network->bssid);
+       IPW_DEBUG_MERGE("Network '%*pE (%pM)' is a viable match.\n",
+                       network->ssid_len, network->ssid, network->bssid);
 
        return 1;
 }
 
 static void ipw_merge_adhoc_network(struct work_struct *work)
 {
-       DECLARE_SSID_BUF(ssid);
        struct ipw_priv *priv =
                container_of(work, struct ipw_priv, merge_networks);
        struct libipw_network *network = NULL;
@@ -5710,9 +5664,8 @@ static void ipw_merge_adhoc_network(struct work_struct *work)
 
                mutex_lock(&priv->mutex);
                if ((priv->ieee->iw_mode == IW_MODE_ADHOC)) {
-                       IPW_DEBUG_MERGE("remove network %s\n",
-                                       print_ssid(ssid, priv->essid,
-                                                  priv->essid_len));
+                       IPW_DEBUG_MERGE("remove network %*pE\n",
+                                       priv->essid_len, priv->essid);
                        ipw_remove_current_network(priv);
                }
 
@@ -5728,7 +5681,6 @@ static int ipw_best_network(struct ipw_priv *priv,
                            struct libipw_network *network, int roaming)
 {
        struct ipw_supported_rates rates;
-       DECLARE_SSID_BUF(ssid);
 
        /* Verify that this network's capability is compatible with the
         * current mode (AdHoc or Infrastructure) */
@@ -5736,10 +5688,8 @@ static int ipw_best_network(struct ipw_priv *priv,
             !(network->capability & WLAN_CAPABILITY_ESS)) ||
            (priv->ieee->iw_mode == IW_MODE_ADHOC &&
             !(network->capability & WLAN_CAPABILITY_IBSS))) {
-               IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded due to "
-                               "capability mismatch.\n",
-                               print_ssid(ssid, network->ssid,
-                                          network->ssid_len),
+               IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded due to capability mismatch.\n",
+                               network->ssid_len, network->ssid,
                                network->bssid);
                return 0;
        }
@@ -5750,10 +5700,8 @@ static int ipw_best_network(struct ipw_priv *priv,
                if ((network->ssid_len != match->network->ssid_len) ||
                    memcmp(network->ssid, match->network->ssid,
                           network->ssid_len)) {
-                       IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
-                                       "because of non-network ESSID.\n",
-                                       print_ssid(ssid, network->ssid,
-                                                  network->ssid_len),
+                       IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of non-network ESSID.\n",
+                                       network->ssid_len, network->ssid,
                                        network->bssid);
                        return 0;
                }
@@ -5764,16 +5712,10 @@ static int ipw_best_network(struct ipw_priv *priv,
                    ((network->ssid_len != priv->essid_len) ||
                     memcmp(network->ssid, priv->essid,
                            min(network->ssid_len, priv->essid_len)))) {
-                       char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
-                       strlcpy(escaped,
-                               print_ssid(ssid, network->ssid,
-                                          network->ssid_len),
-                               sizeof(escaped));
-                       IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
-                                       "because of ESSID mismatch: '%s'.\n",
-                                       escaped, network->bssid,
-                                       print_ssid(ssid, priv->essid,
-                                                  priv->essid_len));
+                       IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of ESSID mismatch: '%*pE'.\n",
+                                       network->ssid_len, network->ssid,
+                                       network->bssid, priv->essid_len,
+                                       priv->essid);
                        return 0;
                }
        }
@@ -5781,16 +5723,10 @@ static int ipw_best_network(struct ipw_priv *priv,
        /* If the old network rate is better than this one, don't bother
         * testing everything else. */
        if (match->network && match->network->stats.rssi > network->stats.rssi) {
-               char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
-               strlcpy(escaped,
-                       print_ssid(ssid, network->ssid, network->ssid_len),
-                       sizeof(escaped));
-               IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded because "
-                               "'%s (%pM)' has a stronger signal.\n",
-                               escaped, network->bssid,
-                               print_ssid(ssid, match->network->ssid,
-                                          match->network->ssid_len),
-                               match->network->bssid);
+               IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because '%*pE (%pM)' has a stronger signal.\n",
+                               network->ssid_len, network->ssid,
+                               network->bssid, match->network->ssid_len,
+                               match->network->ssid, match->network->bssid);
                return 0;
        }
 
@@ -5798,11 +5734,8 @@ static int ipw_best_network(struct ipw_priv *priv,
         * last 3 seconds, do not try and associate again... */
        if (network->last_associate &&
            time_after(network->last_associate + (HZ * 3UL), jiffies)) {
-               IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
-                               "because of storming (%ums since last "
-                               "assoc attempt).\n",
-                               print_ssid(ssid, network->ssid,
-                                          network->ssid_len),
+               IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of storming (%ums since last assoc attempt).\n",
+                               network->ssid_len, network->ssid,
                                network->bssid,
                                jiffies_to_msecs(jiffies -
                                                 network->last_associate));
@@ -5812,10 +5745,8 @@ static int ipw_best_network(struct ipw_priv *priv,
        /* Now go through and see if the requested network is valid... */
        if (priv->ieee->scan_age != 0 &&
            time_after(jiffies, network->last_scanned + priv->ieee->scan_age)) {
-               IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
-                               "because of age: %ums.\n",
-                               print_ssid(ssid, network->ssid,
-                                          network->ssid_len),
+               IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of age: %ums.\n",
+                               network->ssid_len, network->ssid,
                                network->bssid,
                                jiffies_to_msecs(jiffies -
                                                 network->last_scanned));
@@ -5824,10 +5755,8 @@ static int ipw_best_network(struct ipw_priv *priv,
 
        if ((priv->config & CFG_STATIC_CHANNEL) &&
            (network->channel != priv->channel)) {
-               IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
-                               "because of channel mismatch: %d != %d.\n",
-                               print_ssid(ssid, network->ssid,
-                                          network->ssid_len),
+               IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of channel mismatch: %d != %d.\n",
+                               network->ssid_len, network->ssid,
                                network->bssid,
                                network->channel, priv->channel);
                return 0;
@@ -5836,10 +5765,8 @@ static int ipw_best_network(struct ipw_priv *priv,
        /* Verify privacy compatibility */
        if (((priv->capability & CAP_PRIVACY_ON) ? 1 : 0) !=
            ((network->capability & WLAN_CAPABILITY_PRIVACY) ? 1 : 0)) {
-               IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
-                               "because of privacy mismatch: %s != %s.\n",
-                               print_ssid(ssid, network->ssid,
-                                          network->ssid_len),
+               IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of privacy mismatch: %s != %s.\n",
+                               network->ssid_len, network->ssid,
                                network->bssid,
                                priv->capability & CAP_PRIVACY_ON ? "on" :
                                "off",
@@ -5850,31 +5777,24 @@ static int ipw_best_network(struct ipw_priv *priv,
 
        if ((priv->config & CFG_STATIC_BSSID) &&
            !ether_addr_equal(network->bssid, priv->bssid)) {
-               IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
-                               "because of BSSID mismatch: %pM.\n",
-                               print_ssid(ssid, network->ssid,
-                                          network->ssid_len),
+               IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of BSSID mismatch: %pM.\n",
+                               network->ssid_len, network->ssid,
                                network->bssid, priv->bssid);
                return 0;
        }
 
        /* Filter out any incompatible freq / mode combinations */
        if (!libipw_is_valid_mode(priv->ieee, network->mode)) {
-               IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
-                               "because of invalid frequency/mode "
-                               "combination.\n",
-                               print_ssid(ssid, network->ssid,
-                                          network->ssid_len),
+               IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of invalid frequency/mode combination.\n",
+                               network->ssid_len, network->ssid,
                                network->bssid);
                return 0;
        }
 
        /* Filter out invalid channel in current GEO */
        if (!libipw_is_valid_channel(priv->ieee, network->channel)) {
-               IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
-                               "because of invalid channel in current GEO\n",
-                               print_ssid(ssid, network->ssid,
-                                          network->ssid_len),
+               IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of invalid channel in current GEO\n",
+                               network->ssid_len, network->ssid,
                                network->bssid);
                return 0;
        }
@@ -5882,20 +5802,15 @@ static int ipw_best_network(struct ipw_priv *priv,
        /* Ensure that the rates supported by the driver are compatible with
         * this AP, including verification of basic rates (mandatory) */
        if (!ipw_compatible_rates(priv, network, &rates)) {
-               IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
-                               "because configured rate mask excludes "
-                               "AP mandatory rate.\n",
-                               print_ssid(ssid, network->ssid,
-                                          network->ssid_len),
+               IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because configured rate mask excludes AP mandatory rate.\n",
+                               network->ssid_len, network->ssid,
                                network->bssid);
                return 0;
        }
 
        if (rates.num_rates == 0) {
-               IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
-                               "because of no compatible rates.\n",
-                               print_ssid(ssid, network->ssid,
-                                          network->ssid_len),
+               IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of no compatible rates.\n",
+                               network->ssid_len, network->ssid,
                                network->bssid);
                return 0;
        }
@@ -5908,9 +5823,8 @@ static int ipw_best_network(struct ipw_priv *priv,
        ipw_copy_rates(&match->rates, &rates);
        match->network = network;
 
-       IPW_DEBUG_ASSOC("Network '%s (%pM)' is a viable match.\n",
-                       print_ssid(ssid, network->ssid, network->ssid_len),
-                       network->bssid);
+       IPW_DEBUG_ASSOC("Network '%*pE (%pM)' is a viable match.\n",
+                       network->ssid_len, network->ssid, network->bssid);
 
        return 1;
 }
@@ -6152,7 +6066,6 @@ static void ipw_bg_adhoc_check(struct work_struct *work)
 
 static void ipw_debug_config(struct ipw_priv *priv)
 {
-       DECLARE_SSID_BUF(ssid);
        IPW_DEBUG_INFO("Scan completed, no valid APs matched "
                       "[CFG 0x%08X]\n", priv->config);
        if (priv->config & CFG_STATIC_CHANNEL)
@@ -6160,8 +6073,8 @@ static void ipw_debug_config(struct ipw_priv *priv)
        else
                IPW_DEBUG_INFO("Channel unlocked.\n");
        if (priv->config & CFG_STATIC_ESSID)
-               IPW_DEBUG_INFO("ESSID locked to '%s'\n",
-                              print_ssid(ssid, priv->essid, priv->essid_len));
+               IPW_DEBUG_INFO("ESSID locked to '%*pE'\n",
+                              priv->essid_len, priv->essid);
        else
                IPW_DEBUG_INFO("ESSID unlocked.\n");
        if (priv->config & CFG_STATIC_BSSID)
@@ -7385,7 +7298,6 @@ static int ipw_associate_network(struct ipw_priv *priv,
                                 struct ipw_supported_rates *rates, int roaming)
 {
        int err;
-       DECLARE_SSID_BUF(ssid);
 
        if (priv->config & CFG_FIXED_RATE)
                ipw_set_fixed_rate(priv, network->mode);
@@ -7451,10 +7363,9 @@ static int ipw_associate_network(struct ipw_priv *priv,
                priv->assoc_request.capability &=
                    ~cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME);
 
-       IPW_DEBUG_ASSOC("%ssociation attempt: '%s', channel %d, "
-                       "802.11%c [%d], %s[:%s], enc=%s%s%s%c%c\n",
+       IPW_DEBUG_ASSOC("%ssociation attempt: '%*pE', channel %d, 802.11%c [%d], %s[:%s], enc=%s%s%s%c%c\n",
                        roaming ? "Rea" : "A",
-                       print_ssid(ssid, priv->essid, priv->essid_len),
+                       priv->essid_len, priv->essid,
                        network->channel,
                        ipw_modes[priv->assoc_request.ieee_mode],
                        rates->num_rates,
@@ -7553,9 +7464,8 @@ static int ipw_associate_network(struct ipw_priv *priv,
                return err;
        }
 
-       IPW_DEBUG(IPW_DL_STATE, "associating: '%s' %pM\n",
-                 print_ssid(ssid, priv->essid, priv->essid_len),
-                 priv->bssid);
+       IPW_DEBUG(IPW_DL_STATE, "associating: '%*pE' %pM\n",
+                 priv->essid_len, priv->essid, priv->bssid);
 
        return 0;
 }
@@ -7645,7 +7555,6 @@ static int ipw_associate(void *data)
        struct ipw_supported_rates *rates;
        struct list_head *element;
        unsigned long flags;
-       DECLARE_SSID_BUF(ssid);
 
        if (priv->ieee->iw_mode == IW_MODE_MONITOR) {
                IPW_DEBUG_ASSOC("Not attempting association (monitor mode)\n");
@@ -7704,10 +7613,8 @@ static int ipw_associate(void *data)
                        /* If there are no more slots, expire the oldest */
                        list_del(&oldest->list);
                        target = oldest;
-                       IPW_DEBUG_ASSOC("Expired '%s' (%pM) from "
-                                       "network list.\n",
-                                       print_ssid(ssid, target->ssid,
-                                                  target->ssid_len),
+                       IPW_DEBUG_ASSOC("Expired '%*pE' (%pM) from network list.\n",
+                                       target->ssid_len, target->ssid,
                                        target->bssid);
                        list_add_tail(&target->list,
                                      &priv->ieee->network_free_list);
@@ -9093,7 +9000,6 @@ static int ipw_wx_set_essid(struct net_device *dev,
 {
        struct ipw_priv *priv = libipw_priv(dev);
         int length;
-       DECLARE_SSID_BUF(ssid);
 
         mutex_lock(&priv->mutex);
 
@@ -9118,8 +9024,7 @@ static int ipw_wx_set_essid(struct net_device *dev,
                return 0;
        }
 
-       IPW_DEBUG_WX("Setting ESSID: '%s' (%d)\n",
-                    print_ssid(ssid, extra, length), length);
+       IPW_DEBUG_WX("Setting ESSID: '%*pE' (%d)\n", length, extra, length);
 
        priv->essid_len = length;
        memcpy(priv->essid, extra, priv->essid_len);
@@ -9138,15 +9043,14 @@ static int ipw_wx_get_essid(struct net_device *dev,
                            union iwreq_data *wrqu, char *extra)
 {
        struct ipw_priv *priv = libipw_priv(dev);
-       DECLARE_SSID_BUF(ssid);
 
        /* If we are associated, trying to associate, or have a statically
         * configured ESSID then return that; otherwise return ANY */
        mutex_lock(&priv->mutex);
        if (priv->config & CFG_STATIC_ESSID ||
            priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) {
-               IPW_DEBUG_WX("Getting essid: '%s'\n",
-                            print_ssid(ssid, priv->essid, priv->essid_len));
+               IPW_DEBUG_WX("Getting essid: '%*pE'\n",
+                            priv->essid_len, priv->essid);
                memcpy(extra, priv->essid, priv->essid_len);
                wrqu->essid.length = priv->essid_len;
                wrqu->essid.flags = 1;  /* active */
index a586a85bfcfe88ccd6378ad476caca6b9aa10a15..2d66984079bb1f1bc928c1aed037851285a22ea6 100644 (file)
@@ -1120,7 +1120,6 @@ static int libipw_parse_info_param(struct libipw_info_element
                                      *info_element, u16 length,
                                      struct libipw_network *network)
 {
-       DECLARE_SSID_BUF(ssid);
        u8 i;
 #ifdef CONFIG_LIBIPW_DEBUG
        char rates_str[64];
@@ -1151,10 +1150,9 @@ static int libipw_parse_info_param(struct libipw_info_element
                                memset(network->ssid + network->ssid_len, 0,
                                       IW_ESSID_MAX_SIZE - network->ssid_len);
 
-                       LIBIPW_DEBUG_MGMT("WLAN_EID_SSID: '%s' len=%d.\n",
-                                            print_ssid(ssid, network->ssid,
-                                                       network->ssid_len),
-                                            network->ssid_len);
+                       LIBIPW_DEBUG_MGMT("WLAN_EID_SSID: '%*pE' len=%d.\n",
+                                         network->ssid_len, network->ssid,
+                                         network->ssid_len);
                        break;
 
                case WLAN_EID_SUPP_RATES:
@@ -1399,8 +1397,6 @@ static int libipw_network_init(struct libipw_device *ieee, struct libipw_probe_r
                                         struct libipw_network *network,
                                         struct libipw_rx_stats *stats)
 {
-       DECLARE_SSID_BUF(ssid);
-
        network->qos_data.active = 0;
        network->qos_data.supported = 0;
        network->qos_data.param_count = 0;
@@ -1447,11 +1443,9 @@ static int libipw_network_init(struct libipw_device *ieee, struct libipw_probe_r
        }
 
        if (network->mode == 0) {
-               LIBIPW_DEBUG_SCAN("Filtered out '%s (%pM)' "
-                                    "network.\n",
-                                    print_ssid(ssid, network->ssid,
-                                                network->ssid_len),
-                                    network->bssid);
+               LIBIPW_DEBUG_SCAN("Filtered out '%*pE (%pM)' network.\n",
+                                 network->ssid_len, network->ssid,
+                                 network->bssid);
                return 1;
        }
 
@@ -1563,11 +1557,9 @@ static void libipw_process_probe_response(struct libipw_device
        struct libipw_info_element *info_element = beacon->info_element;
 #endif
        unsigned long flags;
-       DECLARE_SSID_BUF(ssid);
 
-       LIBIPW_DEBUG_SCAN("'%s' (%pM"
-                    "): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
-                    print_ssid(ssid, info_element->data, info_element->len),
+       LIBIPW_DEBUG_SCAN("'%*pE' (%pM): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
+                    info_element->len, info_element->data,
                     beacon->header.addr3,
                     (beacon->capability & cpu_to_le16(1 << 0xf)) ? '1' : '0',
                     (beacon->capability & cpu_to_le16(1 << 0xe)) ? '1' : '0',
@@ -1587,12 +1579,11 @@ static void libipw_process_probe_response(struct libipw_device
                     (beacon->capability & cpu_to_le16(1 << 0x0)) ? '1' : '0');
 
        if (libipw_network_init(ieee, beacon, &network, stats)) {
-               LIBIPW_DEBUG_SCAN("Dropped '%s' (%pM) via %s.\n",
-                                    print_ssid(ssid, info_element->data,
-                                                info_element->len),
-                                    beacon->header.addr3,
-                                    is_beacon(beacon->header.frame_ctl) ?
-                                    "BEACON" : "PROBE RESPONSE");
+               LIBIPW_DEBUG_SCAN("Dropped '%*pE' (%pM) via %s.\n",
+                                 info_element->len, info_element->data,
+                                 beacon->header.addr3,
+                                 is_beacon(beacon->header.frame_ctl) ?
+                                 "BEACON" : "PROBE RESPONSE");
                return;
        }
 
@@ -1624,11 +1615,9 @@ static void libipw_process_probe_response(struct libipw_device
                        /* If there are no more slots, expire the oldest */
                        list_del(&oldest->list);
                        target = oldest;
-                       LIBIPW_DEBUG_SCAN("Expired '%s' (%pM) from "
-                                            "network list.\n",
-                                            print_ssid(ssid, target->ssid,
-                                                        target->ssid_len),
-                                            target->bssid);
+                       LIBIPW_DEBUG_SCAN("Expired '%*pE' (%pM) from network list.\n",
+                                         target->ssid_len, target->ssid,
+                                         target->bssid);
                        libipw_network_reset(target);
                } else {
                        /* Otherwise just pull from the free list */
@@ -1638,23 +1627,21 @@ static void libipw_process_probe_response(struct libipw_device
                }
 
 #ifdef CONFIG_LIBIPW_DEBUG
-               LIBIPW_DEBUG_SCAN("Adding '%s' (%pM) via %s.\n",
-                                    print_ssid(ssid, network.ssid,
-                                                network.ssid_len),
-                                    network.bssid,
-                                    is_beacon(beacon->header.frame_ctl) ?
-                                    "BEACON" : "PROBE RESPONSE");
+               LIBIPW_DEBUG_SCAN("Adding '%*pE' (%pM) via %s.\n",
+                                 network.ssid_len, network.ssid,
+                                 network.bssid,
+                                 is_beacon(beacon->header.frame_ctl) ?
+                                 "BEACON" : "PROBE RESPONSE");
 #endif
                memcpy(target, &network, sizeof(*target));
                network.ibss_dfs = NULL;
                list_add_tail(&target->list, &ieee->network_list);
        } else {
-               LIBIPW_DEBUG_SCAN("Updating '%s' (%pM) via %s.\n",
-                                    print_ssid(ssid, target->ssid,
-                                                target->ssid_len),
-                                    target->bssid,
-                                    is_beacon(beacon->header.frame_ctl) ?
-                                    "BEACON" : "PROBE RESPONSE");
+               LIBIPW_DEBUG_SCAN("Updating '%*pE' (%pM) via %s.\n",
+                                 target->ssid_len, target->ssid,
+                                 target->bssid,
+                                 is_beacon(beacon->header.frame_ctl) ?
+                                 "BEACON" : "PROBE RESPONSE");
                update_network(target, &network);
                network.ibss_dfs = NULL;
        }
index 54aba474443867f463714e117f14a605ba251803..dd29f46d086b2bf2f60586655fb59ff9647c0b0c 100644 (file)
@@ -272,7 +272,6 @@ int libipw_wx_get_scan(struct libipw_device *ieee,
        char *ev = extra;
        char *stop = ev + wrqu->data.length;
        int i = 0;
-       DECLARE_SSID_BUF(ssid);
 
        LIBIPW_DEBUG_WX("Getting scan\n");
 
@@ -290,12 +289,10 @@ int libipw_wx_get_scan(struct libipw_device *ieee,
                        ev = libipw_translate_scan(ieee, ev, stop, network,
                                                      info);
                else {
-                       LIBIPW_DEBUG_SCAN("Not showing network '%s ("
-                                            "%pM)' due to age (%ums).\n",
-                                            print_ssid(ssid, network->ssid,
-                                                        network->ssid_len),
-                                            network->bssid,
-                                            elapsed_jiffies_msecs(
+                       LIBIPW_DEBUG_SCAN("Not showing network '%*pE (%pM)' due to age (%ums).\n",
+                                         network->ssid_len, network->ssid,
+                                         network->bssid,
+                                         elapsed_jiffies_msecs(
                                                       network->last_scanned));
                }
        }
@@ -322,7 +319,6 @@ int libipw_wx_set_encode(struct libipw_device *ieee,
        int i, key, key_provided, len;
        struct lib80211_crypt_data **crypt;
        int host_crypto = ieee->host_encrypt || ieee->host_decrypt;
-       DECLARE_SSID_BUF(ssid);
 
        LIBIPW_DEBUG_WX("SET_ENCODE\n");
 
@@ -417,8 +413,8 @@ int libipw_wx_set_encode(struct libipw_device *ieee,
                if (len > erq->length)
                        memset(sec.keys[key] + erq->length, 0,
                               len - erq->length);
-               LIBIPW_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
-                                  key, print_ssid(ssid, sec.keys[key], len),
+               LIBIPW_DEBUG_WX("Setting key %d to '%*pE' (%d:%d bytes)\n",
+                                  key, len, sec.keys[key],
                                   erq->length, len);
                sec.key_sizes[key] = len;
                if (*crypt)
index 818b1edaaa9aa5d38f3176828ca2ed3802fb3fde..34f09ef90bb31bbc02f0fda014c27ed3dfa52e72 100644 (file)
@@ -590,7 +590,6 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy,
                int chan_no = -1;
                const u8 *ssid = NULL;
                u8 ssid_len = 0;
-               DECLARE_SSID_BUF(ssid_buf);
 
                int len = get_unaligned_le16(pos);
                pos += 2;
@@ -644,10 +643,8 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy,
                        struct ieee80211_channel *channel =
                                ieee80211_get_channel(wiphy, freq);
 
-                       lbs_deb_scan("scan: %pM, capa %04x, chan %2d, %s, "
-                                    "%d dBm\n",
-                                    bssid, capa, chan_no,
-                                    print_ssid(ssid_buf, ssid, ssid_len),
+                       lbs_deb_scan("scan: %pM, capa %04x, chan %2d, %*pE, %d dBm\n",
+                                    bssid, capa, chan_no, ssid_len, ssid,
                                     LBS_SCAN_RSSI_TO_MBM(rssi)/100);
 
                        if (channel &&
@@ -1984,7 +1981,6 @@ static int lbs_join_ibss(struct wiphy *wiphy, struct net_device *dev,
        struct lbs_private *priv = wiphy_priv(wiphy);
        int ret = 0;
        struct cfg80211_bss *bss;
-       DECLARE_SSID_BUF(ssid_buf);
 
        if (dev == priv->mesh_dev)
                return -EOPNOTSUPP;
index 01a67f62696f74788e6e4b01eb717f1f6d7fb75c..d0c881dd584677f18c551657d351b6bee435da5f 100644 (file)
@@ -93,7 +93,6 @@ static int lbs_mesh_config(struct lbs_private *priv, uint16_t action,
 {
        struct cmd_ds_mesh_config cmd;
        struct mrvl_meshie *ie;
-       DECLARE_SSID_BUF(ssid);
 
        memset(&cmd, 0, sizeof(cmd));
        cmd.channel = cpu_to_le16(chan);
@@ -122,9 +121,9 @@ static int lbs_mesh_config(struct lbs_private *priv, uint16_t action,
        default:
                return -1;
        }
-       lbs_deb_cmd("mesh config action %d type %x channel %d SSID %s\n",
-                   action, priv->mesh_tlv, chan,
-                   print_ssid(ssid, priv->mesh_ssid, priv->mesh_ssid_len));
+       lbs_deb_cmd("mesh config action %d type %x channel %d SSID %*pE\n",
+                   action, priv->mesh_tlv, chan, priv->mesh_ssid_len,
+                   priv->mesh_ssid);
 
        return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv);
 }
index f959978c7aacdfca1da94b25021f1c86af1bcfb4..cf0f89364d4411f8321bdf69bff7b64725b5612f 100644 (file)
@@ -8878,13 +8878,13 @@ static int __must_check __init get_thinkpad_model_data(
        }
 
        s = dmi_get_system_info(DMI_PRODUCT_VERSION);
-       if (s && !(strnicmp(s, "ThinkPad", 8) && strnicmp(s, "Lenovo", 6))) {
+       if (s && !(strncasecmp(s, "ThinkPad", 8) && strncasecmp(s, "Lenovo", 6))) {
                tp->model_str = kstrdup(s, GFP_KERNEL);
                if (!tp->model_str)
                        return -ENOMEM;
        } else {
                s = dmi_get_system_info(DMI_BIOS_VENDOR);
-               if (s && !(strnicmp(s, "Lenovo", 6))) {
+               if (s && !(strncasecmp(s, "Lenovo", 6))) {
                        tp->model_str = kstrdup(s, GFP_KERNEL);
                        if (!tp->model_str)
                                return -ENOMEM;
index e6c403be09a924b7fe795e973dafb227a089affe..4b6808ff0e5df3517f5e72a9fdd71ed6f05d0a9e 100644 (file)
@@ -346,41 +346,41 @@ static ssize_t resources_store(struct device *dmdev,
        }
 
        buf = skip_spaces(buf);
-       if (!strnicmp(buf, "disable", 7)) {
+       if (!strncasecmp(buf, "disable", 7)) {
                retval = pnp_disable_dev(dev);
                goto done;
        }
-       if (!strnicmp(buf, "activate", 8)) {
+       if (!strncasecmp(buf, "activate", 8)) {
                retval = pnp_activate_dev(dev);
                goto done;
        }
-       if (!strnicmp(buf, "fill", 4)) {
+       if (!strncasecmp(buf, "fill", 4)) {
                if (dev->active)
                        goto done;
                retval = pnp_auto_config_dev(dev);
                goto done;
        }
-       if (!strnicmp(buf, "auto", 4)) {
+       if (!strncasecmp(buf, "auto", 4)) {
                if (dev->active)
                        goto done;
                pnp_init_resources(dev);
                retval = pnp_auto_config_dev(dev);
                goto done;
        }
-       if (!strnicmp(buf, "clear", 5)) {
+       if (!strncasecmp(buf, "clear", 5)) {
                if (dev->active)
                        goto done;
                pnp_init_resources(dev);
                goto done;
        }
-       if (!strnicmp(buf, "get", 3)) {
+       if (!strncasecmp(buf, "get", 3)) {
                mutex_lock(&pnp_res_mutex);
                if (pnp_can_read(dev))
                        dev->protocol->get(dev);
                mutex_unlock(&pnp_res_mutex);
                goto done;
        }
-       if (!strnicmp(buf, "set", 3)) {
+       if (!strncasecmp(buf, "set", 3)) {
                resource_size_t start;
                resource_size_t end;
                unsigned long flags;
@@ -392,31 +392,31 @@ static ssize_t resources_store(struct device *dmdev,
                mutex_lock(&pnp_res_mutex);
                while (1) {
                        buf = skip_spaces(buf);
-                       if (!strnicmp(buf, "io", 2)) {
+                       if (!strncasecmp(buf, "io", 2)) {
                                buf = pnp_get_resource_value(buf + 2,
                                                             IORESOURCE_IO,
                                                             &start, &end,
                                                             &flags);
                                pnp_add_io_resource(dev, start, end, flags);
-                       } else if (!strnicmp(buf, "mem", 3)) {
+                       } else if (!strncasecmp(buf, "mem", 3)) {
                                buf = pnp_get_resource_value(buf + 3,
                                                             IORESOURCE_MEM,
                                                             &start, &end,
                                                             &flags);
                                pnp_add_mem_resource(dev, start, end, flags);
-                       } else if (!strnicmp(buf, "irq", 3)) {
+                       } else if (!strncasecmp(buf, "irq", 3)) {
                                buf = pnp_get_resource_value(buf + 3,
                                                             IORESOURCE_IRQ,
                                                             &start, NULL,
                                                             &flags);
                                pnp_add_irq_resource(dev, start, flags);
-                       } else if (!strnicmp(buf, "dma", 3)) {
+                       } else if (!strncasecmp(buf, "dma", 3)) {
                                buf = pnp_get_resource_value(buf + 3,
                                                             IORESOURCE_DMA,
                                                             &start, NULL,
                                                             &flags);
                                pnp_add_dma_resource(dev, start, flags);
-                       } else if (!strnicmp(buf, "bus", 3)) {
+                       } else if (!strncasecmp(buf, "bus", 3)) {
                                buf = pnp_get_resource_value(buf + 3,
                                                             IORESOURCE_BUS,
                                                             &start, &end,
index 1bea0fc43464f9dcc2ce3f94a87d3628590d6de5..8cd0beebdc3f0464670893eec27222b5d11c8b69 100644 (file)
@@ -288,6 +288,26 @@ config RTC_DRV_MAX77686
          This driver can also be built as a module. If so, the module
          will be called rtc-max77686.
 
+config RTC_DRV_RK808
+       tristate "Rockchip RK808 RTC"
+       depends on MFD_RK808
+       help
+         If you say yes here you will get support for the
+         RTC of RK808 PMIC.
+
+         This driver can also be built as a module. If so, the module
+         will be called rk808-rtc.
+
+config RTC_DRV_MAX77802
+       tristate "Maxim 77802 RTC"
+       depends on MFD_MAX77686
+       help
+         If you say yes here you will get support for the
+         RTC of Maxim MAX77802 PMIC.
+
+         This driver can also be built as a module. If so, the module
+         will be called rtc-max77802.
+
 config RTC_DRV_RS5C372
        tristate "Ricoh R2025S/D, RS5C372A/B, RV5C386, RV5C387A"
        help
@@ -732,6 +752,7 @@ config RTC_DRV_DS1216
 
 config RTC_DRV_DS1286
        tristate "Dallas DS1286"
+       depends on HAS_IOMEM
        help
          If you say yes here you get support for the Dallas DS1286 RTC chips.
 
@@ -743,6 +764,7 @@ config RTC_DRV_DS1302
 
 config RTC_DRV_DS1511
        tristate "Dallas DS1511"
+       depends on HAS_IOMEM
        help
          If you say yes here you get support for the
          Dallas DS1511 timekeeping/watchdog chip.
@@ -752,6 +774,7 @@ config RTC_DRV_DS1511
 
 config RTC_DRV_DS1553
        tristate "Maxim/Dallas DS1553"
+       depends on HAS_IOMEM
        help
          If you say yes here you get support for the
          Maxim/Dallas DS1553 timekeeping chip.
@@ -761,6 +784,7 @@ config RTC_DRV_DS1553
 
 config RTC_DRV_DS1742
        tristate "Maxim/Dallas DS1742/1743"
+       depends on HAS_IOMEM
        help
          If you say yes here you get support for the
          Maxim/Dallas DS1742/1743 timekeeping chip.
@@ -816,6 +840,7 @@ config RTC_DRV_EFI
 
 config RTC_DRV_STK17TA8
        tristate "Simtek STK17TA8"
+       depends on HAS_IOMEM
        help
          If you say yes here you get support for the
          Simtek STK17TA8 timekeeping chip.
@@ -834,6 +859,7 @@ config RTC_DRV_M48T86
 
 config RTC_DRV_M48T35
        tristate "ST M48T35"
+       depends on HAS_IOMEM
        help
          If you say Y here you will get support for the
          ST M48T35 RTC chip.
@@ -843,6 +869,7 @@ config RTC_DRV_M48T35
 
 config RTC_DRV_M48T59
        tristate "ST M48T59/M48T08/M48T02"
+       depends on HAS_IOMEM
        help
          If you say Y here you will get support for the
          ST M48T59 RTC chip and compatible ST M48T08 and M48T02.
@@ -855,6 +882,7 @@ config RTC_DRV_M48T59
 
 config RTC_DRV_MSM6242
        tristate "Oki MSM6242"
+       depends on HAS_IOMEM
        help
          If you say yes here you get support for the Oki MSM6242
          timekeeping chip. It is used in some Amiga models (e.g. A2000).
@@ -864,6 +892,7 @@ config RTC_DRV_MSM6242
 
 config RTC_DRV_BQ4802
        tristate "TI BQ4802"
+       depends on HAS_IOMEM
        help
          If you say Y here you will get support for the TI
          BQ4802 RTC chip.
@@ -873,6 +902,7 @@ config RTC_DRV_BQ4802
 
 config RTC_DRV_RP5C01
        tristate "Ricoh RP5C01"
+       depends on HAS_IOMEM
        help
          If you say yes here you get support for the Ricoh RP5C01
          timekeeping chip. It is used in some Amiga models (e.g. A3000
@@ -1374,6 +1404,7 @@ config RTC_DRV_MOXART
 
 config RTC_DRV_XGENE
        tristate "APM X-Gene RTC"
+       depends on HAS_IOMEM
        help
          If you say yes here you get support for the APM X-Gene SoC real time
          clock.
index 9055b7dd3dc5b93655088bd83f7911ca678e9d50..b188323c096a62421696fbe394a74d061939ddcb 100644 (file)
@@ -85,6 +85,7 @@ obj-$(CONFIG_RTC_DRV_MAX8998) += rtc-max8998.o
 obj-$(CONFIG_RTC_DRV_MAX8997)  += rtc-max8997.o
 obj-$(CONFIG_RTC_DRV_MAX6902)  += rtc-max6902.o
 obj-$(CONFIG_RTC_DRV_MAX77686) += rtc-max77686.o
+obj-$(CONFIG_RTC_DRV_MAX77802)  += rtc-max77802.o
 obj-$(CONFIG_RTC_DRV_MC13XXX)  += rtc-mc13xxx.o
 obj-$(CONFIG_RTC_DRV_MCP795)   += rtc-mcp795.o
 obj-$(CONFIG_RTC_DRV_MSM6242)  += rtc-msm6242.o
@@ -109,6 +110,7 @@ obj-$(CONFIG_RTC_DRV_PUV3)  += rtc-puv3.o
 obj-$(CONFIG_RTC_DRV_PXA)      += rtc-pxa.o
 obj-$(CONFIG_RTC_DRV_R9701)    += rtc-r9701.o
 obj-$(CONFIG_RTC_DRV_RC5T583)  += rtc-rc5t583.o
+obj-$(CONFIG_RTC_DRV_RK808)    += rtc-rk808.o
 obj-$(CONFIG_RTC_DRV_RP5C01)   += rtc-rp5c01.o
 obj-$(CONFIG_RTC_DRV_RS5C313)  += rtc-rs5c313.o
 obj-$(CONFIG_RTC_DRV_RS5C348)  += rtc-rs5c348.o
index c74bf0dc52cc83baa3a66de3f030f27c7a089335..314129e66d6e8fd47280202cacf19f0793848e58 100644 (file)
@@ -2,10 +2,14 @@
  * Driver for TI BQ32000 RTC.
  *
  * Copyright (C) 2009 Semihalf.
+ * Copyright (C) 2014 Pavel Machek <pavel@denx.de>
  *
  * 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.
+ *
+ * You can get hardware description at
+ * http://www.ti.com/lit/ds/symlink/bq32000.pdf
  */
 
 #include <linux/module.h>
 #define BQ32K_CENT             0x40    /* Century flag */
 #define BQ32K_CENT_EN          0x80    /* Century flag enable bit */
 
+#define BQ32K_CALIBRATION      0x07    /* CAL_CFG1, calibration and control */
+#define BQ32K_TCH2             0x08    /* Trickle charge enable */
+#define BQ32K_CFG2             0x09    /* Trickle charger control */
+
 struct bq32k_regs {
        uint8_t         seconds;
        uint8_t         minutes;
@@ -122,6 +130,57 @@ static const struct rtc_class_ops bq32k_rtc_ops = {
        .set_time       = bq32k_rtc_set_time,
 };
 
+static int trickle_charger_of_init(struct device *dev, struct device_node *node)
+{
+       unsigned char reg;
+       int error;
+       u32 ohms = 0;
+
+       if (of_property_read_u32(node, "trickle-resistor-ohms" , &ohms))
+               return 0;
+
+       switch (ohms) {
+       case 180+940:
+               /*
+                * TCHE[3:0] == 0x05, TCH2 == 1, TCFE == 0 (charging
+                * over diode and 940ohm resistor)
+                */
+
+               if (of_property_read_bool(node, "trickle-diode-disable")) {
+                       dev_err(dev, "diode and resistor mismatch\n");
+                       return -EINVAL;
+               }
+               reg = 0x05;
+               break;
+
+       case 180+20000:
+               /* diode disabled */
+
+               if (!of_property_read_bool(node, "trickle-diode-disable")) {
+                       dev_err(dev, "bq32k: diode and resistor mismatch\n");
+                       return -EINVAL;
+               }
+               reg = 0x25;
+               break;
+
+       default:
+               dev_err(dev, "invalid resistor value (%d)\n", ohms);
+               return -EINVAL;
+       }
+
+       error = bq32k_write(dev, &reg, BQ32K_CFG2, 1);
+       if (error)
+               return error;
+
+       reg = 0x20;
+       error = bq32k_write(dev, &reg, BQ32K_TCH2, 1);
+       if (error)
+               return error;
+
+       dev_info(dev, "Enabled trickle RTC battery charge.\n");
+       return 0;
+}
+
 static int bq32k_probe(struct i2c_client *client,
                                const struct i2c_device_id *id)
 {
@@ -153,6 +212,9 @@ static int bq32k_probe(struct i2c_client *client,
        if (error)
                return error;
 
+       if (client && client->dev.of_node)
+               trickle_charger_of_init(dev, client->dev.of_node);
+
        rtc = devm_rtc_device_register(&client->dev, bq32k_driver.driver.name,
                                                &bq32k_rtc_ops, THIS_MODULE);
        if (IS_ERR(rtc))
index b0e4a3eb33c7dc55d7632fd167cff27e0549b1fb..5b2e76159b419854ca8f69b8c3f99919fbab319f 100644 (file)
@@ -856,7 +856,7 @@ static void __exit cmos_do_remove(struct device *dev)
        cmos->dev = NULL;
 }
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
 
 static int cmos_suspend(struct device *dev)
 {
@@ -907,6 +907,8 @@ static inline int cmos_poweroff(struct device *dev)
        return cmos_suspend(dev);
 }
 
+#ifdef CONFIG_PM_SLEEP
+
 static int cmos_resume(struct device *dev)
 {
        struct cmos_rtc *cmos = dev_get_drvdata(dev);
@@ -954,6 +956,7 @@ static int cmos_resume(struct device *dev)
        return 0;
 }
 
+#endif
 #else
 
 static inline int cmos_poweroff(struct device *dev)
index f03d5ba96db1fe3f5e063e15957056604896570b..bb43cf703efc590bf40ba62a3de52aeea64d71b4 100644 (file)
@@ -126,9 +126,14 @@ struct chip_desc {
        u16                     nvram_offset;
        u16                     nvram_size;
        u16                     trickle_charger_reg;
+       u8                      trickle_charger_setup;
+       u8                      (*do_trickle_setup)(struct i2c_client *, uint32_t, bool);
 };
 
-static const struct chip_desc chips[last_ds_type] = {
+static u8 do_trickle_setup_ds1339(struct i2c_client *,
+                                 uint32_t ohms, bool diode);
+
+static struct chip_desc chips[last_ds_type] = {
        [ds_1307] = {
                .nvram_offset   = 8,
                .nvram_size     = 56,
@@ -143,6 +148,7 @@ static const struct chip_desc chips[last_ds_type] = {
        [ds_1339] = {
                .alarm          = 1,
                .trickle_charger_reg = 0x10,
+               .do_trickle_setup = &do_trickle_setup_ds1339,
        },
        [ds_1340] = {
                .trickle_charger_reg = 0x08,
@@ -833,15 +839,58 @@ ds1307_nvram_write(struct file *filp, struct kobject *kobj,
        return count;
 }
 
+
 /*----------------------------------------------------------------------*/
 
+static u8 do_trickle_setup_ds1339(struct i2c_client *client,
+                                 uint32_t ohms, bool diode)
+{
+       u8 setup = (diode) ? DS1307_TRICKLE_CHARGER_DIODE :
+               DS1307_TRICKLE_CHARGER_NO_DIODE;
+
+       switch (ohms) {
+       case 250:
+               setup |= DS1307_TRICKLE_CHARGER_250_OHM;
+               break;
+       case 2000:
+               setup |= DS1307_TRICKLE_CHARGER_2K_OHM;
+               break;
+       case 4000:
+               setup |= DS1307_TRICKLE_CHARGER_4K_OHM;
+               break;
+       default:
+               dev_warn(&client->dev,
+                        "Unsupported ohm value %u in dt\n", ohms);
+               return 0;
+       }
+       return setup;
+}
+
+static void ds1307_trickle_of_init(struct i2c_client *client,
+                                  struct chip_desc *chip)
+{
+       uint32_t ohms = 0;
+       bool diode = true;
+
+       if (!chip->do_trickle_setup)
+               goto out;
+       if (of_property_read_u32(client->dev.of_node, "trickle-resistor-ohms" , &ohms))
+               goto out;
+       if (of_property_read_bool(client->dev.of_node, "trickle-diode-disable"))
+               diode = false;
+       chip->trickle_charger_setup = chip->do_trickle_setup(client,
+                                                            ohms, diode);
+out:
+       return;
+}
+
 static int ds1307_probe(struct i2c_client *client,
                        const struct i2c_device_id *id)
 {
        struct ds1307           *ds1307;
        int                     err = -ENODEV;
        int                     tmp;
-       const struct chip_desc  *chip = &chips[id->driver_data];
+       struct chip_desc        *chip = &chips[id->driver_data];
        struct i2c_adapter      *adapter = to_i2c_adapter(client->dev.parent);
        bool                    want_irq = false;
        unsigned char           *buf;
@@ -866,9 +915,19 @@ static int ds1307_probe(struct i2c_client *client,
        ds1307->client  = client;
        ds1307->type    = id->driver_data;
 
-       if (pdata && pdata->trickle_charger_setup && chip->trickle_charger_reg)
+       if (!pdata && client->dev.of_node)
+               ds1307_trickle_of_init(client, chip);
+       else if (pdata && pdata->trickle_charger_setup)
+               chip->trickle_charger_setup = pdata->trickle_charger_setup;
+
+       if (chip->trickle_charger_setup && chip->trickle_charger_reg) {
+               dev_dbg(&client->dev, "writing trickle charger info 0x%x to 0x%x\n",
+                   DS13XX_TRICKLE_CHARGER_MAGIC | chip->trickle_charger_setup,
+                   chip->trickle_charger_reg);
                i2c_smbus_write_byte_data(client, chip->trickle_charger_reg,
-                       DS13XX_TRICKLE_CHARGER_MAGIC | pdata->trickle_charger_setup);
+                   DS13XX_TRICKLE_CHARGER_MAGIC |
+                   chip->trickle_charger_setup);
+       }
 
        buf = ds1307->regs;
        if (i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) {
index aa55f081c505c81bee8bf71ccfe49d85dc27fef7..ee3ba7e6b45e148d3f03c9d671ddefbcbc02f282 100644 (file)
@@ -274,7 +274,7 @@ static int isl12022_probe(struct i2c_client *client,
 }
 
 #ifdef CONFIG_OF
-static struct of_device_id isl12022_dt_match[] = {
+static const struct of_device_id isl12022_dt_match[] = {
        { .compatible = "isl,isl12022" },
        { },
 };
index d20a7f0786ebd9540625caa57c7609412569354f..cf73e969c8cc9a1ac38add953e79f6f9f6892094 100644 (file)
 #define RTC_UDR_MASK                   (1 << RTC_UDR_SHIFT)
 #define RTC_RBUDR_SHIFT                        4
 #define RTC_RBUDR_MASK                 (1 << RTC_RBUDR_SHIFT)
-/* WTSR and SMPL Register */
-#define WTSRT_SHIFT                    0
-#define SMPLT_SHIFT                    2
-#define WTSR_EN_SHIFT                  6
-#define SMPL_EN_SHIFT                  7
-#define WTSRT_MASK                     (3 << WTSRT_SHIFT)
-#define SMPLT_MASK                     (3 << SMPLT_SHIFT)
-#define WTSR_EN_MASK                   (1 << WTSR_EN_SHIFT)
-#define SMPL_EN_MASK                   (1 << SMPL_EN_SHIFT)
 /* RTC Hour register */
 #define HOUR_PM_SHIFT                  6
 #define HOUR_PM_MASK                   (1 << HOUR_PM_SHIFT)
@@ -49,7 +40,6 @@
 #define ALARM_ENABLE_MASK              (1 << ALARM_ENABLE_SHIFT)
 
 #define MAX77686_RTC_UPDATE_DELAY      16
-#undef MAX77686_RTC_WTSR_SMPL
 
 enum {
        RTC_SEC = 0,
@@ -80,16 +70,6 @@ enum MAX77686_RTC_OP {
        MAX77686_RTC_READ,
 };
 
-static inline int max77686_rtc_calculate_wday(u8 shifted)
-{
-       int counter = -1;
-       while (shifted) {
-               shifted >>= 1;
-               counter++;
-       }
-       return counter;
-}
-
 static void max77686_rtc_data_to_tm(u8 *data, struct rtc_time *tm,
                                   int rtc_24hr_mode)
 {
@@ -103,7 +83,8 @@ static void max77686_rtc_data_to_tm(u8 *data, struct rtc_time *tm,
                        tm->tm_hour += 12;
        }
 
-       tm->tm_wday = max77686_rtc_calculate_wday(data[RTC_WEEKDAY] & 0x7f);
+       /* Only a single bit is set in data[], so fls() would be equivalent */
+       tm->tm_wday = ffs(data[RTC_WEEKDAY] & 0x7f) - 1;
        tm->tm_mday = data[RTC_DATE] & 0x1f;
        tm->tm_mon = (data[RTC_MONTH] & 0x0f) - 1;
        tm->tm_year = (data[RTC_YEAR] & 0x7f) + 100;
@@ -412,64 +393,6 @@ static const struct rtc_class_ops max77686_rtc_ops = {
        .alarm_irq_enable = max77686_rtc_alarm_irq_enable,
 };
 
-#ifdef MAX77686_RTC_WTSR_SMPL
-static void max77686_rtc_enable_wtsr(struct max77686_rtc_info *info, bool enable)
-{
-       int ret;
-       unsigned int val, mask;
-
-       if (enable)
-               val = (1 << WTSR_EN_SHIFT) | (3 << WTSRT_SHIFT);
-       else
-               val = 0;
-
-       mask = WTSR_EN_MASK | WTSRT_MASK;
-
-       dev_info(info->dev, "%s: %s WTSR\n", __func__,
-                       enable ? "enable" : "disable");
-
-       ret = regmap_update_bits(info->max77686->rtc_regmap,
-                                MAX77686_WTSR_SMPL_CNTL, mask, val);
-       if (ret < 0) {
-               dev_err(info->dev, "%s: fail to update WTSR reg(%d)\n",
-                               __func__, ret);
-               return;
-       }
-
-       max77686_rtc_update(info, MAX77686_RTC_WRITE);
-}
-
-static void max77686_rtc_enable_smpl(struct max77686_rtc_info *info, bool enable)
-{
-       int ret;
-       unsigned int val, mask;
-
-       if (enable)
-               val = (1 << SMPL_EN_SHIFT) | (0 << SMPLT_SHIFT);
-       else
-               val = 0;
-
-       mask = SMPL_EN_MASK | SMPLT_MASK;
-
-       dev_info(info->dev, "%s: %s SMPL\n", __func__,
-                       enable ? "enable" : "disable");
-
-       ret = regmap_update_bits(info->max77686->rtc_regmap,
-                                MAX77686_WTSR_SMPL_CNTL, mask, val);
-       if (ret < 0) {
-               dev_err(info->dev, "%s: fail to update SMPL reg(%d)\n",
-                               __func__, ret);
-               return;
-       }
-
-       max77686_rtc_update(info, MAX77686_RTC_WRITE);
-
-       val = 0;
-       regmap_read(info->max77686->rtc_regmap, MAX77686_WTSR_SMPL_CNTL, &val);
-       dev_info(info->dev, "%s: WTSR_SMPL(0x%02x)\n", __func__, val);
-}
-#endif /* MAX77686_RTC_WTSR_SMPL */
-
 static int max77686_rtc_init_reg(struct max77686_rtc_info *info)
 {
        u8 data[2];
@@ -519,19 +442,12 @@ static int max77686_rtc_probe(struct platform_device *pdev)
                goto err_rtc;
        }
 
-#ifdef MAX77686_RTC_WTSR_SMPL
-       max77686_rtc_enable_wtsr(info, true);
-       max77686_rtc_enable_smpl(info, true);
-#endif
-
        device_init_wakeup(&pdev->dev, 1);
 
        info->rtc_dev = devm_rtc_device_register(&pdev->dev, "max77686-rtc",
                                        &max77686_rtc_ops, THIS_MODULE);
 
        if (IS_ERR(info->rtc_dev)) {
-               dev_info(&pdev->dev, "%s: fail\n", __func__);
-
                ret = PTR_ERR(info->rtc_dev);
                dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret);
                if (ret == 0)
@@ -539,6 +455,12 @@ static int max77686_rtc_probe(struct platform_device *pdev)
                goto err_rtc;
        }
 
+       if (!max77686->rtc_irq_data) {
+               ret = -EINVAL;
+               dev_err(&pdev->dev, "%s: no RTC regmap IRQ chip\n", __func__);
+               goto err_rtc;
+       }
+
        info->virq = regmap_irq_get_virq(max77686->rtc_irq_data,
                                         MAX77686_RTCIRQ_RTCA1);
        if (!info->virq) {
@@ -556,33 +478,33 @@ err_rtc:
        return ret;
 }
 
-static void max77686_rtc_shutdown(struct platform_device *pdev)
+#ifdef CONFIG_PM_SLEEP
+static int max77686_rtc_suspend(struct device *dev)
 {
-#ifdef MAX77686_RTC_WTSR_SMPL
-       struct max77686_rtc_info *info = platform_get_drvdata(pdev);
-       int i;
-       u8 val = 0;
-
-       for (i = 0; i < 3; i++) {
-               max77686_rtc_enable_wtsr(info, false);
-               regmap_read(info->max77686->rtc_regmap, MAX77686_WTSR_SMPL_CNTL, &val);
-               dev_info(info->dev, "%s: WTSR_SMPL reg(0x%02x)\n", __func__,
-                               val);
-               if (val & WTSR_EN_MASK) {
-                       dev_emerg(info->dev, "%s: fail to disable WTSR\n",
-                                       __func__);
-               } else {
-                       dev_info(info->dev, "%s: success to disable WTSR\n",
-                                       __func__);
-                       break;
-               }
+       if (device_may_wakeup(dev)) {
+               struct max77686_rtc_info *info = dev_get_drvdata(dev);
+
+               return enable_irq_wake(info->virq);
        }
 
-       /* Disable SMPL when power off */
-       max77686_rtc_enable_smpl(info, false);
-#endif /* MAX77686_RTC_WTSR_SMPL */
+       return 0;
 }
 
+static int max77686_rtc_resume(struct device *dev)
+{
+       if (device_may_wakeup(dev)) {
+               struct max77686_rtc_info *info = dev_get_drvdata(dev);
+
+               return disable_irq_wake(info->virq);
+       }
+
+       return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(max77686_rtc_pm_ops,
+                        max77686_rtc_suspend, max77686_rtc_resume);
+
 static const struct platform_device_id rtc_id[] = {
        { "max77686-rtc", 0 },
        {},
@@ -592,9 +514,9 @@ static struct platform_driver max77686_rtc_driver = {
        .driver         = {
                .name   = "max77686-rtc",
                .owner  = THIS_MODULE,
+               .pm     = &max77686_rtc_pm_ops,
        },
        .probe          = max77686_rtc_probe,
-       .shutdown       = max77686_rtc_shutdown,
        .id_table       = rtc_id,
 };
 
diff --git a/drivers/rtc/rtc-max77802.c b/drivers/rtc/rtc-max77802.c
new file mode 100644 (file)
index 0000000..5664713
--- /dev/null
@@ -0,0 +1,502 @@
+/*
+ * RTC driver for Maxim MAX77802
+ *
+ * Copyright (C) 2013 Google, Inc
+ *
+ * Copyright (C) 2012 Samsung Electronics Co.Ltd
+ *
+ *  based on rtc-max8997.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;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/rtc.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/max77686-private.h>
+#include <linux/irqdomain.h>
+#include <linux/regmap.h>
+
+/* RTC Control Register */
+#define BCD_EN_SHIFT                   0
+#define BCD_EN_MASK                    (1 << BCD_EN_SHIFT)
+#define MODEL24_SHIFT                  1
+#define MODEL24_MASK                   (1 << MODEL24_SHIFT)
+/* RTC Update Register1 */
+#define RTC_UDR_SHIFT                  0
+#define RTC_UDR_MASK                   (1 << RTC_UDR_SHIFT)
+#define RTC_RBUDR_SHIFT                        4
+#define RTC_RBUDR_MASK                 (1 << RTC_RBUDR_SHIFT)
+/* RTC Hour register */
+#define HOUR_PM_SHIFT                  6
+#define HOUR_PM_MASK                   (1 << HOUR_PM_SHIFT)
+/* RTC Alarm Enable */
+#define ALARM_ENABLE_SHIFT             7
+#define ALARM_ENABLE_MASK              (1 << ALARM_ENABLE_SHIFT)
+
+/* For the RTCAE1 register, we write this value to enable the alarm */
+#define ALARM_ENABLE_VALUE             0x77
+
+#define MAX77802_RTC_UPDATE_DELAY_US   200
+
+enum {
+       RTC_SEC = 0,
+       RTC_MIN,
+       RTC_HOUR,
+       RTC_WEEKDAY,
+       RTC_MONTH,
+       RTC_YEAR,
+       RTC_DATE,
+       RTC_NR_TIME
+};
+
+struct max77802_rtc_info {
+       struct device           *dev;
+       struct max77686_dev     *max77802;
+       struct i2c_client       *rtc;
+       struct rtc_device       *rtc_dev;
+       struct mutex            lock;
+
+       struct regmap           *regmap;
+
+       int virq;
+       int rtc_24hr_mode;
+};
+
+enum MAX77802_RTC_OP {
+       MAX77802_RTC_WRITE,
+       MAX77802_RTC_READ,
+};
+
+static void max77802_rtc_data_to_tm(u8 *data, struct rtc_time *tm,
+                                  int rtc_24hr_mode)
+{
+       tm->tm_sec = data[RTC_SEC] & 0xff;
+       tm->tm_min = data[RTC_MIN] & 0xff;
+       if (rtc_24hr_mode)
+               tm->tm_hour = data[RTC_HOUR] & 0x1f;
+       else {
+               tm->tm_hour = data[RTC_HOUR] & 0x0f;
+               if (data[RTC_HOUR] & HOUR_PM_MASK)
+                       tm->tm_hour += 12;
+       }
+
+       /* Only a single bit is set in data[], so fls() would be equivalent */
+       tm->tm_wday = ffs(data[RTC_WEEKDAY] & 0xff) - 1;
+       tm->tm_mday = data[RTC_DATE] & 0x1f;
+       tm->tm_mon = (data[RTC_MONTH] & 0x0f) - 1;
+
+       tm->tm_year = data[RTC_YEAR] & 0xff;
+       tm->tm_yday = 0;
+       tm->tm_isdst = 0;
+}
+
+static int max77802_rtc_tm_to_data(struct rtc_time *tm, u8 *data)
+{
+       data[RTC_SEC] = tm->tm_sec;
+       data[RTC_MIN] = tm->tm_min;
+       data[RTC_HOUR] = tm->tm_hour;
+       data[RTC_WEEKDAY] = 1 << tm->tm_wday;
+       data[RTC_DATE] = tm->tm_mday;
+       data[RTC_MONTH] = tm->tm_mon + 1;
+       data[RTC_YEAR] = tm->tm_year;
+
+       return 0;
+}
+
+static int max77802_rtc_update(struct max77802_rtc_info *info,
+       enum MAX77802_RTC_OP op)
+{
+       int ret;
+       unsigned int data;
+
+       if (op == MAX77802_RTC_WRITE)
+               data = 1 << RTC_UDR_SHIFT;
+       else
+               data = 1 << RTC_RBUDR_SHIFT;
+
+       ret = regmap_update_bits(info->max77802->regmap,
+                                MAX77802_RTC_UPDATE0, data, data);
+       if (ret < 0)
+               dev_err(info->dev, "%s: fail to write update reg(ret=%d, data=0x%x)\n",
+                               __func__, ret, data);
+       else {
+               /* Minimum delay required before RTC update. */
+               usleep_range(MAX77802_RTC_UPDATE_DELAY_US,
+                            MAX77802_RTC_UPDATE_DELAY_US * 2);
+       }
+
+       return ret;
+}
+
+static int max77802_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+       struct max77802_rtc_info *info = dev_get_drvdata(dev);
+       u8 data[RTC_NR_TIME];
+       int ret;
+
+       mutex_lock(&info->lock);
+
+       ret = max77802_rtc_update(info, MAX77802_RTC_READ);
+       if (ret < 0)
+               goto out;
+
+       ret = regmap_bulk_read(info->max77802->regmap,
+                               MAX77802_RTC_SEC, data, RTC_NR_TIME);
+       if (ret < 0) {
+               dev_err(info->dev, "%s: fail to read time reg(%d)\n", __func__,
+                       ret);
+               goto out;
+       }
+
+       max77802_rtc_data_to_tm(data, tm, info->rtc_24hr_mode);
+
+       ret = rtc_valid_tm(tm);
+
+out:
+       mutex_unlock(&info->lock);
+       return ret;
+}
+
+static int max77802_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+       struct max77802_rtc_info *info = dev_get_drvdata(dev);
+       u8 data[RTC_NR_TIME];
+       int ret;
+
+       ret = max77802_rtc_tm_to_data(tm, data);
+       if (ret < 0)
+               return ret;
+
+       mutex_lock(&info->lock);
+
+       ret = regmap_bulk_write(info->max77802->regmap,
+                                MAX77802_RTC_SEC, data, RTC_NR_TIME);
+       if (ret < 0) {
+               dev_err(info->dev, "%s: fail to write time reg(%d)\n", __func__,
+                       ret);
+               goto out;
+       }
+
+       ret = max77802_rtc_update(info, MAX77802_RTC_WRITE);
+
+out:
+       mutex_unlock(&info->lock);
+       return ret;
+}
+
+static int max77802_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+       struct max77802_rtc_info *info = dev_get_drvdata(dev);
+       u8 data[RTC_NR_TIME];
+       unsigned int val;
+       int ret;
+
+       mutex_lock(&info->lock);
+
+       ret = max77802_rtc_update(info, MAX77802_RTC_READ);
+       if (ret < 0)
+               goto out;
+
+       ret = regmap_bulk_read(info->max77802->regmap,
+                                MAX77802_ALARM1_SEC, data, RTC_NR_TIME);
+       if (ret < 0) {
+               dev_err(info->dev, "%s:%d fail to read alarm reg(%d)\n",
+                               __func__, __LINE__, ret);
+               goto out;
+       }
+
+       max77802_rtc_data_to_tm(data, &alrm->time, info->rtc_24hr_mode);
+
+       alrm->enabled = 0;
+       ret = regmap_read(info->max77802->regmap,
+                         MAX77802_RTC_AE1, &val);
+       if (ret < 0) {
+               dev_err(info->dev, "%s:%d fail to read alarm enable(%d)\n",
+                       __func__, __LINE__, ret);
+               goto out;
+       }
+       if (val)
+               alrm->enabled = 1;
+
+       alrm->pending = 0;
+       ret = regmap_read(info->max77802->regmap, MAX77802_REG_STATUS2, &val);
+       if (ret < 0) {
+               dev_err(info->dev, "%s:%d fail to read status2 reg(%d)\n",
+                               __func__, __LINE__, ret);
+               goto out;
+       }
+
+       if (val & (1 << 2)) /* RTCA1 */
+               alrm->pending = 1;
+
+out:
+       mutex_unlock(&info->lock);
+       return 0;
+}
+
+static int max77802_rtc_stop_alarm(struct max77802_rtc_info *info)
+{
+       int ret;
+
+       if (!mutex_is_locked(&info->lock))
+               dev_warn(info->dev, "%s: should have mutex locked\n", __func__);
+
+       ret = max77802_rtc_update(info, MAX77802_RTC_READ);
+       if (ret < 0)
+               goto out;
+
+       ret = regmap_write(info->max77802->regmap,
+                          MAX77802_RTC_AE1, 0);
+       if (ret < 0) {
+               dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
+                       __func__, ret);
+               goto out;
+       }
+
+       ret = max77802_rtc_update(info, MAX77802_RTC_WRITE);
+out:
+       return ret;
+}
+
+static int max77802_rtc_start_alarm(struct max77802_rtc_info *info)
+{
+       int ret;
+
+       if (!mutex_is_locked(&info->lock))
+               dev_warn(info->dev, "%s: should have mutex locked\n",
+                        __func__);
+
+       ret = max77802_rtc_update(info, MAX77802_RTC_READ);
+       if (ret < 0)
+               goto out;
+
+       ret = regmap_write(info->max77802->regmap,
+                                  MAX77802_RTC_AE1,
+                                  ALARM_ENABLE_VALUE);
+
+       if (ret < 0) {
+               dev_err(info->dev, "%s: fail to read alarm reg(%d)\n",
+                               __func__, ret);
+               goto out;
+       }
+
+       ret = max77802_rtc_update(info, MAX77802_RTC_WRITE);
+out:
+       return ret;
+}
+
+static int max77802_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+       struct max77802_rtc_info *info = dev_get_drvdata(dev);
+       u8 data[RTC_NR_TIME];
+       int ret;
+
+       ret = max77802_rtc_tm_to_data(&alrm->time, data);
+       if (ret < 0)
+               return ret;
+
+       mutex_lock(&info->lock);
+
+       ret = max77802_rtc_stop_alarm(info);
+       if (ret < 0)
+               goto out;
+
+       ret = regmap_bulk_write(info->max77802->regmap,
+                                MAX77802_ALARM1_SEC, data, RTC_NR_TIME);
+
+       if (ret < 0) {
+               dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
+                               __func__, ret);
+               goto out;
+       }
+
+       ret = max77802_rtc_update(info, MAX77802_RTC_WRITE);
+       if (ret < 0)
+               goto out;
+
+       if (alrm->enabled)
+               ret = max77802_rtc_start_alarm(info);
+out:
+       mutex_unlock(&info->lock);
+       return ret;
+}
+
+static int max77802_rtc_alarm_irq_enable(struct device *dev,
+                                        unsigned int enabled)
+{
+       struct max77802_rtc_info *info = dev_get_drvdata(dev);
+       int ret;
+
+       mutex_lock(&info->lock);
+       if (enabled)
+               ret = max77802_rtc_start_alarm(info);
+       else
+               ret = max77802_rtc_stop_alarm(info);
+       mutex_unlock(&info->lock);
+
+       return ret;
+}
+
+static irqreturn_t max77802_rtc_alarm_irq(int irq, void *data)
+{
+       struct max77802_rtc_info *info = data;
+
+       dev_dbg(info->dev, "%s:irq(%d)\n", __func__, irq);
+
+       rtc_update_irq(info->rtc_dev, 1, RTC_IRQF | RTC_AF);
+
+       return IRQ_HANDLED;
+}
+
+static const struct rtc_class_ops max77802_rtc_ops = {
+       .read_time = max77802_rtc_read_time,
+       .set_time = max77802_rtc_set_time,
+       .read_alarm = max77802_rtc_read_alarm,
+       .set_alarm = max77802_rtc_set_alarm,
+       .alarm_irq_enable = max77802_rtc_alarm_irq_enable,
+};
+
+static int max77802_rtc_init_reg(struct max77802_rtc_info *info)
+{
+       u8 data[2];
+       int ret;
+
+       max77802_rtc_update(info, MAX77802_RTC_READ);
+
+       /* Set RTC control register : Binary mode, 24hour mdoe */
+       data[0] = (1 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT);
+       data[1] = (0 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT);
+
+       info->rtc_24hr_mode = 1;
+
+       ret = regmap_bulk_write(info->max77802->regmap,
+                               MAX77802_RTC_CONTROLM, data, ARRAY_SIZE(data));
+       if (ret < 0) {
+               dev_err(info->dev, "%s: fail to write controlm reg(%d)\n",
+                               __func__, ret);
+               return ret;
+       }
+
+       ret = max77802_rtc_update(info, MAX77802_RTC_WRITE);
+       return ret;
+}
+
+static int max77802_rtc_probe(struct platform_device *pdev)
+{
+       struct max77686_dev *max77802 = dev_get_drvdata(pdev->dev.parent);
+       struct max77802_rtc_info *info;
+       int ret;
+
+       dev_dbg(&pdev->dev, "%s\n", __func__);
+
+       info = devm_kzalloc(&pdev->dev, sizeof(struct max77802_rtc_info),
+                           GFP_KERNEL);
+       if (!info)
+               return -ENOMEM;
+
+       mutex_init(&info->lock);
+       info->dev = &pdev->dev;
+       info->max77802 = max77802;
+       info->rtc = max77802->i2c;
+
+       platform_set_drvdata(pdev, info);
+
+       ret = max77802_rtc_init_reg(info);
+
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Failed to initialize RTC reg:%d\n", ret);
+               return ret;
+       }
+
+       device_init_wakeup(&pdev->dev, 1);
+
+       info->rtc_dev = devm_rtc_device_register(&pdev->dev, "max77802-rtc",
+                                                &max77802_rtc_ops, THIS_MODULE);
+
+       if (IS_ERR(info->rtc_dev)) {
+               ret = PTR_ERR(info->rtc_dev);
+               dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret);
+               if (ret == 0)
+                       ret = -EINVAL;
+               return ret;
+       }
+
+       if (!max77802->rtc_irq_data) {
+               dev_err(&pdev->dev, "No RTC regmap IRQ chip\n");
+               return -EINVAL;
+       }
+
+       info->virq = regmap_irq_get_virq(max77802->rtc_irq_data,
+                                        MAX77686_RTCIRQ_RTCA1);
+
+       if (info->virq <= 0) {
+               dev_err(&pdev->dev, "Failed to get virtual IRQ %d\n",
+                       MAX77686_RTCIRQ_RTCA1);
+               return -EINVAL;
+       }
+
+       ret = devm_request_threaded_irq(&pdev->dev, info->virq, NULL,
+                                       max77802_rtc_alarm_irq, 0, "rtc-alarm1",
+                                       info);
+       if (ret < 0)
+               dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n",
+                       info->virq, ret);
+
+       return ret;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int max77802_rtc_suspend(struct device *dev)
+{
+       if (device_may_wakeup(dev)) {
+               struct max77802_rtc_info *info = dev_get_drvdata(dev);
+
+               return enable_irq_wake(info->virq);
+       }
+
+       return 0;
+}
+
+static int max77802_rtc_resume(struct device *dev)
+{
+       if (device_may_wakeup(dev)) {
+               struct max77802_rtc_info *info = dev_get_drvdata(dev);
+
+               return disable_irq_wake(info->virq);
+       }
+
+       return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(max77802_rtc_pm_ops,
+                        max77802_rtc_suspend, max77802_rtc_resume);
+
+static const struct platform_device_id rtc_id[] = {
+       { "max77802-rtc", 0 },
+       {},
+};
+
+static struct platform_driver max77802_rtc_driver = {
+       .driver         = {
+               .name   = "max77802-rtc",
+               .owner  = THIS_MODULE,
+               .pm     = &max77802_rtc_pm_ops,
+       },
+       .probe          = max77802_rtc_probe,
+       .id_table       = rtc_id,
+};
+
+module_platform_driver(max77802_rtc_driver);
+
+MODULE_DESCRIPTION("Maxim MAX77802 RTC driver");
+MODULE_AUTHOR("Simon Glass <sjg@chromium.org>");
+MODULE_LICENSE("GPL");
index dc4f14255cc36c755ca90658cdad4c501fda4f71..3b965ad6f4d5ad959f84c920e52767443cb899d4 100644 (file)
@@ -401,7 +401,7 @@ static int mpc5121_rtc_remove(struct platform_device *op)
 }
 
 #ifdef CONFIG_OF
-static struct of_device_id mpc5121_rtc_match[] = {
+static const struct of_device_id mpc5121_rtc_match[] = {
        { .compatible = "fsl,mpc5121-rtc", },
        { .compatible = "fsl,mpc5200-rtc", },
        {},
index 5a197d9dc7e727b881740b5715e80aa31155ce7e..c2ef0a22ee94639a0db6d3f1e0334d26947059cb 100644 (file)
@@ -167,8 +167,8 @@ static irqreturn_t pcf8563_irq(int irq, void *dev_id)
        char pending;
 
        err = pcf8563_get_alarm_mode(pcf8563->client, NULL, &pending);
-       if (err < 0)
-               return err;
+       if (err)
+               return IRQ_NONE;
 
        if (pending) {
                rtc_update_irq(pcf8563->rtc, 1, RTC_IRQF | RTC_AF);
index c2639845186b3f8433551116074ae19197ee1866..5911a6dca29199d976fd71b72e818eda1480431c 100644 (file)
@@ -176,7 +176,11 @@ static int pcf8583_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
        struct i2c_client *client = to_i2c_client(dev);
        unsigned char ctrl, year[2];
-       struct rtc_mem mem = { CMOS_YEAR, sizeof(year), year };
+       struct rtc_mem mem = {
+               .loc = CMOS_YEAR,
+               .nr = sizeof(year),
+               .data = year
+       };
        int real_year, year_offset, err;
 
        /*
@@ -222,8 +226,16 @@ static int pcf8583_rtc_set_time(struct device *dev, struct rtc_time *tm)
 {
        struct i2c_client *client = to_i2c_client(dev);
        unsigned char year[2], chk;
-       struct rtc_mem cmos_year  = { CMOS_YEAR, sizeof(year), year };
-       struct rtc_mem cmos_check = { CMOS_CHECKSUM, 1, &chk };
+       struct rtc_mem cmos_year  = {
+               .loc = CMOS_YEAR,
+               .nr = sizeof(year),
+               .data = year
+       };
+       struct rtc_mem cmos_check = {
+               .loc = CMOS_CHECKSUM,
+               .nr = 1,
+               .data = &chk
+       };
        unsigned int proper_year = tm->tm_year + 1900;
        int ret;
 
diff --git a/drivers/rtc/rtc-rk808.c b/drivers/rtc/rtc-rk808.c
new file mode 100644 (file)
index 0000000..df42257
--- /dev/null
@@ -0,0 +1,414 @@
+/*
+ * RTC driver for Rockchip RK808
+ *
+ * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
+ *
+ * Author: Chris Zhong <zyw@rock-chips.com>
+ * Author: Zhang Qing <zhangqing@rock-chips.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+#include <linux/mfd/rk808.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+
+/* RTC_CTRL_REG bitfields */
+#define BIT_RTC_CTRL_REG_STOP_RTC_M            BIT(0)
+
+/* RK808 has a shadowed register for saving a "frozen" RTC time.
+ * When user setting "GET_TIME" to 1, the time will save in this shadowed
+ * register. If set "READSEL" to 1, user read rtc time register, actually
+ * get the time of that moment. If we need the real time, clr this bit.
+ */
+#define BIT_RTC_CTRL_REG_RTC_GET_TIME          BIT(6)
+#define BIT_RTC_CTRL_REG_RTC_READSEL_M         BIT(7)
+#define BIT_RTC_INTERRUPTS_REG_IT_ALARM_M      BIT(3)
+#define RTC_STATUS_MASK                0xFE
+
+#define SECONDS_REG_MSK                0x7F
+#define MINUTES_REG_MAK                0x7F
+#define HOURS_REG_MSK          0x3F
+#define DAYS_REG_MSK           0x3F
+#define MONTHS_REG_MSK         0x1F
+#define YEARS_REG_MSK          0xFF
+#define WEEKS_REG_MSK          0x7
+
+/* REG_SECONDS_REG through REG_YEARS_REG is how many registers? */
+
+#define NUM_TIME_REGS  (RK808_WEEKS_REG - RK808_SECONDS_REG + 1)
+#define NUM_ALARM_REGS (RK808_ALARM_YEARS_REG - RK808_ALARM_SECONDS_REG + 1)
+
+struct rk808_rtc {
+       struct rk808 *rk808;
+       struct rtc_device *rtc;
+       int irq;
+};
+
+/* Read current time and date in RTC */
+static int rk808_rtc_readtime(struct device *dev, struct rtc_time *tm)
+{
+       struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev);
+       struct rk808 *rk808 = rk808_rtc->rk808;
+       u8 rtc_data[NUM_TIME_REGS];
+       int ret;
+
+       /* Force an update of the shadowed registers right now */
+       ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG,
+                                BIT_RTC_CTRL_REG_RTC_GET_TIME,
+                                0);
+       if (ret) {
+               dev_err(dev, "Failed to update bits rtc_ctrl: %d\n", ret);
+               return ret;
+       }
+
+       ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG,
+                                BIT_RTC_CTRL_REG_RTC_GET_TIME,
+                                BIT_RTC_CTRL_REG_RTC_GET_TIME);
+       if (ret) {
+               dev_err(dev, "Failed to update bits rtc_ctrl: %d\n", ret);
+               return ret;
+       }
+
+       ret = regmap_bulk_read(rk808->regmap, RK808_SECONDS_REG,
+                              rtc_data, NUM_TIME_REGS);
+       if (ret) {
+               dev_err(dev, "Failed to bulk read rtc_data: %d\n", ret);
+               return ret;
+       }
+
+       tm->tm_sec = bcd2bin(rtc_data[0] & SECONDS_REG_MSK);
+       tm->tm_min = bcd2bin(rtc_data[1] & MINUTES_REG_MAK);
+       tm->tm_hour = bcd2bin(rtc_data[2] & HOURS_REG_MSK);
+       tm->tm_mday = bcd2bin(rtc_data[3] & DAYS_REG_MSK);
+       tm->tm_mon = (bcd2bin(rtc_data[4] & MONTHS_REG_MSK)) - 1;
+       tm->tm_year = (bcd2bin(rtc_data[5] & YEARS_REG_MSK)) + 100;
+       tm->tm_wday = bcd2bin(rtc_data[6] & WEEKS_REG_MSK);
+       dev_dbg(dev, "RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n",
+               1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday,
+               tm->tm_wday, tm->tm_hour , tm->tm_min, tm->tm_sec);
+
+       return ret;
+}
+
+/* Set current time and date in RTC */
+static int rk808_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+       struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev);
+       struct rk808 *rk808 = rk808_rtc->rk808;
+       u8 rtc_data[NUM_TIME_REGS];
+       int ret;
+
+       rtc_data[0] = bin2bcd(tm->tm_sec);
+       rtc_data[1] = bin2bcd(tm->tm_min);
+       rtc_data[2] = bin2bcd(tm->tm_hour);
+       rtc_data[3] = bin2bcd(tm->tm_mday);
+       rtc_data[4] = bin2bcd(tm->tm_mon + 1);
+       rtc_data[5] = bin2bcd(tm->tm_year - 100);
+       rtc_data[6] = bin2bcd(tm->tm_wday);
+       dev_dbg(dev, "set RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n",
+               1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday,
+               tm->tm_wday, tm->tm_hour , tm->tm_min, tm->tm_sec);
+
+       /* Stop RTC while updating the RTC registers */
+       ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG,
+                                BIT_RTC_CTRL_REG_STOP_RTC_M,
+                                BIT_RTC_CTRL_REG_STOP_RTC_M);
+       if (ret) {
+               dev_err(dev, "Failed to update RTC control: %d\n", ret);
+               return ret;
+       }
+
+       ret = regmap_bulk_write(rk808->regmap, RK808_SECONDS_REG,
+                               rtc_data, NUM_TIME_REGS);
+       if (ret) {
+               dev_err(dev, "Failed to bull write rtc_data: %d\n", ret);
+               return ret;
+       }
+       /* Start RTC again */
+       ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG,
+                                BIT_RTC_CTRL_REG_STOP_RTC_M, 0);
+       if (ret) {
+               dev_err(dev, "Failed to update RTC control: %d\n", ret);
+               return ret;
+       }
+       return 0;
+}
+
+/* Read alarm time and date in RTC */
+static int rk808_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+       struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev);
+       struct rk808 *rk808 = rk808_rtc->rk808;
+       u8 alrm_data[NUM_ALARM_REGS];
+       uint32_t int_reg;
+       int ret;
+
+       ret = regmap_bulk_read(rk808->regmap, RK808_ALARM_SECONDS_REG,
+                              alrm_data, NUM_ALARM_REGS);
+
+       alrm->time.tm_sec = bcd2bin(alrm_data[0] & SECONDS_REG_MSK);
+       alrm->time.tm_min = bcd2bin(alrm_data[1] & MINUTES_REG_MAK);
+       alrm->time.tm_hour = bcd2bin(alrm_data[2] & HOURS_REG_MSK);
+       alrm->time.tm_mday = bcd2bin(alrm_data[3] & DAYS_REG_MSK);
+       alrm->time.tm_mon = (bcd2bin(alrm_data[4] & MONTHS_REG_MSK)) - 1;
+       alrm->time.tm_year = (bcd2bin(alrm_data[5] & YEARS_REG_MSK)) + 100;
+
+       ret = regmap_read(rk808->regmap, RK808_RTC_INT_REG, &int_reg);
+       if (ret) {
+               dev_err(dev, "Failed to read RTC INT REG: %d\n", ret);
+               return ret;
+       }
+
+       dev_dbg(dev, "alrm read RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n",
+               1900 + alrm->time.tm_year, alrm->time.tm_mon + 1,
+               alrm->time.tm_mday, alrm->time.tm_wday, alrm->time.tm_hour,
+               alrm->time.tm_min, alrm->time.tm_sec);
+
+       alrm->enabled = (int_reg & BIT_RTC_INTERRUPTS_REG_IT_ALARM_M) ? 1 : 0;
+
+       return 0;
+}
+
+static int rk808_rtc_stop_alarm(struct rk808_rtc *rk808_rtc)
+{
+       struct rk808 *rk808 = rk808_rtc->rk808;
+       int ret;
+
+       ret = regmap_update_bits(rk808->regmap, RK808_RTC_INT_REG,
+                                BIT_RTC_INTERRUPTS_REG_IT_ALARM_M, 0);
+
+       return ret;
+}
+
+static int rk808_rtc_start_alarm(struct rk808_rtc *rk808_rtc)
+{
+       struct rk808 *rk808 = rk808_rtc->rk808;
+       int ret;
+
+       ret = regmap_update_bits(rk808->regmap, RK808_RTC_INT_REG,
+                                BIT_RTC_INTERRUPTS_REG_IT_ALARM_M,
+                                BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
+
+       return ret;
+}
+
+static int rk808_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+       struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev);
+       struct rk808 *rk808 = rk808_rtc->rk808;
+       u8 alrm_data[NUM_ALARM_REGS];
+       int ret;
+
+       ret = rk808_rtc_stop_alarm(rk808_rtc);
+       if (ret) {
+               dev_err(dev, "Failed to stop alarm: %d\n", ret);
+               return ret;
+       }
+       dev_dbg(dev, "alrm set RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n",
+               1900 + alrm->time.tm_year, alrm->time.tm_mon + 1,
+               alrm->time.tm_mday, alrm->time.tm_wday, alrm->time.tm_hour,
+               alrm->time.tm_min, alrm->time.tm_sec);
+
+       alrm_data[0] = bin2bcd(alrm->time.tm_sec);
+       alrm_data[1] = bin2bcd(alrm->time.tm_min);
+       alrm_data[2] = bin2bcd(alrm->time.tm_hour);
+       alrm_data[3] = bin2bcd(alrm->time.tm_mday);
+       alrm_data[4] = bin2bcd(alrm->time.tm_mon + 1);
+       alrm_data[5] = bin2bcd(alrm->time.tm_year - 100);
+
+       ret = regmap_bulk_write(rk808->regmap, RK808_ALARM_SECONDS_REG,
+                               alrm_data, NUM_ALARM_REGS);
+       if (ret) {
+               dev_err(dev, "Failed to bulk write: %d\n", ret);
+               return ret;
+       }
+       if (alrm->enabled) {
+               ret = rk808_rtc_start_alarm(rk808_rtc);
+               if (ret) {
+                       dev_err(dev, "Failed to start alarm: %d\n", ret);
+                       return ret;
+               }
+       }
+       return 0;
+}
+
+static int rk808_rtc_alarm_irq_enable(struct device *dev,
+                                     unsigned int enabled)
+{
+       struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev);
+
+       if (enabled)
+               return rk808_rtc_start_alarm(rk808_rtc);
+
+       return rk808_rtc_stop_alarm(rk808_rtc);
+}
+
+/*
+ * We will just handle setting the frequency and make use the framework for
+ * reading the periodic interupts.
+ *
+ * @freq: Current periodic IRQ freq:
+ * bit 0: every second
+ * bit 1: every minute
+ * bit 2: every hour
+ * bit 3: every day
+ */
+static irqreturn_t rk808_alarm_irq(int irq, void *data)
+{
+       struct rk808_rtc *rk808_rtc = data;
+       struct rk808 *rk808 = rk808_rtc->rk808;
+       struct i2c_client *client = rk808->i2c;
+       int ret;
+
+       ret = regmap_write(rk808->regmap, RK808_RTC_STATUS_REG,
+                          RTC_STATUS_MASK);
+       if (ret) {
+               dev_err(&client->dev,
+                       "%s:Failed to update RTC status: %d\n", __func__, ret);
+               return ret;
+       }
+
+       rtc_update_irq(rk808_rtc->rtc, 1, RTC_IRQF | RTC_AF);
+       dev_dbg(&client->dev,
+                "%s:irq=%d\n", __func__, irq);
+       return IRQ_HANDLED;
+}
+
+static const struct rtc_class_ops rk808_rtc_ops = {
+       .read_time = rk808_rtc_readtime,
+       .set_time = rk808_rtc_set_time,
+       .read_alarm = rk808_rtc_readalarm,
+       .set_alarm = rk808_rtc_setalarm,
+       .alarm_irq_enable = rk808_rtc_alarm_irq_enable,
+};
+
+#ifdef CONFIG_PM_SLEEP
+/* Turn off the alarm if it should not be a wake source. */
+static int rk808_rtc_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct rk808_rtc *rk808_rtc = dev_get_drvdata(&pdev->dev);
+
+       if (device_may_wakeup(dev))
+               enable_irq_wake(rk808_rtc->irq);
+
+       return 0;
+}
+
+/* Enable the alarm if it should be enabled (in case it was disabled to
+ * prevent use as a wake source).
+ */
+static int rk808_rtc_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct rk808_rtc *rk808_rtc = dev_get_drvdata(&pdev->dev);
+
+       if (device_may_wakeup(dev))
+               disable_irq_wake(rk808_rtc->irq);
+
+       return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(rk808_rtc_pm_ops,
+       rk808_rtc_suspend, rk808_rtc_resume);
+
+static int rk808_rtc_probe(struct platform_device *pdev)
+{
+       struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent);
+       struct rk808_rtc *rk808_rtc;
+       struct rtc_time tm;
+       int ret;
+
+       rk808_rtc = devm_kzalloc(&pdev->dev, sizeof(*rk808_rtc), GFP_KERNEL);
+       if (rk808_rtc == NULL)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, rk808_rtc);
+       rk808_rtc->rk808 = rk808;
+
+       /* start rtc running by default, and use shadowed timer. */
+       ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG,
+                                BIT_RTC_CTRL_REG_STOP_RTC_M |
+                                BIT_RTC_CTRL_REG_RTC_READSEL_M,
+                                BIT_RTC_CTRL_REG_RTC_READSEL_M);
+       if (ret) {
+               dev_err(&pdev->dev,
+                       "Failed to update RTC control: %d\n", ret);
+               return ret;
+       }
+
+       ret = regmap_write(rk808->regmap, RK808_RTC_STATUS_REG,
+                          RTC_STATUS_MASK);
+       if (ret) {
+               dev_err(&pdev->dev,
+                       "Failed to write RTC status: %d\n", ret);
+                       return ret;
+       }
+
+       /* set init time */
+       ret = rk808_rtc_readtime(&pdev->dev, &tm);
+       if (ret) {
+               dev_err(&pdev->dev, "Failed to read RTC time\n");
+               return ret;
+       }
+       ret = rtc_valid_tm(&tm);
+       if (ret)
+               dev_warn(&pdev->dev, "invalid date/time\n");
+
+       device_init_wakeup(&pdev->dev, 1);
+
+       rk808_rtc->rtc = devm_rtc_device_register(&pdev->dev, "rk808-rtc",
+                                                 &rk808_rtc_ops, THIS_MODULE);
+       if (IS_ERR(rk808_rtc->rtc)) {
+               ret = PTR_ERR(rk808_rtc->rtc);
+               return ret;
+       }
+
+       rk808_rtc->irq = platform_get_irq(pdev, 0);
+       if (rk808_rtc->irq < 0) {
+               if (rk808_rtc->irq != -EPROBE_DEFER)
+                       dev_err(&pdev->dev, "Wake up is not possible as irq = %d\n",
+                               rk808_rtc->irq);
+               return rk808_rtc->irq;
+       }
+
+       /* request alarm irq of rk808 */
+       ret = devm_request_threaded_irq(&pdev->dev, rk808_rtc->irq, NULL,
+                                       rk808_alarm_irq, 0,
+                                       "RTC alarm", rk808_rtc);
+       if (ret) {
+               dev_err(&pdev->dev, "Failed to request alarm IRQ %d: %d\n",
+                       rk808_rtc->irq, ret);
+       }
+
+       return ret;
+}
+
+static struct platform_driver rk808_rtc_driver = {
+       .probe = rk808_rtc_probe,
+       .driver = {
+               .name = "rk808-rtc",
+               .pm = &rk808_rtc_pm_ops,
+       },
+};
+
+module_platform_driver(rk808_rtc_driver);
+
+MODULE_DESCRIPTION("RTC driver for the rk808 series PMICs");
+MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
+MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:rk808-rtc");
index ccf54f06396bf251bf42be6007c40db21b84a5c6..28871cd7e3b592681d0839b2830b710e4bce0d60 100644 (file)
@@ -142,12 +142,11 @@ static int rs5c_get_regs(struct rs5c372 *rs5c)
        }
 
        dev_dbg(&client->dev,
-               "%02x %02x %02x (%02x) %02x %02x %02x (%02x), "
-               "%02x %02x %02x, %02x %02x %02x; %02x %02x\n",
-               rs5c->regs[0],  rs5c->regs[1],  rs5c->regs[2],  rs5c->regs[3],
-               rs5c->regs[4],  rs5c->regs[5],  rs5c->regs[6],  rs5c->regs[7],
-               rs5c->regs[8],  rs5c->regs[9],  rs5c->regs[10], rs5c->regs[11],
-               rs5c->regs[12], rs5c->regs[13], rs5c->regs[14], rs5c->regs[15]);
+               "%3ph (%02x) %3ph (%02x), %3ph, %3ph; %02x %02x\n",
+               rs5c->regs + 0, rs5c->regs[3],
+               rs5c->regs + 4, rs5c->regs[7],
+               rs5c->regs + 8, rs5c->regs + 11,
+               rs5c->regs[14], rs5c->regs[15]);
 
        return 0;
 }
index 4958a363b2c76a29b38c476177bca94fe378ca01..a6b1252c9941884a93dac49ed4c10c828ad0964d 100644 (file)
 #include <asm/irq.h>
 #include "rtc-s3c.h"
 
-enum s3c_cpu_type {
-       TYPE_S3C2410,
-       TYPE_S3C2416,
-       TYPE_S3C2443,
-       TYPE_S3C64XX,
-};
+struct s3c_rtc {
+       struct device *dev;
+       struct rtc_device *rtc;
 
-struct s3c_rtc_drv_data {
-       int cpu_type;
-};
+       void __iomem *base;
+       struct clk *rtc_clk;
+       struct clk *rtc_src_clk;
+       bool enabled;
+
+       struct s3c_rtc_data *data;
 
-/* I have yet to find an S3C implementation with more than one
- * of these rtc blocks in */
+       int irq_alarm;
+       int irq_tick;
 
-static struct clk *rtc_clk;
-static void __iomem *s3c_rtc_base;
-static int s3c_rtc_alarmno;
-static int s3c_rtc_tickno;
-static enum s3c_cpu_type s3c_rtc_cpu_type;
+       spinlock_t pie_lock;
+       spinlock_t alarm_clk_lock;
 
-static DEFINE_SPINLOCK(s3c_rtc_pie_lock);
+       int ticnt_save, ticnt_en_save;
+       bool wake_en;
+};
+
+struct s3c_rtc_data {
+       int max_user_freq;
+       bool needs_src_clk;
+
+       void (*irq_handler) (struct s3c_rtc *info, int mask);
+       void (*set_freq) (struct s3c_rtc *info, int freq);
+       void (*enable_tick) (struct s3c_rtc *info, struct seq_file *seq);
+       void (*select_tick_clk) (struct s3c_rtc *info);
+       void (*save_tick_cnt) (struct s3c_rtc *info);
+       void (*restore_tick_cnt) (struct s3c_rtc *info);
+       void (*enable) (struct s3c_rtc *info);
+       void (*disable) (struct s3c_rtc *info);
+};
 
-static void s3c_rtc_alarm_clk_enable(bool enable)
+static void s3c_rtc_alarm_clk_enable(struct s3c_rtc *info, bool enable)
 {
-       static DEFINE_SPINLOCK(s3c_rtc_alarm_clk_lock);
-       static bool alarm_clk_enabled;
        unsigned long irq_flags;
 
-       spin_lock_irqsave(&s3c_rtc_alarm_clk_lock, irq_flags);
+       spin_lock_irqsave(&info->alarm_clk_lock, irq_flags);
        if (enable) {
-               if (!alarm_clk_enabled) {
-                       clk_enable(rtc_clk);
-                       alarm_clk_enabled = true;
+               if (!info->enabled) {
+                       clk_enable(info->rtc_clk);
+                       if (info->data->needs_src_clk)
+                               clk_enable(info->rtc_src_clk);
+                       info->enabled = true;
                }
        } else {
-               if (alarm_clk_enabled) {
-                       clk_disable(rtc_clk);
-                       alarm_clk_enabled = false;
+               if (info->enabled) {
+                       if (info->data->needs_src_clk)
+                               clk_disable(info->rtc_src_clk);
+                       clk_disable(info->rtc_clk);
+                       info->enabled = false;
                }
        }
-       spin_unlock_irqrestore(&s3c_rtc_alarm_clk_lock, irq_flags);
+       spin_unlock_irqrestore(&info->alarm_clk_lock, irq_flags);
 }
 
 /* IRQ Handlers */
-
-static irqreturn_t s3c_rtc_alarmirq(int irq, void *id)
+static irqreturn_t s3c_rtc_tickirq(int irq, void *id)
 {
-       struct rtc_device *rdev = id;
-
-       clk_enable(rtc_clk);
-       rtc_update_irq(rdev, 1, RTC_AF | RTC_IRQF);
-
-       if (s3c_rtc_cpu_type == TYPE_S3C64XX)
-               writeb(S3C2410_INTP_ALM, s3c_rtc_base + S3C2410_INTP);
-
-       clk_disable(rtc_clk);
+       struct s3c_rtc *info = (struct s3c_rtc *)id;
 
-       s3c_rtc_alarm_clk_enable(false);
+       if (info->data->irq_handler)
+               info->data->irq_handler(info, S3C2410_INTP_TIC);
 
        return IRQ_HANDLED;
 }
 
-static irqreturn_t s3c_rtc_tickirq(int irq, void *id)
+static irqreturn_t s3c_rtc_alarmirq(int irq, void *id)
 {
-       struct rtc_device *rdev = id;
+       struct s3c_rtc *info = (struct s3c_rtc *)id;
 
-       clk_enable(rtc_clk);
-       rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF);
+       if (info->data->irq_handler)
+               info->data->irq_handler(info, S3C2410_INTP_ALM);
 
-       if (s3c_rtc_cpu_type == TYPE_S3C64XX)
-               writeb(S3C2410_INTP_TIC, s3c_rtc_base + S3C2410_INTP);
-
-       clk_disable(rtc_clk);
        return IRQ_HANDLED;
 }
 
 /* Update control registers */
 static int s3c_rtc_setaie(struct device *dev, unsigned int enabled)
 {
+       struct s3c_rtc *info = dev_get_drvdata(dev);
        unsigned int tmp;
 
-       dev_dbg(dev, "%s: aie=%d\n", __func__, enabled);
+       dev_dbg(info->dev, "%s: aie=%d\n", __func__, enabled);
 
-       clk_enable(rtc_clk);
-       tmp = readb(s3c_rtc_base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN;
+       clk_enable(info->rtc_clk);
+       if (info->data->needs_src_clk)
+               clk_enable(info->rtc_src_clk);
+       tmp = readb(info->base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN;
 
        if (enabled)
                tmp |= S3C2410_RTCALM_ALMEN;
 
-       writeb(tmp, s3c_rtc_base + S3C2410_RTCALM);
-       clk_disable(rtc_clk);
+       writeb(tmp, info->base + S3C2410_RTCALM);
+       if (info->data->needs_src_clk)
+               clk_disable(info->rtc_src_clk);
+       clk_disable(info->rtc_clk);
 
-       s3c_rtc_alarm_clk_enable(enabled);
+       s3c_rtc_alarm_clk_enable(info, enabled);
 
        return 0;
 }
 
-static int s3c_rtc_setfreq(struct device *dev, int freq)
+/* Set RTC frequency */
+static int s3c_rtc_setfreq(struct s3c_rtc *info, int freq)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       struct rtc_device *rtc_dev = platform_get_drvdata(pdev);
-       unsigned int tmp = 0;
-       int val;
-
        if (!is_power_of_2(freq))
                return -EINVAL;
 
-       clk_enable(rtc_clk);
-       spin_lock_irq(&s3c_rtc_pie_lock);
+       clk_enable(info->rtc_clk);
+       if (info->data->needs_src_clk)
+               clk_enable(info->rtc_src_clk);
+       spin_lock_irq(&info->pie_lock);
 
-       if (s3c_rtc_cpu_type != TYPE_S3C64XX) {
-               tmp = readb(s3c_rtc_base + S3C2410_TICNT);
-               tmp &= S3C2410_TICNT_ENABLE;
-       }
+       if (info->data->set_freq)
+               info->data->set_freq(info, freq);
 
-       val = (rtc_dev->max_user_freq / freq) - 1;
-
-       if (s3c_rtc_cpu_type == TYPE_S3C2416 || s3c_rtc_cpu_type == TYPE_S3C2443) {
-               tmp |= S3C2443_TICNT_PART(val);
-               writel(S3C2443_TICNT1_PART(val), s3c_rtc_base + S3C2443_TICNT1);
-
-               if (s3c_rtc_cpu_type == TYPE_S3C2416)
-                       writel(S3C2416_TICNT2_PART(val), s3c_rtc_base + S3C2416_TICNT2);
-       } else {
-               tmp |= val;
-       }
-
-       writel(tmp, s3c_rtc_base + S3C2410_TICNT);
-       spin_unlock_irq(&s3c_rtc_pie_lock);
-       clk_disable(rtc_clk);
+       spin_unlock_irq(&info->pie_lock);
+       if (info->data->needs_src_clk)
+               clk_disable(info->rtc_src_clk);
+       clk_disable(info->rtc_clk);
 
        return 0;
 }
 
 /* Time read/write */
-
 static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
 {
+       struct s3c_rtc *info = dev_get_drvdata(dev);
        unsigned int have_retried = 0;
-       void __iomem *base = s3c_rtc_base;
 
-       clk_enable(rtc_clk);
+       clk_enable(info->rtc_clk);
+       if (info->data->needs_src_clk)
+               clk_enable(info->rtc_src_clk);
+
  retry_get_time:
-       rtc_tm->tm_min  = readb(base + S3C2410_RTCMIN);
-       rtc_tm->tm_hour = readb(base + S3C2410_RTCHOUR);
-       rtc_tm->tm_mday = readb(base + S3C2410_RTCDATE);
-       rtc_tm->tm_mon  = readb(base + S3C2410_RTCMON);
-       rtc_tm->tm_year = readb(base + S3C2410_RTCYEAR);
-       rtc_tm->tm_sec  = readb(base + S3C2410_RTCSEC);
+       rtc_tm->tm_min  = readb(info->base + S3C2410_RTCMIN);
+       rtc_tm->tm_hour = readb(info->base + S3C2410_RTCHOUR);
+       rtc_tm->tm_mday = readb(info->base + S3C2410_RTCDATE);
+       rtc_tm->tm_mon  = readb(info->base + S3C2410_RTCMON);
+       rtc_tm->tm_year = readb(info->base + S3C2410_RTCYEAR);
+       rtc_tm->tm_sec  = readb(info->base + S3C2410_RTCSEC);
 
        /* the only way to work out whether the system was mid-update
         * when we read it is to check the second counter, and if it
@@ -207,13 +202,16 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
 
        rtc_tm->tm_mon -= 1;
 
-       clk_disable(rtc_clk);
+       if (info->data->needs_src_clk)
+               clk_disable(info->rtc_src_clk);
+       clk_disable(info->rtc_clk);
+
        return rtc_valid_tm(rtc_tm);
 }
 
 static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
 {
-       void __iomem *base = s3c_rtc_base;
+       struct s3c_rtc *info = dev_get_drvdata(dev);
        int year = tm->tm_year - 100;
 
        dev_dbg(dev, "set time %04d.%02d.%02d %02d:%02d:%02d\n",
@@ -227,33 +225,42 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
                return -EINVAL;
        }
 
-       clk_enable(rtc_clk);
-       writeb(bin2bcd(tm->tm_sec),  base + S3C2410_RTCSEC);
-       writeb(bin2bcd(tm->tm_min),  base + S3C2410_RTCMIN);
-       writeb(bin2bcd(tm->tm_hour), base + S3C2410_RTCHOUR);
-       writeb(bin2bcd(tm->tm_mday), base + S3C2410_RTCDATE);
-       writeb(bin2bcd(tm->tm_mon + 1), base + S3C2410_RTCMON);
-       writeb(bin2bcd(year), base + S3C2410_RTCYEAR);
-       clk_disable(rtc_clk);
+       clk_enable(info->rtc_clk);
+       if (info->data->needs_src_clk)
+               clk_enable(info->rtc_src_clk);
+
+       writeb(bin2bcd(tm->tm_sec),  info->base + S3C2410_RTCSEC);
+       writeb(bin2bcd(tm->tm_min),  info->base + S3C2410_RTCMIN);
+       writeb(bin2bcd(tm->tm_hour), info->base + S3C2410_RTCHOUR);
+       writeb(bin2bcd(tm->tm_mday), info->base + S3C2410_RTCDATE);
+       writeb(bin2bcd(tm->tm_mon + 1), info->base + S3C2410_RTCMON);
+       writeb(bin2bcd(year), info->base + S3C2410_RTCYEAR);
+
+       if (info->data->needs_src_clk)
+               clk_disable(info->rtc_src_clk);
+       clk_disable(info->rtc_clk);
 
        return 0;
 }
 
 static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
 {
+       struct s3c_rtc *info = dev_get_drvdata(dev);
        struct rtc_time *alm_tm = &alrm->time;
-       void __iomem *base = s3c_rtc_base;
        unsigned int alm_en;
 
-       clk_enable(rtc_clk);
-       alm_tm->tm_sec  = readb(base + S3C2410_ALMSEC);
-       alm_tm->tm_min  = readb(base + S3C2410_ALMMIN);
-       alm_tm->tm_hour = readb(base + S3C2410_ALMHOUR);
-       alm_tm->tm_mon  = readb(base + S3C2410_ALMMON);
-       alm_tm->tm_mday = readb(base + S3C2410_ALMDATE);
-       alm_tm->tm_year = readb(base + S3C2410_ALMYEAR);
+       clk_enable(info->rtc_clk);
+       if (info->data->needs_src_clk)
+               clk_enable(info->rtc_src_clk);
 
-       alm_en = readb(base + S3C2410_RTCALM);
+       alm_tm->tm_sec  = readb(info->base + S3C2410_ALMSEC);
+       alm_tm->tm_min  = readb(info->base + S3C2410_ALMMIN);
+       alm_tm->tm_hour = readb(info->base + S3C2410_ALMHOUR);
+       alm_tm->tm_mon  = readb(info->base + S3C2410_ALMMON);
+       alm_tm->tm_mday = readb(info->base + S3C2410_ALMDATE);
+       alm_tm->tm_year = readb(info->base + S3C2410_ALMYEAR);
+
+       alm_en = readb(info->base + S3C2410_RTCALM);
 
        alrm->enabled = (alm_en & S3C2410_RTCALM_ALMEN) ? 1 : 0;
 
@@ -297,65 +304,74 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
        else
                alm_tm->tm_year = -1;
 
-       clk_disable(rtc_clk);
+       if (info->data->needs_src_clk)
+               clk_disable(info->rtc_src_clk);
+       clk_disable(info->rtc_clk);
+
        return 0;
 }
 
 static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
 {
+       struct s3c_rtc *info = dev_get_drvdata(dev);
        struct rtc_time *tm = &alrm->time;
-       void __iomem *base = s3c_rtc_base;
        unsigned int alrm_en;
 
-       clk_enable(rtc_clk);
+       clk_enable(info->rtc_clk);
+       if (info->data->needs_src_clk)
+               clk_enable(info->rtc_src_clk);
+
        dev_dbg(dev, "s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n",
                 alrm->enabled,
                 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday,
                 tm->tm_hour, tm->tm_min, tm->tm_sec);
 
-       alrm_en = readb(base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN;
-       writeb(0x00, base + S3C2410_RTCALM);
+       alrm_en = readb(info->base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN;
+       writeb(0x00, info->base + S3C2410_RTCALM);
 
        if (tm->tm_sec < 60 && tm->tm_sec >= 0) {
                alrm_en |= S3C2410_RTCALM_SECEN;
-               writeb(bin2bcd(tm->tm_sec), base + S3C2410_ALMSEC);
+               writeb(bin2bcd(tm->tm_sec), info->base + S3C2410_ALMSEC);
        }
 
        if (tm->tm_min < 60 && tm->tm_min >= 0) {
                alrm_en |= S3C2410_RTCALM_MINEN;
-               writeb(bin2bcd(tm->tm_min), base + S3C2410_ALMMIN);
+               writeb(bin2bcd(tm->tm_min), info->base + S3C2410_ALMMIN);
        }
 
        if (tm->tm_hour < 24 && tm->tm_hour >= 0) {
                alrm_en |= S3C2410_RTCALM_HOUREN;
-               writeb(bin2bcd(tm->tm_hour), base + S3C2410_ALMHOUR);
+               writeb(bin2bcd(tm->tm_hour), info->base + S3C2410_ALMHOUR);
        }
 
        dev_dbg(dev, "setting S3C2410_RTCALM to %08x\n", alrm_en);
 
-       writeb(alrm_en, base + S3C2410_RTCALM);
+       writeb(alrm_en, info->base + S3C2410_RTCALM);
 
        s3c_rtc_setaie(dev, alrm->enabled);
 
-       clk_disable(rtc_clk);
+       if (info->data->needs_src_clk)
+               clk_disable(info->rtc_src_clk);
+       clk_disable(info->rtc_clk);
+
        return 0;
 }
 
 static int s3c_rtc_proc(struct device *dev, struct seq_file *seq)
 {
-       unsigned int ticnt;
+       struct s3c_rtc *info = dev_get_drvdata(dev);
 
-       clk_enable(rtc_clk);
-       if (s3c_rtc_cpu_type == TYPE_S3C64XX) {
-               ticnt = readw(s3c_rtc_base + S3C2410_RTCCON);
-               ticnt &= S3C64XX_RTCCON_TICEN;
-       } else {
-               ticnt = readb(s3c_rtc_base + S3C2410_TICNT);
-               ticnt &= S3C2410_TICNT_ENABLE;
-       }
+       clk_enable(info->rtc_clk);
+       if (info->data->needs_src_clk)
+               clk_enable(info->rtc_src_clk);
+
+       if (info->data->enable_tick)
+               info->data->enable_tick(info, seq);
+
+       if (info->data->needs_src_clk)
+               clk_disable(info->rtc_src_clk);
+       clk_disable(info->rtc_clk);
 
-       seq_printf(seq, "periodic_IRQ\t: %s\n", ticnt  ? "yes" : "no");
-       clk_disable(rtc_clk);
        return 0;
 }
 
@@ -368,152 +384,199 @@ static const struct rtc_class_ops s3c_rtcops = {
        .alarm_irq_enable = s3c_rtc_setaie,
 };
 
-static void s3c_rtc_enable(struct platform_device *pdev, int en)
+static void s3c24xx_rtc_enable(struct s3c_rtc *info)
 {
-       void __iomem *base = s3c_rtc_base;
-       unsigned int tmp;
+       unsigned int con, tmp;
 
-       if (s3c_rtc_base == NULL)
-               return;
-
-       clk_enable(rtc_clk);
-       if (!en) {
-               tmp = readw(base + S3C2410_RTCCON);
-               if (s3c_rtc_cpu_type == TYPE_S3C64XX)
-                       tmp &= ~S3C64XX_RTCCON_TICEN;
-               tmp &= ~S3C2410_RTCCON_RTCEN;
-               writew(tmp, base + S3C2410_RTCCON);
-
-               if (s3c_rtc_cpu_type != TYPE_S3C64XX) {
-                       tmp = readb(base + S3C2410_TICNT);
-                       tmp &= ~S3C2410_TICNT_ENABLE;
-                       writeb(tmp, base + S3C2410_TICNT);
-               }
-       } else {
-               /* re-enable the device, and check it is ok */
+       clk_enable(info->rtc_clk);
+       if (info->data->needs_src_clk)
+               clk_enable(info->rtc_src_clk);
 
-               if ((readw(base+S3C2410_RTCCON) & S3C2410_RTCCON_RTCEN) == 0) {
-                       dev_info(&pdev->dev, "rtc disabled, re-enabling\n");
+       con = readw(info->base + S3C2410_RTCCON);
+       /* re-enable the device, and check it is ok */
+       if ((con & S3C2410_RTCCON_RTCEN) == 0) {
+               dev_info(info->dev, "rtc disabled, re-enabling\n");
 
-                       tmp = readw(base + S3C2410_RTCCON);
-                       writew(tmp | S3C2410_RTCCON_RTCEN,
-                               base + S3C2410_RTCCON);
-               }
+               tmp = readw(info->base + S3C2410_RTCCON);
+               writew(tmp | S3C2410_RTCCON_RTCEN,
+                       info->base + S3C2410_RTCCON);
+       }
 
-               if ((readw(base + S3C2410_RTCCON) & S3C2410_RTCCON_CNTSEL)) {
-                       dev_info(&pdev->dev, "removing RTCCON_CNTSEL\n");
+       if (con & S3C2410_RTCCON_CNTSEL) {
+               dev_info(info->dev, "removing RTCCON_CNTSEL\n");
 
-                       tmp = readw(base + S3C2410_RTCCON);
-                       writew(tmp & ~S3C2410_RTCCON_CNTSEL,
-                               base + S3C2410_RTCCON);
-               }
+               tmp = readw(info->base + S3C2410_RTCCON);
+               writew(tmp & ~S3C2410_RTCCON_CNTSEL,
+                       info->base + S3C2410_RTCCON);
+       }
 
-               if ((readw(base + S3C2410_RTCCON) & S3C2410_RTCCON_CLKRST)) {
-                       dev_info(&pdev->dev, "removing RTCCON_CLKRST\n");
+       if (con & S3C2410_RTCCON_CLKRST) {
+               dev_info(info->dev, "removing RTCCON_CLKRST\n");
 
-                       tmp = readw(base + S3C2410_RTCCON);
-                       writew(tmp & ~S3C2410_RTCCON_CLKRST,
-                               base + S3C2410_RTCCON);
-               }
+               tmp = readw(info->base + S3C2410_RTCCON);
+               writew(tmp & ~S3C2410_RTCCON_CLKRST,
+                       info->base + S3C2410_RTCCON);
        }
-       clk_disable(rtc_clk);
+
+       if (info->data->needs_src_clk)
+               clk_disable(info->rtc_src_clk);
+       clk_disable(info->rtc_clk);
 }
 
-static int s3c_rtc_remove(struct platform_device *dev)
+static void s3c24xx_rtc_disable(struct s3c_rtc *info)
 {
-       s3c_rtc_setaie(&dev->dev, 0);
+       unsigned int con;
+
+       clk_enable(info->rtc_clk);
+       if (info->data->needs_src_clk)
+               clk_enable(info->rtc_src_clk);
+
+       con = readw(info->base + S3C2410_RTCCON);
+       con &= ~S3C2410_RTCCON_RTCEN;
+       writew(con, info->base + S3C2410_RTCCON);
 
-       clk_unprepare(rtc_clk);
-       rtc_clk = NULL;
+       con = readb(info->base + S3C2410_TICNT);
+       con &= ~S3C2410_TICNT_ENABLE;
+       writeb(con, info->base + S3C2410_TICNT);
+
+       if (info->data->needs_src_clk)
+               clk_disable(info->rtc_src_clk);
+       clk_disable(info->rtc_clk);
+}
+
+static void s3c6410_rtc_disable(struct s3c_rtc *info)
+{
+       unsigned int con;
+
+       clk_enable(info->rtc_clk);
+       if (info->data->needs_src_clk)
+               clk_enable(info->rtc_src_clk);
+
+       con = readw(info->base + S3C2410_RTCCON);
+       con &= ~S3C64XX_RTCCON_TICEN;
+       con &= ~S3C2410_RTCCON_RTCEN;
+       writew(con, info->base + S3C2410_RTCCON);
+
+       if (info->data->needs_src_clk)
+               clk_disable(info->rtc_src_clk);
+       clk_disable(info->rtc_clk);
+}
+
+static int s3c_rtc_remove(struct platform_device *pdev)
+{
+       struct s3c_rtc *info = platform_get_drvdata(pdev);
+
+       s3c_rtc_setaie(info->dev, 0);
+
+       clk_unprepare(info->rtc_clk);
+       info->rtc_clk = NULL;
 
        return 0;
 }
 
 static const struct of_device_id s3c_rtc_dt_match[];
 
-static inline int s3c_rtc_get_driver_data(struct platform_device *pdev)
+static struct s3c_rtc_data *s3c_rtc_get_data(struct platform_device *pdev)
 {
-#ifdef CONFIG_OF
-       struct s3c_rtc_drv_data *data;
-       if (pdev->dev.of_node) {
-               const struct of_device_id *match;
-               match = of_match_node(s3c_rtc_dt_match, pdev->dev.of_node);
-               data = (struct s3c_rtc_drv_data *) match->data;
-               return data->cpu_type;
-       }
-#endif
-       return platform_get_device_id(pdev)->driver_data;
+       const struct of_device_id *match;
+
+       match = of_match_node(s3c_rtc_dt_match, pdev->dev.of_node);
+       return (struct s3c_rtc_data *)match->data;
 }
 
 static int s3c_rtc_probe(struct platform_device *pdev)
 {
-       struct rtc_device *rtc;
+       struct s3c_rtc *info = NULL;
        struct rtc_time rtc_tm;
        struct resource *res;
        int ret;
-       int tmp;
 
-       dev_dbg(&pdev->dev, "%s: probe=%p\n", __func__, pdev);
+       info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+       if (!info)
+               return -ENOMEM;
 
        /* find the IRQs */
-
-       s3c_rtc_tickno = platform_get_irq(pdev, 1);
-       if (s3c_rtc_tickno < 0) {
+       info->irq_tick = platform_get_irq(pdev, 1);
+       if (info->irq_tick < 0) {
                dev_err(&pdev->dev, "no irq for rtc tick\n");
-               return s3c_rtc_tickno;
+               return info->irq_tick;
+       }
+
+       info->dev = &pdev->dev;
+       info->data = s3c_rtc_get_data(pdev);
+       if (!info->data) {
+               dev_err(&pdev->dev, "failed getting s3c_rtc_data\n");
+               return -EINVAL;
        }
+       spin_lock_init(&info->pie_lock);
+       spin_lock_init(&info->alarm_clk_lock);
+
+       platform_set_drvdata(pdev, info);
 
-       s3c_rtc_alarmno = platform_get_irq(pdev, 0);
-       if (s3c_rtc_alarmno < 0) {
+       info->irq_alarm = platform_get_irq(pdev, 0);
+       if (info->irq_alarm < 0) {
                dev_err(&pdev->dev, "no irq for alarm\n");
-               return s3c_rtc_alarmno;
+               return info->irq_alarm;
        }
 
        dev_dbg(&pdev->dev, "s3c2410_rtc: tick irq %d, alarm irq %d\n",
-                s3c_rtc_tickno, s3c_rtc_alarmno);
+                info->irq_tick, info->irq_alarm);
 
        /* get the memory region */
-
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       s3c_rtc_base = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(s3c_rtc_base))
-               return PTR_ERR(s3c_rtc_base);
-
-       rtc_clk = devm_clk_get(&pdev->dev, "rtc");
-       if (IS_ERR(rtc_clk)) {
-               dev_err(&pdev->dev, "failed to find rtc clock source\n");
-               ret = PTR_ERR(rtc_clk);
-               rtc_clk = NULL;
-               return ret;
+       info->base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(info->base))
+               return PTR_ERR(info->base);
+
+       info->rtc_clk = devm_clk_get(&pdev->dev, "rtc");
+       if (IS_ERR(info->rtc_clk)) {
+               dev_err(&pdev->dev, "failed to find rtc clock\n");
+               return PTR_ERR(info->rtc_clk);
        }
+       clk_prepare_enable(info->rtc_clk);
 
-       clk_prepare_enable(rtc_clk);
+       info->rtc_src_clk = devm_clk_get(&pdev->dev, "rtc_src");
+       if (IS_ERR(info->rtc_src_clk)) {
+               dev_err(&pdev->dev, "failed to find rtc source clock\n");
+               return PTR_ERR(info->rtc_src_clk);
+       }
+       clk_prepare_enable(info->rtc_src_clk);
 
-       /* check to see if everything is setup correctly */
 
-       s3c_rtc_enable(pdev, 1);
+       /* check to see if everything is setup correctly */
+       if (info->data->enable)
+               info->data->enable(info);
 
        dev_dbg(&pdev->dev, "s3c2410_rtc: RTCCON=%02x\n",
-                readw(s3c_rtc_base + S3C2410_RTCCON));
+                readw(info->base + S3C2410_RTCCON));
 
        device_init_wakeup(&pdev->dev, 1);
 
        /* register RTC and exit */
-
-       rtc = devm_rtc_device_register(&pdev->dev, "s3c", &s3c_rtcops,
+       info->rtc = devm_rtc_device_register(&pdev->dev, "s3c", &s3c_rtcops,
                                  THIS_MODULE);
-
-       if (IS_ERR(rtc)) {
+       if (IS_ERR(info->rtc)) {
                dev_err(&pdev->dev, "cannot attach rtc\n");
-               ret = PTR_ERR(rtc);
+               ret = PTR_ERR(info->rtc);
                goto err_nortc;
        }
 
-       s3c_rtc_cpu_type = s3c_rtc_get_driver_data(pdev);
+       ret = devm_request_irq(&pdev->dev, info->irq_alarm, s3c_rtc_alarmirq,
+                         0,  "s3c2410-rtc alarm", info);
+       if (ret) {
+               dev_err(&pdev->dev, "IRQ%d error %d\n", info->irq_alarm, ret);
+               goto err_nortc;
+       }
 
-       /* Check RTC Time */
+       ret = devm_request_irq(&pdev->dev, info->irq_tick, s3c_rtc_tickirq,
+                         0,  "s3c2410-rtc tick", info);
+       if (ret) {
+               dev_err(&pdev->dev, "IRQ%d error %d\n", info->irq_tick, ret);
+               goto err_nortc;
+       }
 
-       s3c_rtc_gettime(NULL, &rtc_tm);
+       /* Check RTC Time */
+       s3c_rtc_gettime(&pdev->dev, &rtc_tm);
 
        if (rtc_valid_tm(&rtc_tm)) {
                rtc_tm.tm_year  = 100;
@@ -523,163 +586,312 @@ static int s3c_rtc_probe(struct platform_device *pdev)
                rtc_tm.tm_min   = 0;
                rtc_tm.tm_sec   = 0;
 
-               s3c_rtc_settime(NULL, &rtc_tm);
+               s3c_rtc_settime(&pdev->dev, &rtc_tm);
 
                dev_warn(&pdev->dev, "warning: invalid RTC value so initializing it\n");
        }
 
-       if (s3c_rtc_cpu_type != TYPE_S3C2410)
-               rtc->max_user_freq = 32768;
-       else
-               rtc->max_user_freq = 128;
-
-       if (s3c_rtc_cpu_type == TYPE_S3C2416 || s3c_rtc_cpu_type == TYPE_S3C2443) {
-               tmp = readw(s3c_rtc_base + S3C2410_RTCCON);
-               tmp |= S3C2443_RTCCON_TICSEL;
-               writew(tmp, s3c_rtc_base + S3C2410_RTCCON);
-       }
+       if (info->data->select_tick_clk)
+               info->data->select_tick_clk(info);
 
-       platform_set_drvdata(pdev, rtc);
+       s3c_rtc_setfreq(info, 1);
 
-       s3c_rtc_setfreq(&pdev->dev, 1);
-
-       ret = devm_request_irq(&pdev->dev, s3c_rtc_alarmno, s3c_rtc_alarmirq,
-                         0,  "s3c2410-rtc alarm", rtc);
-       if (ret) {
-               dev_err(&pdev->dev, "IRQ%d error %d\n", s3c_rtc_alarmno, ret);
-               goto err_nortc;
-       }
-
-       ret = devm_request_irq(&pdev->dev, s3c_rtc_tickno, s3c_rtc_tickirq,
-                         0,  "s3c2410-rtc tick", rtc);
-       if (ret) {
-               dev_err(&pdev->dev, "IRQ%d error %d\n", s3c_rtc_tickno, ret);
-               goto err_nortc;
-       }
-
-       clk_disable(rtc_clk);
+       if (info->data->needs_src_clk)
+               clk_disable(info->rtc_src_clk);
+       clk_disable(info->rtc_clk);
 
        return 0;
 
  err_nortc:
-       s3c_rtc_enable(pdev, 0);
-       clk_disable_unprepare(rtc_clk);
+       if (info->data->disable)
+               info->data->disable(info);
+       clk_disable_unprepare(info->rtc_clk);
 
        return ret;
 }
 
 #ifdef CONFIG_PM_SLEEP
-/* RTC Power management control */
-
-static int ticnt_save, ticnt_en_save;
-static bool wake_en;
 
 static int s3c_rtc_suspend(struct device *dev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
+       struct s3c_rtc *info = dev_get_drvdata(dev);
+
+       clk_enable(info->rtc_clk);
+       if (info->data->needs_src_clk)
+               clk_enable(info->rtc_src_clk);
 
-       clk_enable(rtc_clk);
        /* save TICNT for anyone using periodic interrupts */
-       if (s3c_rtc_cpu_type == TYPE_S3C64XX) {
-               ticnt_en_save = readw(s3c_rtc_base + S3C2410_RTCCON);
-               ticnt_en_save &= S3C64XX_RTCCON_TICEN;
-               ticnt_save = readl(s3c_rtc_base + S3C2410_TICNT);
-       } else {
-               ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT);
-       }
-       s3c_rtc_enable(pdev, 0);
+       if (info->data->save_tick_cnt)
+               info->data->save_tick_cnt(info);
+
+       if (info->data->disable)
+               info->data->disable(info);
 
-       if (device_may_wakeup(dev) && !wake_en) {
-               if (enable_irq_wake(s3c_rtc_alarmno) == 0)
-                       wake_en = true;
+       if (device_may_wakeup(dev) && !info->wake_en) {
+               if (enable_irq_wake(info->irq_alarm) == 0)
+                       info->wake_en = true;
                else
                        dev_err(dev, "enable_irq_wake failed\n");
        }
-       clk_disable(rtc_clk);
+
+       if (info->data->needs_src_clk)
+               clk_disable(info->rtc_src_clk);
+       clk_disable(info->rtc_clk);
 
        return 0;
 }
 
 static int s3c_rtc_resume(struct device *dev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       unsigned int tmp;
+       struct s3c_rtc *info = dev_get_drvdata(dev);
 
-       clk_enable(rtc_clk);
-       s3c_rtc_enable(pdev, 1);
-       if (s3c_rtc_cpu_type == TYPE_S3C64XX) {
-               writel(ticnt_save, s3c_rtc_base + S3C2410_TICNT);
-               if (ticnt_en_save) {
-                       tmp = readw(s3c_rtc_base + S3C2410_RTCCON);
-                       writew(tmp | ticnt_en_save,
-                                       s3c_rtc_base + S3C2410_RTCCON);
-               }
-       } else {
-               writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT);
-       }
+       clk_enable(info->rtc_clk);
+       if (info->data->needs_src_clk)
+               clk_enable(info->rtc_src_clk);
 
-       if (device_may_wakeup(dev) && wake_en) {
-               disable_irq_wake(s3c_rtc_alarmno);
-               wake_en = false;
+       if (info->data->enable)
+               info->data->enable(info);
+
+       if (info->data->restore_tick_cnt)
+               info->data->restore_tick_cnt(info);
+
+       if (device_may_wakeup(dev) && info->wake_en) {
+               disable_irq_wake(info->irq_alarm);
+               info->wake_en = false;
        }
-       clk_disable(rtc_clk);
+
+       if (info->data->needs_src_clk)
+               clk_disable(info->rtc_src_clk);
+       clk_disable(info->rtc_clk);
 
        return 0;
 }
 #endif
-
 static SIMPLE_DEV_PM_OPS(s3c_rtc_pm_ops, s3c_rtc_suspend, s3c_rtc_resume);
 
-#ifdef CONFIG_OF
-static struct s3c_rtc_drv_data s3c_rtc_drv_data_array[] = {
-       [TYPE_S3C2410] = { TYPE_S3C2410 },
-       [TYPE_S3C2416] = { TYPE_S3C2416 },
-       [TYPE_S3C2443] = { TYPE_S3C2443 },
-       [TYPE_S3C64XX] = { TYPE_S3C64XX },
+static void s3c24xx_rtc_irq(struct s3c_rtc *info, int mask)
+{
+       clk_enable(info->rtc_clk);
+       if (info->data->needs_src_clk)
+               clk_enable(info->rtc_src_clk);
+       rtc_update_irq(info->rtc, 1, RTC_AF | RTC_IRQF);
+       if (info->data->needs_src_clk)
+               clk_disable(info->rtc_src_clk);
+       clk_disable(info->rtc_clk);
+
+       s3c_rtc_alarm_clk_enable(info, false);
+}
+
+static void s3c6410_rtc_irq(struct s3c_rtc *info, int mask)
+{
+       clk_enable(info->rtc_clk);
+       if (info->data->needs_src_clk)
+               clk_enable(info->rtc_src_clk);
+       rtc_update_irq(info->rtc, 1, RTC_AF | RTC_IRQF);
+       writeb(mask, info->base + S3C2410_INTP);
+       if (info->data->needs_src_clk)
+               clk_disable(info->rtc_src_clk);
+       clk_disable(info->rtc_clk);
+
+       s3c_rtc_alarm_clk_enable(info, false);
+}
+
+static void s3c2410_rtc_setfreq(struct s3c_rtc *info, int freq)
+{
+       unsigned int tmp = 0;
+       int val;
+
+       tmp = readb(info->base + S3C2410_TICNT);
+       tmp &= S3C2410_TICNT_ENABLE;
+
+       val = (info->rtc->max_user_freq / freq) - 1;
+       tmp |= val;
+
+       writel(tmp, info->base + S3C2410_TICNT);
+}
+
+static void s3c2416_rtc_setfreq(struct s3c_rtc *info, int freq)
+{
+       unsigned int tmp = 0;
+       int val;
+
+       tmp = readb(info->base + S3C2410_TICNT);
+       tmp &= S3C2410_TICNT_ENABLE;
+
+       val = (info->rtc->max_user_freq / freq) - 1;
+
+       tmp |= S3C2443_TICNT_PART(val);
+       writel(S3C2443_TICNT1_PART(val), info->base + S3C2443_TICNT1);
+
+       writel(S3C2416_TICNT2_PART(val), info->base + S3C2416_TICNT2);
+
+       writel(tmp, info->base + S3C2410_TICNT);
+}
+
+static void s3c2443_rtc_setfreq(struct s3c_rtc *info, int freq)
+{
+       unsigned int tmp = 0;
+       int val;
+
+       tmp = readb(info->base + S3C2410_TICNT);
+       tmp &= S3C2410_TICNT_ENABLE;
+
+       val = (info->rtc->max_user_freq / freq) - 1;
+
+       tmp |= S3C2443_TICNT_PART(val);
+       writel(S3C2443_TICNT1_PART(val), info->base + S3C2443_TICNT1);
+
+       writel(tmp, info->base + S3C2410_TICNT);
+}
+
+static void s3c6410_rtc_setfreq(struct s3c_rtc *info, int freq)
+{
+       int val;
+
+       val = (info->rtc->max_user_freq / freq) - 1;
+       writel(val, info->base + S3C2410_TICNT);
+}
+
+static void s3c24xx_rtc_enable_tick(struct s3c_rtc *info, struct seq_file *seq)
+{
+       unsigned int ticnt;
+
+       ticnt = readb(info->base + S3C2410_TICNT);
+       ticnt &= S3C2410_TICNT_ENABLE;
+
+       seq_printf(seq, "periodic_IRQ\t: %s\n", ticnt  ? "yes" : "no");
+}
+
+static void s3c2416_rtc_select_tick_clk(struct s3c_rtc *info)
+{
+       unsigned int con;
+
+       con = readw(info->base + S3C2410_RTCCON);
+       con |= S3C2443_RTCCON_TICSEL;
+       writew(con, info->base + S3C2410_RTCCON);
+}
+
+static void s3c6410_rtc_enable_tick(struct s3c_rtc *info, struct seq_file *seq)
+{
+       unsigned int ticnt;
+
+       ticnt = readw(info->base + S3C2410_RTCCON);
+       ticnt &= S3C64XX_RTCCON_TICEN;
+
+       seq_printf(seq, "periodic_IRQ\t: %s\n", ticnt  ? "yes" : "no");
+}
+
+static void s3c24xx_rtc_save_tick_cnt(struct s3c_rtc *info)
+{
+       info->ticnt_save = readb(info->base + S3C2410_TICNT);
+}
+
+static void s3c24xx_rtc_restore_tick_cnt(struct s3c_rtc *info)
+{
+       writeb(info->ticnt_save, info->base + S3C2410_TICNT);
+}
+
+static void s3c6410_rtc_save_tick_cnt(struct s3c_rtc *info)
+{
+       info->ticnt_en_save = readw(info->base + S3C2410_RTCCON);
+       info->ticnt_en_save &= S3C64XX_RTCCON_TICEN;
+       info->ticnt_save = readl(info->base + S3C2410_TICNT);
+}
+
+static void s3c6410_rtc_restore_tick_cnt(struct s3c_rtc *info)
+{
+       unsigned int con;
+
+       writel(info->ticnt_save, info->base + S3C2410_TICNT);
+       if (info->ticnt_en_save) {
+               con = readw(info->base + S3C2410_RTCCON);
+               writew(con | info->ticnt_en_save,
+                               info->base + S3C2410_RTCCON);
+       }
+}
+
+static struct s3c_rtc_data const s3c2410_rtc_data = {
+       .max_user_freq          = 128,
+       .irq_handler            = s3c24xx_rtc_irq,
+       .set_freq               = s3c2410_rtc_setfreq,
+       .enable_tick            = s3c24xx_rtc_enable_tick,
+       .save_tick_cnt          = s3c24xx_rtc_save_tick_cnt,
+       .restore_tick_cnt       = s3c24xx_rtc_restore_tick_cnt,
+       .enable                 = s3c24xx_rtc_enable,
+       .disable                = s3c24xx_rtc_disable,
+};
+
+static struct s3c_rtc_data const s3c2416_rtc_data = {
+       .max_user_freq          = 32768,
+       .irq_handler            = s3c24xx_rtc_irq,
+       .set_freq               = s3c2416_rtc_setfreq,
+       .enable_tick            = s3c24xx_rtc_enable_tick,
+       .select_tick_clk        = s3c2416_rtc_select_tick_clk,
+       .save_tick_cnt          = s3c24xx_rtc_save_tick_cnt,
+       .restore_tick_cnt       = s3c24xx_rtc_restore_tick_cnt,
+       .enable                 = s3c24xx_rtc_enable,
+       .disable                = s3c24xx_rtc_disable,
+};
+
+static struct s3c_rtc_data const s3c2443_rtc_data = {
+       .max_user_freq          = 32768,
+       .irq_handler            = s3c24xx_rtc_irq,
+       .set_freq               = s3c2443_rtc_setfreq,
+       .enable_tick            = s3c24xx_rtc_enable_tick,
+       .select_tick_clk        = s3c2416_rtc_select_tick_clk,
+       .save_tick_cnt          = s3c24xx_rtc_save_tick_cnt,
+       .restore_tick_cnt       = s3c24xx_rtc_restore_tick_cnt,
+       .enable                 = s3c24xx_rtc_enable,
+       .disable                = s3c24xx_rtc_disable,
+};
+
+static struct s3c_rtc_data const s3c6410_rtc_data = {
+       .max_user_freq          = 32768,
+       .irq_handler            = s3c6410_rtc_irq,
+       .set_freq               = s3c6410_rtc_setfreq,
+       .enable_tick            = s3c6410_rtc_enable_tick,
+       .save_tick_cnt          = s3c6410_rtc_save_tick_cnt,
+       .restore_tick_cnt       = s3c6410_rtc_restore_tick_cnt,
+       .enable                 = s3c24xx_rtc_enable,
+       .disable                = s3c6410_rtc_disable,
+};
+
+static struct s3c_rtc_data const exynos3250_rtc_data = {
+       .max_user_freq          = 32768,
+       .needs_src_clk          = true,
+       .irq_handler            = s3c6410_rtc_irq,
+       .set_freq               = s3c6410_rtc_setfreq,
+       .enable_tick            = s3c6410_rtc_enable_tick,
+       .save_tick_cnt          = s3c6410_rtc_save_tick_cnt,
+       .restore_tick_cnt       = s3c6410_rtc_restore_tick_cnt,
+       .enable                 = s3c24xx_rtc_enable,
+       .disable                = s3c6410_rtc_disable,
 };
 
 static const struct of_device_id s3c_rtc_dt_match[] = {
        {
                .compatible = "samsung,s3c2410-rtc",
-               .data = &s3c_rtc_drv_data_array[TYPE_S3C2410],
+               .data = (void *)&s3c2410_rtc_data,
        }, {
                .compatible = "samsung,s3c2416-rtc",
-               .data = &s3c_rtc_drv_data_array[TYPE_S3C2416],
+               .data = (void *)&s3c2416_rtc_data,
        }, {
                .compatible = "samsung,s3c2443-rtc",
-               .data = &s3c_rtc_drv_data_array[TYPE_S3C2443],
+               .data = (void *)&s3c2443_rtc_data,
        }, {
                .compatible = "samsung,s3c6410-rtc",
-               .data = &s3c_rtc_drv_data_array[TYPE_S3C64XX],
-       },
-       {},
-};
-MODULE_DEVICE_TABLE(of, s3c_rtc_dt_match);
-#endif
-
-static struct platform_device_id s3c_rtc_driver_ids[] = {
-       {
-               .name           = "s3c2410-rtc",
-               .driver_data    = TYPE_S3C2410,
-       }, {
-               .name           = "s3c2416-rtc",
-               .driver_data    = TYPE_S3C2416,
-       }, {
-               .name           = "s3c2443-rtc",
-               .driver_data    = TYPE_S3C2443,
+               .data = (void *)&s3c6410_rtc_data,
        }, {
-               .name           = "s3c64xx-rtc",
-               .driver_data    = TYPE_S3C64XX,
+               .compatible = "samsung,exynos3250-rtc",
+               .data = (void *)&exynos3250_rtc_data,
        },
-       { }
+       { /* sentinel */ },
 };
-
-MODULE_DEVICE_TABLE(platform, s3c_rtc_driver_ids);
+MODULE_DEVICE_TABLE(of, s3c_rtc_dt_match);
 
 static struct platform_driver s3c_rtc_driver = {
        .probe          = s3c_rtc_probe,
        .remove         = s3c_rtc_remove,
-       .id_table       = s3c_rtc_driver_ids,
        .driver         = {
                .name   = "s3c-rtc",
                .owner  = THIS_MODULE,
@@ -687,7 +899,6 @@ static struct platform_driver s3c_rtc_driver = {
                .of_match_table = of_match_ptr(s3c_rtc_dt_match),
        },
 };
-
 module_platform_driver(s3c_rtc_driver);
 
 MODULE_DESCRIPTION("Samsung S3C RTC Driver");
index d497aa05a72f1da5f2e4b56091c06329696d0130..c692dfebd0bab1c808f460349dff194b028f5c5c 100644 (file)
@@ -257,11 +257,11 @@ static ssize_t chp_status_write(struct device *dev,
        if (!num_args)
                return count;
 
-       if (!strnicmp(cmd, "on", 2) || !strcmp(cmd, "1")) {
+       if (!strncasecmp(cmd, "on", 2) || !strcmp(cmd, "1")) {
                mutex_lock(&cp->lock);
                error = s390_vary_chpid(cp->chpid, 1);
                mutex_unlock(&cp->lock);
-       } else if (!strnicmp(cmd, "off", 3) || !strcmp(cmd, "0")) {
+       } else if (!strncasecmp(cmd, "off", 3) || !strcmp(cmd, "0")) {
                mutex_lock(&cp->lock);
                error = s390_vary_chpid(cp->chpid, 0);
                mutex_unlock(&cp->lock);
index 52a216f21ae579644b97c093e89e12306a265595..e5afc3884d74a68a3f180188edb3fb75c5fba762 100644 (file)
@@ -528,7 +528,7 @@ ips_setup(char *ips_str)
                 * Update the variables
                 */
                for (i = 0; i < ARRAY_SIZE(options); i++) {
-                       if (strnicmp
+                       if (strncasecmp
                            (key, options[i].option_name,
                             strlen(options[i].option_name)) == 0) {
                                if (value)
index 2b6d447ad6d641723169cb45af42efdab5cb16be..238e06f13b8a1c977146699d95f1783bbef571e7 100644 (file)
@@ -3371,7 +3371,7 @@ static ssize_t opts_store(struct device_driver *ddp, const char *buf,
        char work[20];
 
         if (1 == sscanf(buf, "%10s", work)) {
-               if (0 == strnicmp(work,"0x", 2)) {
+               if (0 == strncasecmp(work,"0x", 2)) {
                        if (1 == sscanf(&work[2], "%x", &opts))
                                goto opts_done;
                } else {
index 1718229f627861993cf15223075367cdbb8e63e9..d9d55d12fd5fdef16e3632f3832c7111bb46044d 100644 (file)
@@ -79,7 +79,7 @@ int rtw_android_cmdstr_to_num(char *cmdstr)
 {
        int cmd_num;
        for (cmd_num = 0; cmd_num < ANDROID_WIFI_CMD_MAX; cmd_num++)
-               if (0 == strnicmp(cmdstr , android_wifi_cmd_str[cmd_num],
+               if (0 == strncasecmp(cmdstr , android_wifi_cmd_str[cmd_num],
                                  strlen(android_wifi_cmd_str[cmd_num])))
                        break;
        return cmd_num;
index 91d35df286c345cf0d71a10eee78da76dd437ed6..2d82f8993ea1422111fcfa18f90381b5862024cf 100644 (file)
@@ -2957,25 +2957,13 @@ extern inline int rtllib_get_scans(struct rtllib_device *ieee)
 static inline const char *escape_essid(const char *essid, u8 essid_len)
 {
        static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
-       const char *s = essid;
-       char *d = escaped;
 
        if (rtllib_is_empty_essid(essid, essid_len)) {
                memcpy(escaped, "<hidden>", sizeof("<hidden>"));
                return escaped;
        }
 
-       essid_len = min(essid_len, (u8)IW_ESSID_MAX_SIZE);
-       while (essid_len--) {
-               if (*s == '\0') {
-                       *d++ = '\\';
-                       *d++ = '0';
-                       s++;
-               } else {
-                       *d++ = *s++;
-               }
-       }
-       *d = '\0';
+       snprintf(escaped, sizeof(escaped), "%*pEn", essid_len, essid);
        return escaped;
 }
 
index 9ecfa4a2421d7b5b815d114e0d551615ce9de0e5..b44aa17d30a764f429fad303d9c562d97975b8d4 100644 (file)
@@ -2593,25 +2593,13 @@ static inline int ieee80211_get_scans(struct ieee80211_device *ieee)
 
 static inline const char *escape_essid(const char *essid, u8 essid_len) {
        static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
-       const char *s = essid;
-       char *d = escaped;
 
        if (ieee80211_is_empty_essid(essid, essid_len)) {
                memcpy(escaped, "<hidden>", sizeof("<hidden>"));
                return escaped;
        }
 
-       essid_len = min(essid_len, (u8)IW_ESSID_MAX_SIZE);
-       while (essid_len--) {
-               if (*s == '\0') {
-                       *d++ = '\\';
-                       *d++ = '0';
-                       s++;
-               } else {
-                       *d++ = *s++;
-               }
-       }
-       *d = '\0';
+       snprintf(escaped, sizeof(escaped), "%*pEn", essid_len, essid);
        return escaped;
 }
 
index 799ce8aa70efb2ba30018668d2aebbb6b8d4b107..df577dfe7ffbe18ea45a0f2a91804a1a22f7062e 100644 (file)
@@ -60,7 +60,6 @@
 #include <linux/netdevice.h>
 #include <linux/workqueue.h>
 #include <linux/byteorder/generic.h>
-#include <linux/ctype.h>
 
 #include <linux/io.h>
 #include <linux/delay.h>
 #include "hfa384x.h"
 #include "prism2mgmt.h"
 
-/* Create a string of printable chars from something that might not be */
-/* It's recommended that the str be 4*len + 1 bytes long */
-#define wlan_mkprintstr(buf, buflen, str, strlen) \
-{ \
-       int i = 0; \
-       int j = 0; \
-       memset(str, 0, (strlen)); \
-       for (i = 0; i < (buflen); i++) { \
-               if (isprint((buf)[i])) { \
-                       (str)[j] = (buf)[i]; \
-                       j++; \
-               } else { \
-                       (str)[j] = '\\'; \
-                       (str)[j+1] = 'x'; \
-                       (str)[j+2] = hex_asc_hi((buf)[i]); \
-                       (str)[j+3] = hex_asc_lo((buf)[i]); \
-                       j += 4; \
-               } \
-       } \
-}
-
 static char *dev_info = "prism2_usb";
 static wlandevice_t *create_wlan(void);
 
@@ -607,7 +585,6 @@ static int prism2sta_getcardinfo(wlandevice_t *wlandev)
        hfa384x_t *hw = (hfa384x_t *) wlandev->priv;
        u16 temp;
        u8 snum[HFA384x_RID_NICSERIALNUMBER_LEN];
-       char pstr[(HFA384x_RID_NICSERIALNUMBER_LEN * 4) + 1];
 
        /* Collect version and compatibility info */
        /*  Some are critical, some are not */
@@ -862,9 +839,8 @@ static int prism2sta_getcardinfo(wlandevice_t *wlandev)
        result = hfa384x_drvr_getconfig(hw, HFA384x_RID_NICSERIALNUMBER,
                                        snum, HFA384x_RID_NICSERIALNUMBER_LEN);
        if (!result) {
-               wlan_mkprintstr(snum, HFA384x_RID_NICSERIALNUMBER_LEN,
-                               pstr, sizeof(pstr));
-               netdev_info(wlandev->netdev, "Prism2 card SN: %s\n", pstr);
+               netdev_info(wlandev->netdev, "Prism2 card SN: %*pEhp\n",
+                           HFA384x_RID_NICSERIALNUMBER_LEN, snum);
        } else {
                netdev_err(wlandev->netdev, "Failed to retrieve Prism2 Card SN\n");
                goto failed;
index 71b0ec0c370d73aad18d685118c197735c5b2833..1e23f4f8d2c2099cc2f634010e4ff8ff2c2db11c 100644 (file)
@@ -66,7 +66,7 @@ static struct thermal_governor *__find_governor(const char *name)
                return def_governor;
 
        list_for_each_entry(pos, &thermal_governor_list, governor_list)
-               if (!strnicmp(name, pos->name, THERMAL_NAME_LENGTH))
+               if (!strncasecmp(name, pos->name, THERMAL_NAME_LENGTH))
                        return pos;
 
        return NULL;
@@ -104,7 +104,7 @@ int thermal_register_governor(struct thermal_governor *governor)
 
                name = pos->tzp->governor_name;
 
-               if (!strnicmp(name, governor->name, THERMAL_NAME_LENGTH))
+               if (!strncasecmp(name, governor->name, THERMAL_NAME_LENGTH))
                        pos->governor = governor;
        }
 
@@ -129,7 +129,7 @@ void thermal_unregister_governor(struct thermal_governor *governor)
        mutex_lock(&thermal_list_lock);
 
        list_for_each_entry(pos, &thermal_tz_list, node) {
-               if (!strnicmp(pos->governor->name, governor->name,
+               if (!strncasecmp(pos->governor->name, governor->name,
                                                THERMAL_NAME_LENGTH))
                        pos->governor = NULL;
        }
@@ -1665,7 +1665,7 @@ struct thermal_zone_device *thermal_zone_get_zone_by_name(const char *name)
 
        mutex_lock(&thermal_list_lock);
        list_for_each_entry(pos, &thermal_tz_list, node)
-               if (!strnicmp(name, pos->type, THERMAL_NAME_LENGTH)) {
+               if (!strncasecmp(name, pos->type, THERMAL_NAME_LENGTH)) {
                        found++;
                        ref = pos;
                }
index 167cffff3d4e3436fc60856a43cef5efe3685763..7c74f58fc10194515ffb831ac31ba765315a2c44 100644 (file)
@@ -1001,7 +1001,7 @@ static int pvr2_get_param(const struct pvr2_params *p, const char *s, int val,
 
        for (i = 0 ; i < size ; i++ ) {
                if (s != NULL) {
-                       if (!strnicmp(p[i].name, s, strlen(s)))
+                       if (!strncasecmp(p[i].name, s, strlen(s)))
                                return p[i].val;
                } else {
                        if (p[i].val == val)
index 43c63a4f31784adf4ddaf9021fc2dead0098d309..e350eb57f11d6d7f5e989e1d0a5187fb2944fec8 100644 (file)
@@ -601,12 +601,12 @@ static int s3c2410fb_debug_store(struct device *dev,
        if (len < 1)
                return -EINVAL;
 
-       if (strnicmp(buf, "on", 2) == 0 ||
-           strnicmp(buf, "1", 1) == 0) {
+       if (strncasecmp(buf, "on", 2) == 0 ||
+           strncasecmp(buf, "1", 1) == 0) {
                debug = 1;
                dev_dbg(dev, "s3c2410fb: Debug On");
-       } else if (strnicmp(buf, "off", 3) == 0 ||
-                  strnicmp(buf, "0", 1) == 0) {
+       } else if (strncasecmp(buf, "off", 3) == 0 ||
+                  strncasecmp(buf, "0", 1) == 0) {
                debug = 0;
                dev_dbg(dev, "s3c2410fb: Debug Off");
        } else {
index 3f12a2dd959a0ade49737a9938654acd14a4233f..4f5cf035ac3c9aa524686b67a7d6c57eb62a7456 100644 (file)
@@ -162,7 +162,7 @@ static void sisfb_search_mode(char *name, bool quiet)
                return;
        }
 
-       if(!strnicmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) {
+       if(!strncasecmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) {
                if(!quiet)
                        printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");
 
@@ -201,7 +201,7 @@ static void sisfb_search_mode(char *name, bool quiet)
 
        i = 0; j = 0;
        while(sisbios_mode[i].mode_no[0] != 0) {
-               if(!strnicmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) {
+               if(!strncasecmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) {
                        if(sisfb_fstn) {
                                if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
                                   sisbios_mode[i-1].mode_no[1] == 0x56 ||
@@ -262,7 +262,7 @@ sisfb_search_crt2type(const char *name)
        if(name == NULL) return;
 
        while(sis_crt2type[i].type_no != -1) {
-               if(!strnicmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) {
+               if(!strncasecmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) {
                        sisfb_crt2type = sis_crt2type[i].type_no;
                        sisfb_tvplug = sis_crt2type[i].tvplug_no;
                        sisfb_crt2flags = sis_crt2type[i].flags;
@@ -289,7 +289,7 @@ sisfb_search_tvstd(const char *name)
                return;
 
        while(sis_tvtype[i].type_no != -1) {
-               if(!strnicmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) {
+               if(!strncasecmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) {
                        sisfb_tvstd = sis_tvtype[i].type_no;
                        break;
                }
@@ -308,12 +308,12 @@ sisfb_search_specialtiming(const char *name)
        if(name == NULL)
                return;
 
-       if(!strnicmp(name, "none", 4)) {
+       if(!strncasecmp(name, "none", 4)) {
                sisfb_specialtiming = CUT_FORCENONE;
                printk(KERN_DEBUG "sisfb: Special timing disabled\n");
        } else {
                while(mycustomttable[i].chipID != 0) {
-                       if(!strnicmp(name,mycustomttable[i].optionName,
+                       if(!strncasecmp(name,mycustomttable[i].optionName,
                           strlen(mycustomttable[i].optionName))) {
                                sisfb_specialtiming = mycustomttable[i].SpecialID;
                                found = true;
@@ -3952,68 +3952,68 @@ static int __init sisfb_setup(char *options)
 
                if(!(*this_opt)) continue;
 
-               if(!strnicmp(this_opt, "off", 3)) {
+               if(!strncasecmp(this_opt, "off", 3)) {
                        sisfb_off = 1;
-               } else if(!strnicmp(this_opt, "forcecrt2type:", 14)) {
+               } else if(!strncasecmp(this_opt, "forcecrt2type:", 14)) {
                        /* Need to check crt2 type first for fstn/dstn */
                        sisfb_search_crt2type(this_opt + 14);
-               } else if(!strnicmp(this_opt, "tvmode:",7)) {
+               } else if(!strncasecmp(this_opt, "tvmode:",7)) {
                        sisfb_search_tvstd(this_opt + 7);
-               } else if(!strnicmp(this_opt, "tvstandard:",11)) {
+               } else if(!strncasecmp(this_opt, "tvstandard:",11)) {
                        sisfb_search_tvstd(this_opt + 11);
-               } else if(!strnicmp(this_opt, "mode:", 5)) {
+               } else if(!strncasecmp(this_opt, "mode:", 5)) {
                        sisfb_search_mode(this_opt + 5, false);
-               } else if(!strnicmp(this_opt, "vesa:", 5)) {
+               } else if(!strncasecmp(this_opt, "vesa:", 5)) {
                        sisfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0), false);
-               } else if(!strnicmp(this_opt, "rate:", 5)) {
+               } else if(!strncasecmp(this_opt, "rate:", 5)) {
                        sisfb_parm_rate = simple_strtoul(this_opt + 5, NULL, 0);
-               } else if(!strnicmp(this_opt, "forcecrt1:", 10)) {
+               } else if(!strncasecmp(this_opt, "forcecrt1:", 10)) {
                        sisfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
-               } else if(!strnicmp(this_opt, "mem:",4)) {
+               } else if(!strncasecmp(this_opt, "mem:",4)) {
                        sisfb_parm_mem = simple_strtoul(this_opt + 4, NULL, 0);
-               } else if(!strnicmp(this_opt, "pdc:", 4)) {
+               } else if(!strncasecmp(this_opt, "pdc:", 4)) {
                        sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
-               } else if(!strnicmp(this_opt, "pdc1:", 5)) {
+               } else if(!strncasecmp(this_opt, "pdc1:", 5)) {
                        sisfb_pdca = simple_strtoul(this_opt + 5, NULL, 0);
-               } else if(!strnicmp(this_opt, "noaccel", 7)) {
+               } else if(!strncasecmp(this_opt, "noaccel", 7)) {
                        sisfb_accel = 0;
-               } else if(!strnicmp(this_opt, "accel", 5)) {
+               } else if(!strncasecmp(this_opt, "accel", 5)) {
                        sisfb_accel = -1;
-               } else if(!strnicmp(this_opt, "noypan", 6)) {
+               } else if(!strncasecmp(this_opt, "noypan", 6)) {
                        sisfb_ypan = 0;
-               } else if(!strnicmp(this_opt, "ypan", 4)) {
+               } else if(!strncasecmp(this_opt, "ypan", 4)) {
                        sisfb_ypan = -1;
-               } else if(!strnicmp(this_opt, "nomax", 5)) {
+               } else if(!strncasecmp(this_opt, "nomax", 5)) {
                        sisfb_max = 0;
-               } else if(!strnicmp(this_opt, "max", 3)) {
+               } else if(!strncasecmp(this_opt, "max", 3)) {
                        sisfb_max = -1;
-               } else if(!strnicmp(this_opt, "userom:", 7)) {
+               } else if(!strncasecmp(this_opt, "userom:", 7)) {
                        sisfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
-               } else if(!strnicmp(this_opt, "useoem:", 7)) {
+               } else if(!strncasecmp(this_opt, "useoem:", 7)) {
                        sisfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
-               } else if(!strnicmp(this_opt, "nocrt2rate", 10)) {
+               } else if(!strncasecmp(this_opt, "nocrt2rate", 10)) {
                        sisfb_nocrt2rate = 1;
-               } else if(!strnicmp(this_opt, "scalelcd:", 9)) {
+               } else if(!strncasecmp(this_opt, "scalelcd:", 9)) {
                        unsigned long temp = 2;
                        temp = simple_strtoul(this_opt + 9, NULL, 0);
                        if((temp == 0) || (temp == 1)) {
                           sisfb_scalelcd = temp ^ 1;
                        }
-               } else if(!strnicmp(this_opt, "tvxposoffset:", 13)) {
+               } else if(!strncasecmp(this_opt, "tvxposoffset:", 13)) {
                        int temp = 0;
                        temp = (int)simple_strtol(this_opt + 13, NULL, 0);
                        if((temp >= -32) && (temp <= 32)) {
                           sisfb_tvxposoffset = temp;
                        }
-               } else if(!strnicmp(this_opt, "tvyposoffset:", 13)) {
+               } else if(!strncasecmp(this_opt, "tvyposoffset:", 13)) {
                        int temp = 0;
                        temp = (int)simple_strtol(this_opt + 13, NULL, 0);
                        if((temp >= -32) && (temp <= 32)) {
                           sisfb_tvyposoffset = temp;
                        }
-               } else if(!strnicmp(this_opt, "specialtiming:", 14)) {
+               } else if(!strncasecmp(this_opt, "specialtiming:", 14)) {
                        sisfb_search_specialtiming(this_opt + 14);
-               } else if(!strnicmp(this_opt, "lvdshl:", 7)) {
+               } else if(!strncasecmp(this_opt, "lvdshl:", 7)) {
                        int temp = 4;
                        temp = simple_strtoul(this_opt + 7, NULL, 0);
                        if((temp >= 0) && (temp <= 3)) {
@@ -4022,9 +4022,9 @@ static int __init sisfb_setup(char *options)
                } else if(this_opt[0] >= '0' && this_opt[0] <= '9') {
                        sisfb_search_mode(this_opt, true);
 #if !defined(__i386__) && !defined(__x86_64__)
-               } else if(!strnicmp(this_opt, "resetcard", 9)) {
+               } else if(!strncasecmp(this_opt, "resetcard", 9)) {
                        sisfb_resetcard = 1;
-               } else if(!strnicmp(this_opt, "videoram:", 9)) {
+               } else if(!strncasecmp(this_opt, "videoram:", 9)) {
                        sisfb_videoram = simple_strtoul(this_opt + 9, NULL, 0);
 #endif
                } else {
index c2c8eb668784f08766444b1cabb159c37c92f455..9e74e8fbe074015c7ee149104edf6826424a87a3 100644 (file)
@@