]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge remote-tracking branch 'regulator/topic/tps65023' into regulator-next
authorMark Brown <broonie@linaro.org>
Wed, 23 Oct 2013 11:18:57 +0000 (12:18 +0100)
committerMark Brown <broonie@linaro.org>
Wed, 23 Oct 2013 11:18:57 +0000 (12:18 +0100)
204 files changed:
Documentation/ABI/stable/sysfs-bus-usb
Documentation/ABI/testing/sysfs-devices-power
Documentation/ABI/testing/sysfs-power
Documentation/acpi/dsdt-override.txt
Documentation/devicetree/bindings/memory.txt [deleted file]
Documentation/devicetree/bindings/regulator/as3722-regulator.txt [new file with mode: 0644]
Documentation/devicetree/bindings/regulator/da9210.txt [new file with mode: 0644]
Documentation/devicetree/bindings/regulator/palmas-pmic.txt
Documentation/devicetree/bindings/regulator/regulator.txt
Documentation/driver-model/devres.txt
MAINTAINERS
Makefile
arch/arm/common/mcpm_entry.c
arch/arm/common/sharpsl_param.c
arch/arm/include/asm/Kbuild
arch/arm/include/asm/mcpm.h
arch/arm/include/asm/syscall.h
arch/arm/kernel/head.S
arch/arm/mach-s3c64xx/mach-crag6410.c
arch/arm/mm/dma-mapping.c
arch/arm/mm/init.c
arch/x86/Kconfig
arch/x86/kernel/apic/x2apic_uv_x.c
arch/x86/kernel/kvm.c
arch/x86/xen/smp.c
block/partitions/efi.c
drivers/acpi/Kconfig
drivers/acpi/device_pm.c
drivers/acpi/power.c
drivers/acpi/scan.c
drivers/ata/libata-acpi.c
drivers/ata/libata-scsi.c
drivers/ata/libata.h
drivers/base/memory.c
drivers/char/tpm/xen-tpmfront.c
drivers/cpufreq/intel_pstate.c
drivers/cpufreq/s3c64xx-cpufreq.c
drivers/gpio/gpio-lynxpoint.c
drivers/gpio/gpiolib.c
drivers/iio/frequency/adf4350.c
drivers/iio/industrialio-buffer.c
drivers/infiniband/hw/amso1100/c2_ae.c
drivers/infiniband/hw/mlx5/main.c
drivers/infiniband/hw/mlx5/mr.c
drivers/infiniband/hw/mlx5/qp.c
drivers/infiniband/hw/mlx5/srq.c
drivers/infiniband/hw/mthca/mthca_eq.c
drivers/infiniband/hw/ocrdma/ocrdma_hw.c
drivers/infiniband/hw/ocrdma/ocrdma_main.c
drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
drivers/md/dm-snap-persistent.c
drivers/mfd/arizona-core.c
drivers/mfd/mfd-core.c
drivers/net/ethernet/mellanox/mlx5/core/cmd.c
drivers/net/ethernet/mellanox/mlx5/core/eq.c
drivers/net/ethernet/mellanox/mlx5/core/main.c
drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c
drivers/of/Kconfig
drivers/of/Makefile
drivers/of/base.c
drivers/of/fdt.c
drivers/of/of_reserved_mem.c [deleted file]
drivers/of/platform.c
drivers/pci/hotplug/acpiphp_glue.c
drivers/regulator/88pm800.c
drivers/regulator/88pm8607.c
drivers/regulator/Kconfig
drivers/regulator/Makefile
drivers/regulator/aat2870-regulator.c
drivers/regulator/ab3100.c
drivers/regulator/ab8500-ext.c
drivers/regulator/ad5398.c
drivers/regulator/anatop-regulator.c
drivers/regulator/arizona-ldo1.c
drivers/regulator/arizona-micsupp.c
drivers/regulator/as3711-regulator.c
drivers/regulator/as3722-regulator.c [new file with mode: 0644]
drivers/regulator/core.c
drivers/regulator/da903x.c
drivers/regulator/da9052-regulator.c
drivers/regulator/da9055-regulator.c
drivers/regulator/da9063-regulator.c
drivers/regulator/da9210-regulator.c
drivers/regulator/devres.c [new file with mode: 0644]
drivers/regulator/fan53555.c
drivers/regulator/fixed.c
drivers/regulator/gpio-regulator.c
drivers/regulator/helpers.c
drivers/regulator/internal.h [new file with mode: 0644]
drivers/regulator/isl6271a-regulator.c
drivers/regulator/lp3971.c
drivers/regulator/lp872x.c
drivers/regulator/lp8788-buck.c
drivers/regulator/lp8788-ldo.c
drivers/regulator/max1586.c
drivers/regulator/max77686.c
drivers/regulator/max77693.c
drivers/regulator/max8649.c
drivers/regulator/max8660.c
drivers/regulator/max8907-regulator.c
drivers/regulator/max8925-regulator.c
drivers/regulator/max8973-regulator.c
drivers/regulator/max8997.c
drivers/regulator/max8998.c
drivers/regulator/mc13783-regulator.c
drivers/regulator/mc13892-regulator.c
drivers/regulator/of_regulator.c
drivers/regulator/palmas-regulator.c
drivers/regulator/pcap-regulator.c
drivers/regulator/pcf50633-regulator.c
drivers/regulator/rc5t583-regulator.c
drivers/regulator/s2mps11.c
drivers/regulator/s5m8767.c
drivers/regulator/stw481x-vmmc.c [new file with mode: 0644]
drivers/regulator/ti-abb-regulator.c
drivers/regulator/tps51632-regulator.c
drivers/regulator/tps6105x-regulator.c
drivers/regulator/tps62360-regulator.c
drivers/regulator/tps65023-regulator.c
drivers/regulator/tps6507x-regulator.c
drivers/regulator/tps65090-regulator.c
drivers/regulator/tps65217-regulator.c
drivers/regulator/tps6524x-regulator.c
drivers/regulator/tps6586x-regulator.c
drivers/regulator/tps65910-regulator.c
drivers/regulator/tps65912-regulator.c
drivers/regulator/tps80031-regulator.c
drivers/regulator/twl-regulator.c
drivers/regulator/vexpress.c
drivers/regulator/wm831x-dcdc.c
drivers/regulator/wm831x-isink.c
drivers/regulator/wm831x-ldo.c
drivers/regulator/wm8350-regulator.c
drivers/regulator/wm8400-regulator.c
drivers/regulator/wm8994-regulator.c
drivers/tty/serial/imx.c
drivers/tty/serial/vt8500_serial.c
drivers/usb/chipidea/host.c
drivers/usb/core/quirks.c
drivers/usb/host/pci-quirks.c
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
drivers/usb/misc/Kconfig
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_core.h
drivers/usb/musb/musb_gadget.c
drivers/usb/musb/musb_virthub.c
drivers/usb/serial/option.c
drivers/usb/serial/ti_usb_3410_5052.c
drivers/usb/storage/scsiglue.c
drivers/usb/storage/unusual_devs.h
drivers/vfio/vfio_iommu_type1.c
drivers/w1/w1.c
fs/btrfs/inode.c
fs/buffer.c
fs/cifs/cifsfs.c
fs/cifs/cifspdu.h
fs/cifs/cifssmb.c
fs/cifs/netmisc.c
fs/cifs/sess.c
fs/cifs/smb2pdu.c
fs/cifs/smbfsctl.h
fs/cifs/transport.c
fs/ext3/namei.c
fs/ext4/namei.c
fs/proc/inode.c
fs/proc/task_mmu.c
include/acpi/acpi_bus.h
include/linux/memcontrol.h
include/linux/mfd/core.h
include/linux/mlx5/device.h
include/linux/mlx5/driver.h
include/linux/of_reserved_mem.h [deleted file]
include/linux/regulator/consumer.h
include/linux/regulator/driver.h
include/linux/regulator/machine.h
include/linux/sched.h
include/linux/usb/usb_phy_gen_xceiv.h
include/linux/usb_usual.h
ipc/sem.c
ipc/util.c
lib/percpu-refcount.c
mm/filemap.c
mm/huge_memory.c
mm/hugetlb.c
mm/memcontrol.c
mm/memory.c
mm/migrate.c
mm/mprotect.c
mm/mremap.c
mm/oom_kill.c
mm/page-writeback.c
mm/slab_common.c
mm/swapfile.c
mm/vmscan.c
mm/zswap.c
security/apparmor/apparmorfs.c
security/apparmor/policy.c
sound/pci/hda/hda_generic.c
sound/pci/rme9652/hdsp.c
sound/usb/usx2y/us122l.c
tools/testing/selftests/timers/posix_timers.c

index 2be603c52a240fa55f1a630d4f3567cc9c134d19..a6b68572474062bf04329a434cb27bbf825d19b8 100644 (file)
@@ -37,8 +37,8 @@ Description:
                that the USB device has been connected to the machine.  This
                file is read-only.
 Users:
-               PowerTOP <power@bughost.org>
-               http://www.lesswatts.org/projects/powertop/
+               PowerTOP <powertop@lists.01.org>
+               https://01.org/powertop/
 
 What:          /sys/bus/usb/device/.../power/active_duration
 Date:          January 2008
@@ -57,8 +57,8 @@ Description:
                will give an integer percentage.  Note that this does not
                account for counter wrap.
 Users:
-               PowerTOP <power@bughost.org>
-               http://www.lesswatts.org/projects/powertop/
+               PowerTOP <powertop@lists.01.org>
+               https://01.org/powertop/
 
 What:          /sys/bus/usb/devices/<busnum>-<port[.port]>...:<config num>-<interface num>/supports_autosuspend
 Date:          January 2008
index 9d43e76708413bdf6b3d25a0b1179714b06680ba..efe449bdf811db7a1c9f74f38a0371d2c0dd692e 100644 (file)
@@ -1,6 +1,6 @@
 What:          /sys/devices/.../power/
 Date:          January 2009
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/devices/.../power directory contains attributes
                allowing the user space to check and modify some power
@@ -8,7 +8,7 @@ Description:
 
 What:          /sys/devices/.../power/wakeup
 Date:          January 2009
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/devices/.../power/wakeup attribute allows the user
                space to check if the device is enabled to wake up the system
@@ -34,7 +34,7 @@ Description:
 
 What:          /sys/devices/.../power/control
 Date:          January 2009
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/devices/.../power/control attribute allows the user
                space to control the run-time power management of the device.
@@ -53,7 +53,7 @@ Description:
 
 What:          /sys/devices/.../power/async
 Date:          January 2009
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/devices/.../async attribute allows the user space to
                enable or diasble the device's suspend and resume callbacks to
@@ -79,7 +79,7 @@ Description:
 
 What:          /sys/devices/.../power/wakeup_count
 Date:          September 2010
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/devices/.../wakeup_count attribute contains the number
                of signaled wakeup events associated with the device.  This
@@ -88,7 +88,7 @@ Description:
 
 What:          /sys/devices/.../power/wakeup_active_count
 Date:          September 2010
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/devices/.../wakeup_active_count attribute contains the
                number of times the processing of wakeup events associated with
@@ -98,7 +98,7 @@ Description:
 
 What:          /sys/devices/.../power/wakeup_abort_count
 Date:          February 2012
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/devices/.../wakeup_abort_count attribute contains the
                number of times the processing of a wakeup event associated with
@@ -109,7 +109,7 @@ Description:
 
 What:          /sys/devices/.../power/wakeup_expire_count
 Date:          February 2012
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/devices/.../wakeup_expire_count attribute contains the
                number of times a wakeup event associated with the device has
@@ -119,7 +119,7 @@ Description:
 
 What:          /sys/devices/.../power/wakeup_active
 Date:          September 2010
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/devices/.../wakeup_active attribute contains either 1,
                or 0, depending on whether or not a wakeup event associated with
@@ -129,7 +129,7 @@ Description:
 
 What:          /sys/devices/.../power/wakeup_total_time_ms
 Date:          September 2010
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/devices/.../wakeup_total_time_ms attribute contains
                the total time of processing wakeup events associated with the
@@ -139,7 +139,7 @@ Description:
 
 What:          /sys/devices/.../power/wakeup_max_time_ms
 Date:          September 2010
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/devices/.../wakeup_max_time_ms attribute contains
                the maximum time of processing a single wakeup event associated
@@ -149,7 +149,7 @@ Description:
 
 What:          /sys/devices/.../power/wakeup_last_time_ms
 Date:          September 2010
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/devices/.../wakeup_last_time_ms attribute contains
                the value of the monotonic clock corresponding to the time of
@@ -160,7 +160,7 @@ Description:
 
 What:          /sys/devices/.../power/wakeup_prevent_sleep_time_ms
 Date:          February 2012
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/devices/.../wakeup_prevent_sleep_time_ms attribute
                contains the total time the device has been preventing
@@ -189,7 +189,7 @@ Description:
 
 What:          /sys/devices/.../power/pm_qos_latency_us
 Date:          March 2012
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/devices/.../power/pm_qos_resume_latency_us attribute
                contains the PM QoS resume latency limit for the given device,
@@ -207,7 +207,7 @@ Description:
 
 What:          /sys/devices/.../power/pm_qos_no_power_off
 Date:          September 2012
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/devices/.../power/pm_qos_no_power_off attribute
                is used for manipulating the PM QoS "no power off" flag.  If
@@ -222,7 +222,7 @@ Description:
 
 What:          /sys/devices/.../power/pm_qos_remote_wakeup
 Date:          September 2012
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/devices/.../power/pm_qos_remote_wakeup attribute
                is used for manipulating the PM QoS "remote wakeup required"
index 217772615d0288f996e05cc128b98c9a40d95042..205a7387844106804de496ec9b3a8c372b725977 100644 (file)
@@ -1,6 +1,6 @@
 What:          /sys/power/
 Date:          August 2006
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/power directory will contain files that will
                provide a unified interface to the power management
@@ -8,7 +8,7 @@ Description:
 
 What:          /sys/power/state
 Date:          August 2006
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/power/state file controls the system power state.
                Reading from this file returns what states are supported,
@@ -22,7 +22,7 @@ Description:
 
 What:          /sys/power/disk
 Date:          September 2006
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/power/disk file controls the operating mode of the
                suspend-to-disk mechanism.  Reading from this file returns
@@ -67,7 +67,7 @@ Description:
 
 What:          /sys/power/image_size
 Date:          August 2006
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/power/image_size file controls the size of the image
                created by the suspend-to-disk mechanism.  It can be written a
@@ -84,7 +84,7 @@ Description:
 
 What:          /sys/power/pm_trace
 Date:          August 2006
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/power/pm_trace file controls the code which saves the
                last PM event point in the RTC across reboots, so that you can
@@ -133,7 +133,7 @@ Description:
 
 What:          /sys/power/pm_async
 Date:          January 2009
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/power/pm_async file controls the switch allowing the
                user space to enable or disable asynchronous suspend and resume
@@ -146,7 +146,7 @@ Description:
 
 What:          /sys/power/wakeup_count
 Date:          July 2010
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/power/wakeup_count file allows user space to put the
                system into a sleep state while taking into account the
@@ -161,7 +161,7 @@ Description:
 
 What:          /sys/power/reserved_size
 Date:          May 2011
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/power/reserved_size file allows user space to control
                the amount of memory reserved for allocations made by device
@@ -175,7 +175,7 @@ Description:
 
 What:          /sys/power/autosleep
 Date:          April 2012
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/power/autosleep file can be written one of the strings
                returned by reads from /sys/power/state.  If that happens, a
@@ -192,7 +192,7 @@ Description:
 
 What:          /sys/power/wake_lock
 Date:          February 2012
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/power/wake_lock file allows user space to create
                wakeup source objects and activate them on demand (if one of
@@ -219,7 +219,7 @@ Description:
 
 What:          /sys/power/wake_unlock
 Date:          February 2012
-Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Contact:       Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
                The /sys/power/wake_unlock file allows user space to deactivate
                wakeup sources created with the help of /sys/power/wake_lock.
index febbb1ba4d2317b984e7217796ac39151f867531..784841caa6e63824ff2503351fb12e682f01e3b3 100644 (file)
@@ -4,4 +4,4 @@ CONFIG_ACPI_CUSTOM_DSDT builds the image into the kernel.
 
 When to use this method is described in detail on the
 Linux/ACPI home page:
-http://www.lesswatts.org/projects/acpi/overridingDSDT.php
+https://01.org/linux-acpi/documentation/overriding-dsdt
diff --git a/Documentation/devicetree/bindings/memory.txt b/Documentation/devicetree/bindings/memory.txt
deleted file mode 100644 (file)
index eb24693..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-*** Memory binding ***
-
-The /memory node provides basic information about the address and size
-of the physical memory. This node is usually filled or updated by the
-bootloader, depending on the actual memory configuration of the given
-hardware.
-
-The memory layout is described by the following node:
-
-/ {
-       #address-cells = <(n)>;
-       #size-cells = <(m)>;
-       memory {
-               device_type = "memory";
-               reg =  <(baseaddr1) (size1)
-                       (baseaddr2) (size2)
-                       ...
-                       (baseaddrN) (sizeN)>;
-       };
-       ...
-};
-
-A memory node follows the typical device tree rules for "reg" property:
-n:             number of cells used to store base address value
-m:             number of cells used to store size value
-baseaddrX:     defines a base address of the defined memory bank
-sizeX:         the size of the defined memory bank
-
-
-More than one memory bank can be defined.
-
-
-*** Reserved memory regions ***
-
-In /memory/reserved-memory node one can create child nodes describing
-particular reserved (excluded from normal use) memory regions. Such
-memory regions are usually designed for the special usage by various
-device drivers. A good example are contiguous memory allocations or
-memory sharing with other operating system on the same hardware board.
-Those special memory regions might depend on the board configuration and
-devices used on the target system.
-
-Parameters for each memory region can be encoded into the device tree
-with the following convention:
-
-[(label):] (name) {
-       compatible = "linux,contiguous-memory-region", "reserved-memory-region";
-       reg = <(address) (size)>;
-       (linux,default-contiguous-region);
-};
-
-compatible:    one or more of:
-       - "linux,contiguous-memory-region" - enables binding of this
-         region to Contiguous Memory Allocator (special region for
-         contiguous memory allocations, shared with movable system
-         memory, Linux kernel-specific).
-       - "reserved-memory-region" - compatibility is defined, given
-         region is assigned for exclusive usage for by the respective
-         devices.
-
-reg:   standard property defining the base address and size of
-       the memory region
-
-linux,default-contiguous-region: property indicating that the region
-       is the default region for all contiguous memory
-       allocations, Linux specific (optional)
-
-It is optional to specify the base address, so if one wants to use
-autoconfiguration of the base address, '0' can be specified as a base
-address in the 'reg' property.
-
-The /memory/reserved-memory node must contain the same #address-cells
-and #size-cells value as the root node.
-
-
-*** Device node's properties ***
-
-Once regions in the /memory/reserved-memory node have been defined, they
-may be referenced by other device nodes. Bindings that wish to reference
-memory regions should explicitly document their use of the following
-property:
-
-memory-region = <&phandle_to_defined_region>;
-
-This property indicates that the device driver should use the memory
-region pointed by the given phandle.
-
-
-*** Example ***
-
-This example defines a memory consisting of 4 memory banks. 3 contiguous
-regions are defined for Linux kernel, one default of all device drivers
-(named contig_mem, placed at 0x72000000, 64MiB), one dedicated to the
-framebuffer device (labelled display_mem, placed at 0x78000000, 8MiB)
-and one for multimedia processing (labelled multimedia_mem, placed at
-0x77000000, 64MiB). 'display_mem' region is then assigned to fb@12300000
-device for DMA memory allocations (Linux kernel drivers will use CMA is
-available or dma-exclusive usage otherwise). 'multimedia_mem' is
-assigned to scaler@12500000 and codec@12600000 devices for contiguous
-memory allocations when CMA driver is enabled.
-
-The reason for creating a separate region for framebuffer device is to
-match the framebuffer base address to the one configured by bootloader,
-so once Linux kernel drivers starts no glitches on the displayed boot
-logo appears. Scaller and codec drivers should share the memory
-allocations.
-
-/ {
-       #address-cells = <1>;
-       #size-cells = <1>;
-
-       /* ... */
-
-       memory {
-               reg =  <0x40000000 0x10000000
-                       0x50000000 0x10000000
-                       0x60000000 0x10000000
-                       0x70000000 0x10000000>;
-
-               reserved-memory {
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-
-                       /*
-                        * global autoconfigured region for contiguous allocations
-                        * (used only with Contiguous Memory Allocator)
-                        */
-                       contig_region@0 {
-                               compatible = "linux,contiguous-memory-region";
-                               reg = <0x0 0x4000000>;
-                               linux,default-contiguous-region;
-                       };
-
-                       /*
-                        * special region for framebuffer
-                        */
-                       display_region: region@78000000 {
-                               compatible = "linux,contiguous-memory-region", "reserved-memory-region";
-                               reg = <0x78000000 0x800000>;
-                       };
-
-                       /*
-                        * special region for multimedia processing devices
-                        */
-                       multimedia_region: region@77000000 {
-                               compatible = "linux,contiguous-memory-region";
-                               reg = <0x77000000 0x4000000>;
-                       };
-               };
-       };
-
-       /* ... */
-
-       fb0: fb@12300000 {
-               status = "okay";
-               memory-region = <&display_region>;
-       };
-
-       scaler: scaler@12500000 {
-               status = "okay";
-               memory-region = <&multimedia_region>;
-       };
-
-       codec: codec@12600000 {
-               status = "okay";
-               memory-region = <&multimedia_region>;
-       };
-};
diff --git a/Documentation/devicetree/bindings/regulator/as3722-regulator.txt b/Documentation/devicetree/bindings/regulator/as3722-regulator.txt
new file mode 100644 (file)
index 0000000..caad0c8
--- /dev/null
@@ -0,0 +1,91 @@
+Regulator of AMS AS3722 PMIC.
+Name of the regulator subnode must be "regulators".
+
+Optional properties:
+--------------------
+The input supply of regulators are the optional properties on the
+regulator node. The AS3722 is having 7 DCDC step-down regulators as
+sd[0-6], 10 LDOs as ldo[0-7], ldo[9-11]. The input supply of these
+regulators are provided through following properties:
+vsup-sd2-supply: Input supply for SD2.
+vsup-sd3-supply: Input supply for SD3.
+vsup-sd4-supply: Input supply for SD4.
+vsup-sd5-supply: Input supply for SD5.
+vin-ldo0-supply: Input supply for LDO0.
+vin-ldo1-6-supply: Input supply for LDO1 and LDO6.
+vin-ldo2-5-7-supply: Input supply for LDO2, LDO5 and LDO7.
+vin-ldo3-4-supply: Input supply for LDO3 and LDO4.
+vin-ldo9-10-supply: Input supply for LDO9 and LDO10.
+vin-ldo11-supply: Input supply for LDO11.
+
+Optional nodes:
+--------------
+- regulators : Must contain a sub-node per regulator from the list below.
+              Each sub-node should contain the constraints and initialization
+              information for that regulator. See regulator.txt for a
+              description of standard properties for these sub-nodes.
+              Additional custom properties  are listed below.
+              sd[0-6], ldo[0-7], ldo[9-11].
+
+              Optional sub-node properties:
+              ----------------------------
+               ams,ext-control: External control of the rail. The option of
+                       this properties will tell which external input is
+                       controlling this rail. Valid values are 0, 1, 2 ad 3.
+                       0: There is no external control of this rail.
+                       1: Rail is controlled by ENABLE1 input pin.
+                       2: Rail is controlled by ENABLE2 input pin.
+                       3: Rail is controlled by ENABLE3 input pin.
+               ams,enable-tracking: Enable tracking with SD1, only supported
+                       by LDO3.
+
+Example:
+-------
+       ams3722: ams3722 {
+               compatible = "ams,as3722";
+               reg = <0x40>;
+               ...
+
+               regulators {
+                       vsup-sd2-supply = <...>;
+                       ...
+
+                       sd0 {
+                               regulator-name = "vdd_cpu";
+                               regulator-min-microvolt = <700000>;
+                               regulator-max-microvolt = <1400000>;
+                               regulator-always-on;
+                               ams,ext-control = <2>;
+                       };
+
+                       sd1 {
+                               regulator-name = "vdd_core";
+                               regulator-min-microvolt = <700000>;
+                               regulator-max-microvolt = <1400000>;
+                               regulator-always-on;
+                               ams,ext-control = <1>;
+                       };
+
+                       sd2 {
+                               regulator-name = "vddio_ddr";
+                               regulator-min-microvolt = <1350000>;
+                               regulator-max-microvolt = <1350000>;
+                               regulator-always-on;
+                       };
+
+                       sd4 {
+                               regulator-name = "avdd-hdmi-pex";
+                               regulator-min-microvolt = <1050000>;
+                               regulator-max-microvolt = <1050000>;
+                               regulator-always-on;
+                       };
+
+                       sd5 {
+                               regulator-name = "vdd-1v8";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                       };
+                       ....
+               };
+       };
diff --git a/Documentation/devicetree/bindings/regulator/da9210.txt b/Documentation/devicetree/bindings/regulator/da9210.txt
new file mode 100644 (file)
index 0000000..f120f22
--- /dev/null
@@ -0,0 +1,21 @@
+* Dialog Semiconductor DA9210 Voltage Regulator
+
+Required properties:
+
+- compatible:  must be "diasemi,da9210"
+- reg:         the i2c slave address of the regulator. It should be 0x68.
+
+Any standard regulator properties can be used to configure the single da9210
+DCDC.
+
+Example:
+
+       da9210@68 {
+               compatible = "diasemi,da9210";
+               reg = <0x68>;
+
+               regulator-min-microvolt = <900000>;
+               regulator-max-microvolt = <1000000>;
+               regulator-boot-on;
+               regulator-always-on;
+       };
index 875639ae0606e1e6637cacd9ef35dfde9ec0399a..42e6b6bc48ff3b5cfe383cf7598ffb42bee5e286 100644 (file)
@@ -26,11 +26,17 @@ Optional nodes:
 
               For ti,palmas-pmic - smps12, smps123, smps3 depending on OTP,
               smps45, smps457, smps7 depending on variant, smps6, smps[8-9],
-              smps10_out2, smps10_out1, do[1-9], ldoln, ldousb.
+              smps10_out2, smps10_out1, ldo[1-9], ldoln, ldousb.
 
               Optional sub-node properties:
               ti,warm-reset - maintain voltage during warm reset(boolean)
-              ti,roof-floor - control voltage selection by pin(boolean)
+              ti,roof-floor - This takes as optional argument on platform supporting
+              the rail from desired external control. If there is no argument then
+              it will be assume that it is controlled by NSLEEP pin.
+              The valid value for external pins are:
+                       ENABLE1 then 1,
+                       ENABLE2 then 2 or
+                       NSLEEP then 3.
               ti,mode-sleep - mode to adopt in pmic sleep 0 - off, 1 - auto,
               2 - eco, 3 - forced pwm
               ti,smps-range - OTP has the wrong range set for the hardware so override
@@ -61,7 +67,7 @@ pmic {
                        regulator-always-on;
                        regulator-boot-on;
                        ti,warm-reset;
-                       ti,roof-floor;
+                       ti,roof-floor = <1>; /* ENABLE1 control */
                        ti,mode-sleep = <0>;
                        ti,smps-range = <1>;
                };
index 2bd8f09787659269bb03847b3517cff2b52cfca9..e2c7f1e7251a3a16c922c50d10f8b8f50ee750cb 100644 (file)
@@ -14,6 +14,11 @@ Optional properties:
 - regulator-ramp-delay: ramp delay for regulator(in uV/uS)
   For hardwares which support disabling ramp rate, it should be explicitly
   intialised to zero (regulator-ramp-delay = <0>) for disabling ramp delay.
+- regulator-enable-ramp-delay: The time taken, in microseconds, for the supply
+  rail to reach the target voltage, plus/minus whatever tolerance the board
+  design requires. This property describes the total system ramp time
+  required due to the combination of internal ramping of the regulator itself,
+  and board design issues such as trace capacitance and load on the supply.
 
 Deprecated properties:
 - regulator-compatible: If a regulator chip contains multiple
index fcb34a5697eaa4ec2c44a46791b711d5a78f1c7b..3d9c2a766230a5d7d24164675a4bee3b4e67dd67 100644 (file)
@@ -283,6 +283,7 @@ REGULATOR
   devm_regulator_get()
   devm_regulator_put()
   devm_regulator_bulk_get()
+  devm_regulator_register()
 
 CLOCK
   devm_clk_get()
index 8a0cbf3cf2c8c01c5be662eef372eff4060daffc..a7c34ef3509d5f199511e0547ddba1e88b9a3be9 100644 (file)
@@ -237,11 +237,11 @@ F:        drivers/platform/x86/acer-wmi.c
 
 ACPI
 M:     Len Brown <lenb@kernel.org>
-M:     Rafael J. Wysocki <rjw@sisk.pl>
+M:     Rafael J. Wysocki <rjw@rjwysocki.net>
 L:     linux-acpi@vger.kernel.org
-W:     http://www.lesswatts.org/projects/acpi/
-Q:     http://patchwork.kernel.org/project/linux-acpi/list/
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux
+W:     https://01.org/linux-acpi
+Q:     https://patchwork.kernel.org/project/linux-acpi/list/
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
 S:     Supported
 F:     drivers/acpi/
 F:     drivers/pnp/pnpacpi/
@@ -256,21 +256,21 @@ F:        drivers/pci/*/*/*acpi*
 ACPI FAN DRIVER
 M:     Zhang Rui <rui.zhang@intel.com>
 L:     linux-acpi@vger.kernel.org
-W:     http://www.lesswatts.org/projects/acpi/
+W:     https://01.org/linux-acpi
 S:     Supported
 F:     drivers/acpi/fan.c
 
 ACPI THERMAL DRIVER
 M:     Zhang Rui <rui.zhang@intel.com>
 L:     linux-acpi@vger.kernel.org
-W:     http://www.lesswatts.org/projects/acpi/
+W:     https://01.org/linux-acpi
 S:     Supported
 F:     drivers/acpi/*thermal*
 
 ACPI VIDEO DRIVER
 M:     Zhang Rui <rui.zhang@intel.com>
 L:     linux-acpi@vger.kernel.org
-W:     http://www.lesswatts.org/projects/acpi/
+W:     https://01.org/linux-acpi
 S:     Supported
 F:     drivers/acpi/video.c
 
@@ -2300,7 +2300,7 @@ S:        Maintained
 F:     drivers/net/ethernet/ti/cpmac.c
 
 CPU FREQUENCY DRIVERS
-M:     Rafael J. Wysocki <rjw@sisk.pl>
+M:     Rafael J. Wysocki <rjw@rjwysocki.net>
 M:     Viresh Kumar <viresh.kumar@linaro.org>
 L:     cpufreq@vger.kernel.org
 L:     linux-pm@vger.kernel.org
@@ -2331,7 +2331,7 @@ S:      Maintained
 F:      drivers/cpuidle/cpuidle-big_little.c
 
 CPUIDLE DRIVERS
-M:     Rafael J. Wysocki <rjw@sisk.pl>
+M:     Rafael J. Wysocki <rjw@rjwysocki.net>
 M:     Daniel Lezcano <daniel.lezcano@linaro.org>
 L:     linux-pm@vger.kernel.org
 S:     Maintained
@@ -3553,7 +3553,7 @@ F:        fs/freevxfs/
 
 FREEZER
 M:     Pavel Machek <pavel@ucw.cz>
-M:     "Rafael J. Wysocki" <rjw@sisk.pl>
+M:     "Rafael J. Wysocki" <rjw@rjwysocki.net>
 L:     linux-pm@vger.kernel.org
 S:     Supported
 F:     Documentation/power/freezing-of-tasks.txt
@@ -3624,6 +3624,12 @@ L:       linux-scsi@vger.kernel.org
 S:     Odd Fixes (e.g., new signatures)
 F:     drivers/scsi/fdomain.*
 
+GCOV BASED KERNEL PROFILING
+M:     Peter Oberparleiter <oberpar@linux.vnet.ibm.com>
+S:     Maintained
+F:     kernel/gcov/
+F:     Documentation/gcov.txt
+
 GDT SCSI DISK ARRAY CONTROLLER DRIVER
 M:     Achim Leubner <achim_leubner@adaptec.com>
 L:     linux-scsi@vger.kernel.org
@@ -3889,7 +3895,7 @@ F:        drivers/video/hgafb.c
 
 HIBERNATION (aka Software Suspend, aka swsusp)
 M:     Pavel Machek <pavel@ucw.cz>
-M:     "Rafael J. Wysocki" <rjw@sisk.pl>
+M:     "Rafael J. Wysocki" <rjw@rjwysocki.net>
 L:     linux-pm@vger.kernel.org
 S:     Supported
 F:     arch/x86/power/
@@ -4339,7 +4345,7 @@ F:        drivers/video/i810/
 INTEL MENLOW THERMAL DRIVER
 M:     Sujith Thomas <sujith.thomas@intel.com>
 L:     platform-driver-x86@vger.kernel.org
-W:     http://www.lesswatts.org/projects/acpi/
+W:     https://01.org/linux-acpi
 S:     Supported
 F:     drivers/platform/x86/intel_menlow.c
 
@@ -8095,7 +8101,7 @@ F:        drivers/sh/
 SUSPEND TO RAM
 M:     Len Brown <len.brown@intel.com>
 M:     Pavel Machek <pavel@ucw.cz>
-M:     "Rafael J. Wysocki" <rjw@sisk.pl>
+M:     "Rafael J. Wysocki" <rjw@rjwysocki.net>
 L:     linux-pm@vger.kernel.org
 S:     Supported
 F:     Documentation/power/
index deec08b7612b4c0d903ca6c9323eddaac6e4ea08..126321d2e6ad6a3c594280ca1102e0b25c7e4dd3 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 12
 SUBLEVEL = 0
-EXTRAVERSION = -rc5
+EXTRAVERSION = -rc6
 NAME = One Giant Leap for Frogkind
 
 # *DOCUMENTATION*
index 370236dd1a03309ee3b123e705aa80132c908427..990250965f2cfb4e4e3a984678fcf62eedbcdb8d 100644 (file)
@@ -51,7 +51,8 @@ void mcpm_cpu_power_down(void)
 {
        phys_reset_t phys_reset;
 
-       BUG_ON(!platform_ops);
+       if (WARN_ON_ONCE(!platform_ops || !platform_ops->power_down))
+               return;
        BUG_ON(!irqs_disabled());
 
        /*
@@ -93,7 +94,8 @@ void mcpm_cpu_suspend(u64 expected_residency)
 {
        phys_reset_t phys_reset;
 
-       BUG_ON(!platform_ops);
+       if (WARN_ON_ONCE(!platform_ops || !platform_ops->suspend))
+               return;
        BUG_ON(!irqs_disabled());
 
        /* Very similar to mcpm_cpu_power_down() */
index d56c932580eb201439c8a63aa401abddd157cbbf..025f6ce38596736eea2c929a211b23fd4eaf0d56 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/module.h>
 #include <linux/string.h>
 #include <asm/mach/sharpsl_param.h>
+#include <asm/memory.h>
 
 /*
  * Certain hardware parameters determined at the time of device manufacture,
  */
 #ifdef CONFIG_ARCH_SA1100
 #define PARAM_BASE     0xe8ffc000
+#define param_start(x) (void *)(x)
 #else
 #define PARAM_BASE     0xa0000a00
+#define param_start(x) __va(x)
 #endif
 #define MAGIC_CHG(a,b,c,d) ( ( d << 24 ) | ( c << 16 )  | ( b << 8 ) | a )
 
@@ -41,7 +44,7 @@ EXPORT_SYMBOL(sharpsl_param);
 
 void sharpsl_save_param(void)
 {
-       memcpy(&sharpsl_param, (void *)PARAM_BASE, sizeof(struct sharpsl_param_info));
+       memcpy(&sharpsl_param, param_start(PARAM_BASE), sizeof(struct sharpsl_param_info));
 
        if (sharpsl_param.comadj_keyword != COMADJ_MAGIC)
                sharpsl_param.comadj=-1;
index d3db39860b9cc5eb83053f99f9430b926443609c..59ceae8f3c959616851a21ba3f08ae18941146ca 100644 (file)
@@ -31,5 +31,4 @@ generic-y += termbits.h
 generic-y += termios.h
 generic-y += timex.h
 generic-y += trace_clock.h
-generic-y += types.h
 generic-y += unaligned.h
index 0f7b7620e9a554b0b4a0ba4939a60c905e0a435c..fc82a88f5b69e556e9235583364b5149b2572b66 100644 (file)
@@ -76,8 +76,11 @@ int mcpm_cpu_power_up(unsigned int cpu, unsigned int cluster);
  *
  * This must be called with interrupts disabled.
  *
- * This does not return.  Re-entry in the kernel is expected via
- * mcpm_entry_point.
+ * On success this does not return.  Re-entry in the kernel is expected
+ * via mcpm_entry_point.
+ *
+ * This will return if mcpm_platform_register() has not been called
+ * previously in which case the caller should take appropriate action.
  */
 void mcpm_cpu_power_down(void);
 
@@ -98,8 +101,11 @@ void mcpm_cpu_power_down(void);
  *
  * This must be called with interrupts disabled.
  *
- * This does not return.  Re-entry in the kernel is expected via
- * mcpm_entry_point.
+ * On success this does not return.  Re-entry in the kernel is expected
+ * via mcpm_entry_point.
+ *
+ * This will return if mcpm_platform_register() has not been called
+ * previously in which case the caller should take appropriate action.
  */
 void mcpm_cpu_suspend(u64 expected_residency);
 
index f1d96d4e8092a652aeb84f5825082a8f9064cd20..73ddd7239b33aa77d178ae1341c0c46c736a08e5 100644 (file)
@@ -57,6 +57,9 @@ static inline void syscall_get_arguments(struct task_struct *task,
                                         unsigned int i, unsigned int n,
                                         unsigned long *args)
 {
+       if (n == 0)
+               return;
+
        if (i + n > SYSCALL_MAX_ARGS) {
                unsigned long *args_bad = args + SYSCALL_MAX_ARGS - i;
                unsigned int n_bad = n + i - SYSCALL_MAX_ARGS;
@@ -81,6 +84,9 @@ static inline void syscall_set_arguments(struct task_struct *task,
                                         unsigned int i, unsigned int n,
                                         const unsigned long *args)
 {
+       if (n == 0)
+               return;
+
        if (i + n > SYSCALL_MAX_ARGS) {
                pr_warning("%s called with max args %d, handling only %d\n",
                           __func__, i + n, SYSCALL_MAX_ARGS);
index 2c7cc1e03473aee9463e86d7dbedfc999f6e51f7..476de57dcef284602e126e29e2da03465df8ff09 100644 (file)
@@ -487,7 +487,26 @@ __fixup_smp:
        mrc     p15, 0, r0, c0, c0, 5   @ read MPIDR
        and     r0, r0, #0xc0000000     @ multiprocessing extensions and
        teq     r0, #0x80000000         @ not part of a uniprocessor system?
-       moveq   pc, lr                  @ yes, assume SMP
+       bne    __fixup_smp_on_up        @ no, assume UP
+
+       @ Core indicates it is SMP. Check for Aegis SOC where a single
+       @ Cortex-A9 CPU is present but SMP operations fault.
+       mov     r4, #0x41000000
+       orr     r4, r4, #0x0000c000
+       orr     r4, r4, #0x00000090
+       teq     r3, r4                  @ Check for ARM Cortex-A9
+       movne   pc, lr                  @ Not ARM Cortex-A9,
+
+       @ If a future SoC *does* use 0x0 as the PERIPH_BASE, then the
+       @ below address check will need to be #ifdef'd or equivalent
+       @ for the Aegis platform.
+       mrc     p15, 4, r0, c15, c0     @ get SCU base address
+       teq     r0, #0x0                @ '0' on actual UP A9 hardware
+       beq     __fixup_smp_on_up       @ So its an A9 UP
+       ldr     r0, [r0, #4]            @ read SCU Config
+       and     r0, r0, #0x3            @ number of CPUs
+       teq     r0, #0x0                @ is 1?
+       movne   pc, lr
 
 __fixup_smp_on_up:
        adr     r0, 1f
index eb8e5a1aca420005fa5e0988a099e51eb8ec6f94..f27ca3b89f4c4ccca96c707d5bc179f946e63ef9 100644 (file)
@@ -310,10 +310,6 @@ static struct regulator_consumer_supply wallvdd_consumers[] = {
 
        REGULATOR_SUPPLY("SPKVDDL", "spi0.1"),
        REGULATOR_SUPPLY("SPKVDDR", "spi0.1"),
-       REGULATOR_SUPPLY("SPKVDDL", "wm5102-codec"),
-       REGULATOR_SUPPLY("SPKVDDR", "wm5102-codec"),
-       REGULATOR_SUPPLY("SPKVDDL", "wm5110-codec"),
-       REGULATOR_SUPPLY("SPKVDDR", "wm5110-codec"),
 
        REGULATOR_SUPPLY("DC1VDD", "0-0034"),
        REGULATOR_SUPPLY("DC2VDD", "0-0034"),
@@ -653,14 +649,6 @@ static struct regulator_consumer_supply pvdd_1v8_consumers[] = {
        REGULATOR_SUPPLY("DBVDD3", "spi0.1"),
        REGULATOR_SUPPLY("LDOVDD", "spi0.1"),
        REGULATOR_SUPPLY("CPVDD", "spi0.1"),
-
-       REGULATOR_SUPPLY("DBVDD2", "wm5102-codec"),
-       REGULATOR_SUPPLY("DBVDD3", "wm5102-codec"),
-       REGULATOR_SUPPLY("CPVDD", "wm5102-codec"),
-
-       REGULATOR_SUPPLY("DBVDD2", "wm5110-codec"),
-       REGULATOR_SUPPLY("DBVDD3", "wm5110-codec"),
-       REGULATOR_SUPPLY("CPVDD", "wm5110-codec"),
 };
 
 static struct regulator_init_data pvdd_1v8 = {
index f5e1a8471714cd421e2ab9dee54ae88f144316d1..1272ed202ddee97c2a9143d97afbf4bed69f0fea 100644 (file)
@@ -1232,7 +1232,8 @@ __iommu_create_mapping(struct device *dev, struct page **pages, size_t size)
                                break;
 
                len = (j - i) << PAGE_SHIFT;
-               ret = iommu_map(mapping->domain, iova, phys, len, 0);
+               ret = iommu_map(mapping->domain, iova, phys, len,
+                               IOMMU_READ|IOMMU_WRITE);
                if (ret < 0)
                        goto fail;
                iova += len;
@@ -1431,6 +1432,27 @@ static int arm_iommu_get_sgtable(struct device *dev, struct sg_table *sgt,
                                         GFP_KERNEL);
 }
 
+static int __dma_direction_to_prot(enum dma_data_direction dir)
+{
+       int prot;
+
+       switch (dir) {
+       case DMA_BIDIRECTIONAL:
+               prot = IOMMU_READ | IOMMU_WRITE;
+               break;
+       case DMA_TO_DEVICE:
+               prot = IOMMU_READ;
+               break;
+       case DMA_FROM_DEVICE:
+               prot = IOMMU_WRITE;
+               break;
+       default:
+               prot = 0;
+       }
+
+       return prot;
+}
+
 /*
  * Map a part of the scatter-gather list into contiguous io address space
  */
@@ -1444,6 +1466,7 @@ static int __map_sg_chunk(struct device *dev, struct scatterlist *sg,
        int ret = 0;
        unsigned int count;
        struct scatterlist *s;
+       int prot;
 
        size = PAGE_ALIGN(size);
        *handle = DMA_ERROR_CODE;
@@ -1460,7 +1483,9 @@ static int __map_sg_chunk(struct device *dev, struct scatterlist *sg,
                        !dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
                        __dma_page_cpu_to_dev(sg_page(s), s->offset, s->length, dir);
 
-               ret = iommu_map(mapping->domain, iova, phys, len, 0);
+               prot = __dma_direction_to_prot(dir);
+
+               ret = iommu_map(mapping->domain, iova, phys, len, prot);
                if (ret < 0)
                        goto fail;
                count += len >> PAGE_SHIFT;
@@ -1665,19 +1690,7 @@ static dma_addr_t arm_coherent_iommu_map_page(struct device *dev, struct page *p
        if (dma_addr == DMA_ERROR_CODE)
                return dma_addr;
 
-       switch (dir) {
-       case DMA_BIDIRECTIONAL:
-               prot = IOMMU_READ | IOMMU_WRITE;
-               break;
-       case DMA_TO_DEVICE:
-               prot = IOMMU_READ;
-               break;
-       case DMA_FROM_DEVICE:
-               prot = IOMMU_WRITE;
-               break;
-       default:
-               prot = 0;
-       }
+       prot = __dma_direction_to_prot(dir);
 
        ret = iommu_map(mapping->domain, dma_addr, page_to_phys(page), len, prot);
        if (ret < 0)
index febaee7ca57be76487290a2ac45c6cf74e53759c..18ec4c504abf908ac9ddca01a4458a8183c6cc95 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/nodemask.h>
 #include <linux/initrd.h>
 #include <linux/of_fdt.h>
-#include <linux/of_reserved_mem.h>
 #include <linux/highmem.h>
 #include <linux/gfp.h>
 #include <linux/memblock.h>
@@ -379,8 +378,6 @@ void __init arm_memblock_init(struct meminfo *mi,
        if (mdesc->reserve)
                mdesc->reserve();
 
-       early_init_dt_scan_reserved_mem();
-
        /*
         * reserve memory for DMA contigouos allocations,
         * must come from DMA area inside low memory
index 145d703227bf63542560df60a842d2b8aa0f1f7c..f67e839f06c845e406d81c8b2be285ced8b57448 100644 (file)
@@ -1033,6 +1033,7 @@ config X86_REBOOTFIXUPS
 
 config MICROCODE
        tristate "CPU microcode loading support"
+       depends on CPU_SUP_AMD || CPU_SUP_INTEL
        select FW_LOADER
        ---help---
 
index 1191ac1c9d2598e64d13a1419b4a7a383933ce03..a419814cea575f9e2cf183772a9e99c59e097a11 100644 (file)
@@ -113,7 +113,7 @@ static int __init early_get_pnodeid(void)
                break;
        case UV3_HUB_PART_NUMBER:
        case UV3_HUB_PART_NUMBER_X:
-               uv_min_hub_revision_id += UV3_HUB_REVISION_BASE - 1;
+               uv_min_hub_revision_id += UV3_HUB_REVISION_BASE;
                break;
        }
 
index 697b93af02ddbc0fb4461b5d853810fa250cd0a1..a0e2a8a80c94129bb3d3d47bf975ef68f98f500e 100644 (file)
@@ -775,11 +775,22 @@ void __init kvm_spinlock_init(void)
        if (!kvm_para_has_feature(KVM_FEATURE_PV_UNHALT))
                return;
 
-       printk(KERN_INFO "KVM setup paravirtual spinlock\n");
+       pv_lock_ops.lock_spinning = PV_CALLEE_SAVE(kvm_lock_spinning);
+       pv_lock_ops.unlock_kick = kvm_unlock_kick;
+}
+
+static __init int kvm_spinlock_init_jump(void)
+{
+       if (!kvm_para_available())
+               return 0;
+       if (!kvm_para_has_feature(KVM_FEATURE_PV_UNHALT))
+               return 0;
 
        static_key_slow_inc(&paravirt_ticketlocks_enabled);
+       printk(KERN_INFO "KVM setup paravirtual spinlock\n");
 
-       pv_lock_ops.lock_spinning = PV_CALLEE_SAVE(kvm_lock_spinning);
-       pv_lock_ops.unlock_kick = kvm_unlock_kick;
+       return 0;
 }
+early_initcall(kvm_spinlock_init_jump);
+
 #endif /* CONFIG_PARAVIRT_SPINLOCKS */
index d1e4777b4e75352fea33ca6a3e3d43a679e19c6d..31d04758b76f6a2da41c309e368768d4881066d0 100644 (file)
@@ -278,6 +278,15 @@ static void __init xen_smp_prepare_boot_cpu(void)
                   old memory can be recycled */
                make_lowmem_page_readwrite(xen_initial_gdt);
 
+#ifdef CONFIG_X86_32
+               /*
+                * Xen starts us with XEN_FLAT_RING1_DS, but linux code
+                * expects __USER_DS
+                */
+               loadsegment(ds, __USER_DS);
+               loadsegment(es, __USER_DS);
+#endif
+
                xen_filter_cpu_maps();
                xen_setup_vcpu_info_placement();
        }
index 1eb09ee5311b414e448b28eb26a72f7ff6bbaa1c..a8287b49d0621d1778295ad0516c8ccbf22ed0fa 100644 (file)
@@ -222,11 +222,16 @@ check_hybrid:
         * the disk size.
         *
         * Hybrid MBRs do not necessarily comply with this.
+        *
+        * Consider a bad value here to be a warning to support dd'ing
+        * an image from a smaller disk to a larger disk.
         */
        if (ret == GPT_MBR_PROTECTIVE) {
                sz = le32_to_cpu(mbr->partition_record[part].size_in_lba);
                if (sz != (uint32_t) total_sectors - 1 && sz != 0xFFFFFFFF)
-                       ret = 0;
+                       pr_debug("GPT: mbr size in lba (%u) different than whole disk (%u).\n",
+                                sz, min_t(uint32_t,
+                                          total_sectors - 1, 0xFFFFFFFF));
        }
 done:
        return ret;
index 22327e6a7236fc367313ec5acf45016d354863d4..6efe2ac6902fa635bf90a2d3e3d14728949aad5c 100644 (file)
@@ -24,7 +24,7 @@ menuconfig ACPI
          are configured, ACPI is used.
 
          The project home page for the Linux ACPI subsystem is here:
-         <http://www.lesswatts.org/projects/acpi/>
+         <https://01.org/linux-acpi>
 
          Linux support for ACPI is based on Intel Corporation's ACPI
          Component Architecture (ACPI CA).  For more information on the
@@ -123,9 +123,9 @@ config ACPI_BUTTON
        default y
        help
          This driver handles events on the power, sleep, and lid buttons.
-         A daemon reads /proc/acpi/event and perform user-defined actions
-         such as shutting down the system.  This is necessary for
-         software-controlled poweroff.
+         A daemon reads events from input devices or via netlink and
+         performs user-defined actions such as shutting down the system.
+         This is necessary for software-controlled poweroff.
 
          To compile this driver as a module, choose M here:
          the module will be called button.
index 59d3202f6b36fc197afe259b343764cb2a9621aa..a94383d1f3502ae35138e7e677df02c1d8df3d72 100644 (file)
@@ -1025,60 +1025,4 @@ void acpi_dev_pm_detach(struct device *dev, bool power_off)
        }
 }
 EXPORT_SYMBOL_GPL(acpi_dev_pm_detach);
-
-/**
- * acpi_dev_pm_add_dependent - Add physical device depending for PM.
- * @handle: Handle of ACPI device node.
- * @depdev: Device depending on that node for PM.
- */
-void acpi_dev_pm_add_dependent(acpi_handle handle, struct device *depdev)
-{
-       struct acpi_device_physical_node *dep;
-       struct acpi_device *adev;
-
-       if (!depdev || acpi_bus_get_device(handle, &adev))
-               return;
-
-       mutex_lock(&adev->physical_node_lock);
-
-       list_for_each_entry(dep, &adev->power_dependent, node)
-               if (dep->dev == depdev)
-                       goto out;
-
-       dep = kzalloc(sizeof(*dep), GFP_KERNEL);
-       if (dep) {
-               dep->dev = depdev;
-               list_add_tail(&dep->node, &adev->power_dependent);
-       }
-
- out:
-       mutex_unlock(&adev->physical_node_lock);
-}
-EXPORT_SYMBOL_GPL(acpi_dev_pm_add_dependent);
-
-/**
- * acpi_dev_pm_remove_dependent - Remove physical device depending for PM.
- * @handle: Handle of ACPI device node.
- * @depdev: Device depending on that node for PM.
- */
-void acpi_dev_pm_remove_dependent(acpi_handle handle, struct device *depdev)
-{
-       struct acpi_device_physical_node *dep;
-       struct acpi_device *adev;
-
-       if (!depdev || acpi_bus_get_device(handle, &adev))
-               return;
-
-       mutex_lock(&adev->physical_node_lock);
-
-       list_for_each_entry(dep, &adev->power_dependent, node)
-               if (dep->dev == depdev) {
-                       list_del(&dep->node);
-                       kfree(dep);
-                       break;
-               }
-
-       mutex_unlock(&adev->physical_node_lock);
-}
-EXPORT_SYMBOL_GPL(acpi_dev_pm_remove_dependent);
 #endif /* CONFIG_PM */
index 0dbe5cdf3396e5f53b23c84bb30041329544774d..c2ad391d8041ecb6a354e2df07b9d813d817a744 100644 (file)
@@ -59,16 +59,9 @@ ACPI_MODULE_NAME("power");
 #define ACPI_POWER_RESOURCE_STATE_ON   0x01
 #define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF
 
-struct acpi_power_dependent_device {
-       struct list_head node;
-       struct acpi_device *adev;
-       struct work_struct work;
-};
-
 struct acpi_power_resource {
        struct acpi_device device;
        struct list_head list_node;
-       struct list_head dependent;
        char *name;
        u32 system_level;
        u32 order;
@@ -233,32 +226,6 @@ static int acpi_power_get_list_state(struct list_head *list, int *state)
        return 0;
 }
 
-static void acpi_power_resume_dependent(struct work_struct *work)
-{
-       struct acpi_power_dependent_device *dep;
-       struct acpi_device_physical_node *pn;
-       struct acpi_device *adev;
-       int state;
-
-       dep = container_of(work, struct acpi_power_dependent_device, work);
-       adev = dep->adev;
-       if (acpi_power_get_inferred_state(adev, &state))
-               return;
-
-       if (state > ACPI_STATE_D0)
-               return;
-
-       mutex_lock(&adev->physical_node_lock);
-
-       list_for_each_entry(pn, &adev->physical_node_list, node)
-               pm_request_resume(pn->dev);
-
-       list_for_each_entry(pn, &adev->power_dependent, node)
-               pm_request_resume(pn->dev);
-
-       mutex_unlock(&adev->physical_node_lock);
-}
-
 static int __acpi_power_on(struct acpi_power_resource *resource)
 {
        acpi_status status = AE_OK;
@@ -283,14 +250,8 @@ static int acpi_power_on_unlocked(struct acpi_power_resource *resource)
                                  resource->name));
        } else {
                result = __acpi_power_on(resource);
-               if (result) {
+               if (result)
                        resource->ref_count--;
-               } else {
-                       struct acpi_power_dependent_device *dep;
-
-                       list_for_each_entry(dep, &resource->dependent, node)
-                               schedule_work(&dep->work);
-               }
        }
        return result;
 }
@@ -390,52 +351,6 @@ static int acpi_power_on_list(struct list_head *list)
        return result;
 }
 
-static void acpi_power_add_dependent(struct acpi_power_resource *resource,
-                                    struct acpi_device *adev)
-{
-       struct acpi_power_dependent_device *dep;
-
-       mutex_lock(&resource->resource_lock);
-
-       list_for_each_entry(dep, &resource->dependent, node)
-               if (dep->adev == adev)
-                       goto out;
-
-       dep = kzalloc(sizeof(*dep), GFP_KERNEL);
-       if (!dep)
-               goto out;
-
-       dep->adev = adev;
-       INIT_WORK(&dep->work, acpi_power_resume_dependent);
-       list_add_tail(&dep->node, &resource->dependent);
-
- out:
-       mutex_unlock(&resource->resource_lock);
-}
-
-static void acpi_power_remove_dependent(struct acpi_power_resource *resource,
-                                       struct acpi_device *adev)
-{
-       struct acpi_power_dependent_device *dep;
-       struct work_struct *work = NULL;
-
-       mutex_lock(&resource->resource_lock);
-
-       list_for_each_entry(dep, &resource->dependent, node)
-               if (dep->adev == adev) {
-                       list_del(&dep->node);
-                       work = &dep->work;
-                       break;
-               }
-
-       mutex_unlock(&resource->resource_lock);
-
-       if (work) {
-               cancel_work_sync(work);
-               kfree(dep);
-       }
-}
-
 static struct attribute *attrs[] = {
        NULL,
 };
@@ -524,8 +439,6 @@ static void acpi_power_expose_hide(struct acpi_device *adev,
 
 void acpi_power_add_remove_device(struct acpi_device *adev, bool add)
 {
-       struct acpi_device_power_state *ps;
-       struct acpi_power_resource_entry *entry;
        int state;
 
        if (adev->wakeup.flags.valid)
@@ -535,16 +448,6 @@ void acpi_power_add_remove_device(struct acpi_device *adev, bool add)
        if (!adev->power.flags.power_resources)
                return;
 
-       ps = &adev->power.states[ACPI_STATE_D0];
-       list_for_each_entry(entry, &ps->resources, node) {
-               struct acpi_power_resource *resource = entry->resource;
-
-               if (add)
-                       acpi_power_add_dependent(resource, adev);
-               else
-                       acpi_power_remove_dependent(resource, adev);
-       }
-
        for (state = ACPI_STATE_D0; state <= ACPI_STATE_D3_HOT; state++)
                acpi_power_expose_hide(adev,
                                       &adev->power.states[state].resources,
@@ -882,7 +785,6 @@ int acpi_add_power_resource(acpi_handle handle)
        acpi_init_device_object(device, handle, ACPI_BUS_TYPE_POWER,
                                ACPI_STA_DEFAULT);
        mutex_init(&resource->resource_lock);
-       INIT_LIST_HEAD(&resource->dependent);
        INIT_LIST_HEAD(&resource->list_node);
        resource->name = device->pnp.bus_id;
        strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME);
@@ -936,8 +838,10 @@ void acpi_resume_power_resources(void)
                mutex_lock(&resource->resource_lock);
 
                result = acpi_power_get_state(resource->device.handle, &state);
-               if (result)
+               if (result) {
+                       mutex_unlock(&resource->resource_lock);
                        continue;
+               }
 
                if (state == ACPI_POWER_RESOURCE_STATE_OFF
                    && resource->ref_count) {
index 407ad13cac2f27945c3b812f791a4f615c2db492..fee8a297c7d95310caa64492b75e6c2fae0c280e 100644 (file)
@@ -999,7 +999,6 @@ int acpi_device_add(struct acpi_device *device,
        INIT_LIST_HEAD(&device->wakeup_list);
        INIT_LIST_HEAD(&device->physical_node_list);
        mutex_init(&device->physical_node_lock);
-       INIT_LIST_HEAD(&device->power_dependent);
 
        new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL);
        if (!new_bus_id) {
index 4ba8b04055728d49a0ac147a608d1ad27391d62a..ab714d2ad978644752ca3c9bdff74ae1c9f63934 100644 (file)
@@ -1035,17 +1035,3 @@ void ata_acpi_on_disable(struct ata_device *dev)
 {
        ata_acpi_clear_gtf(dev);
 }
-
-void ata_scsi_acpi_bind(struct ata_device *dev)
-{
-       acpi_handle handle = ata_dev_acpi_handle(dev);
-       if (handle)
-               acpi_dev_pm_add_dependent(handle, &dev->sdev->sdev_gendev);
-}
-
-void ata_scsi_acpi_unbind(struct ata_device *dev)
-{
-       acpi_handle handle = ata_dev_acpi_handle(dev);
-       if (handle)
-               acpi_dev_pm_remove_dependent(handle, &dev->sdev->sdev_gendev);
-}
index 97a0cef1295916223202058b83e80a20de74c7de..db6dfcfa3e2ee932190069290814f2a71bc8f3f6 100644 (file)
@@ -3679,7 +3679,6 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync)
                        if (!IS_ERR(sdev)) {
                                dev->sdev = sdev;
                                scsi_device_put(sdev);
-                               ata_scsi_acpi_bind(dev);
                        } else {
                                dev->sdev = NULL;
                        }
@@ -3767,8 +3766,6 @@ static void ata_scsi_remove_dev(struct ata_device *dev)
        struct scsi_device *sdev;
        unsigned long flags;
 
-       ata_scsi_acpi_unbind(dev);
-
        /* Alas, we need to grab scan_mutex to ensure SCSI device
         * state doesn't change underneath us and thus
         * scsi_device_get() always succeeds.  The mutex locking can
index eeeb77845d48574e3f43b4b6e456302e5f3926d9..45b5ab3a95d51158c9ef0e618d6c8ae0fdeb373b 100644 (file)
@@ -121,8 +121,6 @@ extern void ata_acpi_set_state(struct ata_port *ap, pm_message_t state);
 extern void ata_acpi_bind_port(struct ata_port *ap);
 extern void ata_acpi_bind_dev(struct ata_device *dev);
 extern acpi_handle ata_dev_acpi_handle(struct ata_device *dev);
-extern void ata_scsi_acpi_bind(struct ata_device *dev);
-extern void ata_scsi_acpi_unbind(struct ata_device *dev);
 #else
 static inline void ata_acpi_dissociate(struct ata_host *host) { }
 static inline int ata_acpi_on_suspend(struct ata_port *ap) { return 0; }
@@ -133,8 +131,6 @@ static inline void ata_acpi_set_state(struct ata_port *ap,
                                      pm_message_t state) { }
 static inline void ata_acpi_bind_port(struct ata_port *ap) {}
 static inline void ata_acpi_bind_dev(struct ata_device *dev) {}
-static inline void ata_scsi_acpi_bind(struct ata_device *dev) {}
-static inline void ata_scsi_acpi_unbind(struct ata_device *dev) {}
 #endif
 
 /* libata-scsi.c */
index 9e59f6535c442bbb26d6ad055b93a4b0cf5bef5d..bece691cb5d99d79f761b9400eebf1e9a78c55a2 100644 (file)
@@ -333,8 +333,10 @@ store_mem_state(struct device *dev,
                online_type = ONLINE_KEEP;
        else if (!strncmp(buf, "offline", min_t(int, count, 7)))
                online_type = -1;
-       else
-               return -EINVAL;
+       else {
+               ret = -EINVAL;
+               goto err;
+       }
 
        switch (online_type) {
        case ONLINE_KERNEL:
@@ -357,6 +359,7 @@ store_mem_state(struct device *dev,
                ret = -EINVAL; /* should never happen */
        }
 
+err:
        unlock_device_hotplug();
 
        if (ret)
index 06189e55b4e5a0479d2eaab0a31610ef91bf472f..94c280d36e8b3bfaea00ee36c4fe3215818b3c86 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/errno.h>
 #include <linux/err.h>
 #include <linux/interrupt.h>
+#include <xen/xen.h>
 #include <xen/events.h>
 #include <xen/interface/io/tpmif.h>
 #include <xen/grant_table.h>
index 32b3479a24051d09a0c1c53647b74848fcb3c967..badf6206b2b20d7284ffbbd098fd66676937fb64 100644 (file)
@@ -383,6 +383,7 @@ static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max)
 static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate)
 {
        int max_perf, min_perf;
+       u64 val;
 
        intel_pstate_get_min_max(cpu, &min_perf, &max_perf);
 
@@ -394,11 +395,11 @@ static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate)
        trace_cpu_frequency(pstate * 100000, cpu->cpu);
 
        cpu->pstate.current_pstate = pstate;
+       val = pstate << 8;
        if (limits.no_turbo)
-               wrmsrl(MSR_IA32_PERF_CTL, BIT(32) | (pstate << 8));
-       else
-               wrmsrl(MSR_IA32_PERF_CTL, pstate << 8);
+               val |= (u64)1 << 32;
 
+       wrmsrl(MSR_IA32_PERF_CTL, val);
 }
 
 static inline void intel_pstate_pstate_increase(struct cpudata *cpu, int steps)
@@ -637,8 +638,8 @@ static int intel_pstate_cpu_exit(struct cpufreq_policy *policy)
 
 static int intel_pstate_cpu_init(struct cpufreq_policy *policy)
 {
-       int rc, min_pstate, max_pstate;
        struct cpudata *cpu;
+       int rc;
 
        rc = intel_pstate_init_cpu(policy->cpu);
        if (rc)
@@ -652,9 +653,8 @@ static int intel_pstate_cpu_init(struct cpufreq_policy *policy)
        else
                policy->policy = CPUFREQ_POLICY_POWERSAVE;
 
-       intel_pstate_get_min_max(cpu, &min_pstate, &max_pstate);
-       policy->min = min_pstate * 100000;
-       policy->max = max_pstate * 100000;
+       policy->min = cpu->pstate.min_pstate * 100000;
+       policy->max = cpu->pstate.turbo_pstate * 100000;
 
        /* cpuinfo and default policy values */
        policy->cpuinfo.min_freq = cpu->pstate.min_pstate * 100000;
index 8a72b0c555f846da21d25d02d9f94d427a7796b5..15631f92ab7d78cceec876e319c85092c921b8bc 100644 (file)
@@ -166,7 +166,7 @@ static void __init s3c64xx_cpufreq_config_regulator(void)
                if (freq->frequency == CPUFREQ_ENTRY_INVALID)
                        continue;
 
-               dvfs = &s3c64xx_dvfs_table[freq->index];
+               dvfs = &s3c64xx_dvfs_table[freq->driver_data];
                found = 0;
 
                for (i = 0; i < count; i++) {
index 2d9ca6055e5e0bde239247fabe41c960d4dd3020..41b5913ddabe6e0a8b1f417004d86628234b77c5 100644 (file)
@@ -248,14 +248,15 @@ static void lp_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
        struct lp_gpio *lg = irq_data_get_irq_handler_data(data);
        struct irq_chip *chip = irq_data_get_irq_chip(data);
        u32 base, pin, mask;
-       unsigned long reg, pending;
+       unsigned long reg, ena, pending;
        unsigned virq;
 
        /* check from GPIO controller which pin triggered the interrupt */
        for (base = 0; base < lg->chip.ngpio; base += 32) {
                reg = lp_gpio_reg(&lg->chip, base, LP_INT_STAT);
+               ena = lp_gpio_reg(&lg->chip, base, LP_INT_ENABLE);
 
-               while ((pending = inl(reg))) {
+               while ((pending = (inl(reg) & inl(ena)))) {
                        pin = __ffs(pending);
                        mask = BIT(pin);
                        /* Clear before handling so we don't lose an edge */
index 86ef3461ec0647b42f1e1ff94a9f47225151f7f6..0dee0e0c247ae5fa2f121df234d09979dc00df74 100644 (file)
@@ -136,7 +136,7 @@ static struct gpio_desc *gpio_to_desc(unsigned gpio)
  */
 static int desc_to_gpio(const struct gpio_desc *desc)
 {
-       return desc->chip->base + gpio_chip_hwgpio(desc);
+       return desc - &gpio_desc[0];
 }
 
 
@@ -1398,7 +1398,7 @@ static int gpiod_request(struct gpio_desc *desc, const char *label)
        int                     status = -EPROBE_DEFER;
        unsigned long           flags;
 
-       if (!desc || !desc->chip) {
+       if (!desc) {
                pr_warn("%s: invalid GPIO\n", __func__);
                return -EINVAL;
        }
@@ -1406,6 +1406,8 @@ static int gpiod_request(struct gpio_desc *desc, const char *label)
        spin_lock_irqsave(&gpio_lock, flags);
 
        chip = desc->chip;
+       if (chip == NULL)
+               goto done;
 
        if (!try_module_get(chip->owner))
                goto done;
index a7b30be86ae06cb7ae59a077aa45ee4e58f52051..52605c0ea3a69fce7c1d312d4fa1610de43174fd 100644 (file)
@@ -525,8 +525,10 @@ static int adf4350_probe(struct spi_device *spi)
        }
 
        indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
-       if (indio_dev == NULL)
-               return -ENOMEM;
+       if (indio_dev == NULL) {
+               ret =  -ENOMEM;
+               goto error_disable_clk;
+       }
 
        st = iio_priv(indio_dev);
 
index 2710f7245c3b5472b0e924bd22a94f6bc1212b6f..2db7dcd826b9db6500e354498b385cbb3ebd9f7d 100644 (file)
@@ -477,6 +477,9 @@ void iio_disable_all_buffers(struct iio_dev *indio_dev)
        indio_dev->currentmode = INDIO_DIRECT_MODE;
        if (indio_dev->setup_ops->postdisable)
                indio_dev->setup_ops->postdisable(indio_dev);
+
+       if (indio_dev->available_scan_masks == NULL)
+               kfree(indio_dev->active_scan_mask);
 }
 
 int iio_update_buffers(struct iio_dev *indio_dev,
index d5d1929753e4fdc95bbdc67625f5f0521ffeb32f..cedda25232be2454b3b2f0902152d96a7b1dfd75 100644 (file)
@@ -141,7 +141,7 @@ static const char *to_qp_state_str(int state)
                return "C2_QP_STATE_ERROR";
        default:
                return "<invalid QP state>";
-       };
+       }
 }
 
 void c2_ae_event(struct c2_dev *c2dev, u32 mq_index)
index 3f831de9a4d8a901607afc26c81827cc5c1e3bd5..b1a6cb3a2809282fbfab1b44b09c53e315a93466 100644 (file)
@@ -164,6 +164,7 @@ int mlx5_vector2eqn(struct mlx5_ib_dev *dev, int vector, int *eqn, int *irqn)
 static int alloc_comp_eqs(struct mlx5_ib_dev *dev)
 {
        struct mlx5_eq_table *table = &dev->mdev.priv.eq_table;
+       char name[MLX5_MAX_EQ_NAME];
        struct mlx5_eq *eq, *n;
        int ncomp_vec;
        int nent;
@@ -180,11 +181,10 @@ static int alloc_comp_eqs(struct mlx5_ib_dev *dev)
                        goto clean;
                }
 
-               snprintf(eq->name, MLX5_MAX_EQ_NAME, "mlx5_comp%d", i);
+               snprintf(name, MLX5_MAX_EQ_NAME, "mlx5_comp%d", i);
                err = mlx5_create_map_eq(&dev->mdev, eq,
                                         i + MLX5_EQ_VEC_COMP_BASE, nent, 0,
-                                        eq->name,
-                                        &dev->mdev.priv.uuari.uars[0]);
+                                        name, &dev->mdev.priv.uuari.uars[0]);
                if (err) {
                        kfree(eq);
                        goto clean;
@@ -301,9 +301,8 @@ static int mlx5_ib_query_device(struct ib_device *ibdev,
        props->max_srq_sge         = max_rq_sg - 1;
        props->max_fast_reg_page_list_len = (unsigned int)-1;
        props->local_ca_ack_delay  = dev->mdev.caps.local_ca_ack_delay;
-       props->atomic_cap          = dev->mdev.caps.flags & MLX5_DEV_CAP_FLAG_ATOMIC ?
-               IB_ATOMIC_HCA : IB_ATOMIC_NONE;
-       props->masked_atomic_cap   = IB_ATOMIC_HCA;
+       props->atomic_cap          = IB_ATOMIC_NONE;
+       props->masked_atomic_cap   = IB_ATOMIC_NONE;
        props->max_pkeys           = be16_to_cpup((__be16 *)(out_mad->data + 28));
        props->max_mcast_grp       = 1 << dev->mdev.caps.log_max_mcg;
        props->max_mcast_qp_attach = dev->mdev.caps.max_qp_mcg;
@@ -1006,6 +1005,11 @@ static void mlx5_ib_event(struct mlx5_core_dev *dev, enum mlx5_dev_event event,
        ibev.device           = &ibdev->ib_dev;
        ibev.element.port_num = port;
 
+       if (port < 1 || port > ibdev->num_ports) {
+               mlx5_ib_warn(ibdev, "warning: event on port %d\n", port);
+               return;
+       }
+
        if (ibdev->ib_active)
                ib_dispatch_event(&ibev);
 }
index bd41df95b6f0214deb445ab228be8d157373074f..3453580b1eb2cc45800b8ee697157a24cf269970 100644 (file)
@@ -42,6 +42,10 @@ enum {
        DEF_CACHE_SIZE  = 10,
 };
 
+enum {
+       MLX5_UMR_ALIGN  = 2048
+};
+
 static __be64 *mr_align(__be64 *ptr, int align)
 {
        unsigned long mask = align - 1;
@@ -61,13 +65,11 @@ static int order2idx(struct mlx5_ib_dev *dev, int order)
 
 static int add_keys(struct mlx5_ib_dev *dev, int c, int num)
 {
-       struct device *ddev = dev->ib_dev.dma_device;
        struct mlx5_mr_cache *cache = &dev->cache;
        struct mlx5_cache_ent *ent = &cache->ent[c];
        struct mlx5_create_mkey_mbox_in *in;
        struct mlx5_ib_mr *mr;
        int npages = 1 << ent->order;
-       int size = sizeof(u64) * npages;
        int err = 0;
        int i;
 
@@ -83,21 +85,6 @@ static int add_keys(struct mlx5_ib_dev *dev, int c, int num)
                }
                mr->order = ent->order;
                mr->umred = 1;
-               mr->pas = kmalloc(size + 0x3f, GFP_KERNEL);
-               if (!mr->pas) {
-                       kfree(mr);
-                       err = -ENOMEM;
-                       goto out;
-               }
-               mr->dma = dma_map_single(ddev, mr_align(mr->pas, 0x40), size,
-                                        DMA_TO_DEVICE);
-               if (dma_mapping_error(ddev, mr->dma)) {
-                       kfree(mr->pas);
-                       kfree(mr);
-                       err = -ENOMEM;
-                       goto out;
-               }
-
                in->seg.status = 1 << 6;
                in->seg.xlt_oct_size = cpu_to_be32((npages + 1) / 2);
                in->seg.qpn_mkey7_0 = cpu_to_be32(0xffffff << 8);
@@ -108,8 +95,6 @@ static int add_keys(struct mlx5_ib_dev *dev, int c, int num)
                                            sizeof(*in));
                if (err) {
                        mlx5_ib_warn(dev, "create mkey failed %d\n", err);
-                       dma_unmap_single(ddev, mr->dma, size, DMA_TO_DEVICE);
-                       kfree(mr->pas);
                        kfree(mr);
                        goto out;
                }
@@ -129,11 +114,9 @@ out:
 
 static void remove_keys(struct mlx5_ib_dev *dev, int c, int num)
 {
-       struct device *ddev = dev->ib_dev.dma_device;
        struct mlx5_mr_cache *cache = &dev->cache;
        struct mlx5_cache_ent *ent = &cache->ent[c];
        struct mlx5_ib_mr *mr;
-       int size;
        int err;
        int i;
 
@@ -149,14 +132,10 @@ static void remove_keys(struct mlx5_ib_dev *dev, int c, int num)
                ent->size--;
                spin_unlock(&ent->lock);
                err = mlx5_core_destroy_mkey(&dev->mdev, &mr->mmr);
-               if (err) {
+               if (err)
                        mlx5_ib_warn(dev, "failed destroy mkey\n");
-               } else {
-                       size = ALIGN(sizeof(u64) * (1 << mr->order), 0x40);
-                       dma_unmap_single(ddev, mr->dma, size, DMA_TO_DEVICE);
-                       kfree(mr->pas);
+               else
                        kfree(mr);
-               }
        }
 }
 
@@ -408,13 +387,12 @@ static void free_cached_mr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
 
 static void clean_keys(struct mlx5_ib_dev *dev, int c)
 {
-       struct device *ddev = dev->ib_dev.dma_device;
        struct mlx5_mr_cache *cache = &dev->cache;
        struct mlx5_cache_ent *ent = &cache->ent[c];
        struct mlx5_ib_mr *mr;
-       int size;
        int err;
 
+       cancel_delayed_work(&ent->dwork);
        while (1) {
                spin_lock(&ent->lock);
                if (list_empty(&ent->head)) {
@@ -427,14 +405,10 @@ static void clean_keys(struct mlx5_ib_dev *dev, int c)
                ent->size--;
                spin_unlock(&ent->lock);
                err = mlx5_core_destroy_mkey(&dev->mdev, &mr->mmr);
-               if (err) {
+               if (err)
                        mlx5_ib_warn(dev, "failed destroy mkey\n");
-               } else {
-                       size = ALIGN(sizeof(u64) * (1 << mr->order), 0x40);
-                       dma_unmap_single(ddev, mr->dma, size, DMA_TO_DEVICE);
-                       kfree(mr->pas);
+               else
                        kfree(mr);
-               }
        }
 }
 
@@ -540,13 +514,15 @@ int mlx5_mr_cache_cleanup(struct mlx5_ib_dev *dev)
        int i;
 
        dev->cache.stopped = 1;
-       destroy_workqueue(dev->cache.wq);
+       flush_workqueue(dev->cache.wq);
 
        mlx5_mr_cache_debugfs_cleanup(dev);
 
        for (i = 0; i < MAX_MR_CACHE_ENTRIES; i++)
                clean_keys(dev, i);
 
+       destroy_workqueue(dev->cache.wq);
+
        return 0;
 }
 
@@ -675,10 +651,12 @@ static struct mlx5_ib_mr *reg_umr(struct ib_pd *pd, struct ib_umem *umem,
                                  int page_shift, int order, int access_flags)
 {
        struct mlx5_ib_dev *dev = to_mdev(pd->device);
+       struct device *ddev = dev->ib_dev.dma_device;
        struct umr_common *umrc = &dev->umrc;
        struct ib_send_wr wr, *bad;
        struct mlx5_ib_mr *mr;
        struct ib_sge sg;
+       int size = sizeof(u64) * npages;
        int err;
        int i;
 
@@ -697,7 +675,22 @@ static struct mlx5_ib_mr *reg_umr(struct ib_pd *pd, struct ib_umem *umem,
        if (!mr)
                return ERR_PTR(-EAGAIN);
 
-       mlx5_ib_populate_pas(dev, umem, page_shift, mr_align(mr->pas, 0x40), 1);
+       mr->pas = kmalloc(size + MLX5_UMR_ALIGN - 1, GFP_KERNEL);
+       if (!mr->pas) {
+               err = -ENOMEM;
+               goto error;
+       }
+
+       mlx5_ib_populate_pas(dev, umem, page_shift,
+                            mr_align(mr->pas, MLX5_UMR_ALIGN), 1);
+
+       mr->dma = dma_map_single(ddev, mr_align(mr->pas, MLX5_UMR_ALIGN), size,
+                                DMA_TO_DEVICE);
+       if (dma_mapping_error(ddev, mr->dma)) {
+               kfree(mr->pas);
+               err = -ENOMEM;
+               goto error;
+       }
 
        memset(&wr, 0, sizeof(wr));
        wr.wr_id = (u64)(unsigned long)mr;
@@ -718,6 +711,9 @@ static struct mlx5_ib_mr *reg_umr(struct ib_pd *pd, struct ib_umem *umem,
        wait_for_completion(&mr->done);
        up(&umrc->sem);
 
+       dma_unmap_single(ddev, mr->dma, size, DMA_TO_DEVICE);
+       kfree(mr->pas);
+
        if (mr->status != IB_WC_SUCCESS) {
                mlx5_ib_warn(dev, "reg umr failed\n");
                err = -EFAULT;
index 045f8cdbd303deba81e60c5f1f52330b536b9617..5659ea88074108e60d9253085ce89f962326b808 100644 (file)
@@ -203,7 +203,7 @@ static int sq_overhead(enum ib_qp_type qp_type)
 
        switch (qp_type) {
        case IB_QPT_XRC_INI:
-               size = sizeof(struct mlx5_wqe_xrc_seg);
+               size += sizeof(struct mlx5_wqe_xrc_seg);
                /* fall through */
        case IB_QPT_RC:
                size += sizeof(struct mlx5_wqe_ctrl_seg) +
@@ -211,20 +211,23 @@ static int sq_overhead(enum ib_qp_type qp_type)
                        sizeof(struct mlx5_wqe_raddr_seg);
                break;
 
+       case IB_QPT_XRC_TGT:
+               return 0;
+
        case IB_QPT_UC:
-               size = sizeof(struct mlx5_wqe_ctrl_seg) +
+               size += sizeof(struct mlx5_wqe_ctrl_seg) +
                        sizeof(struct mlx5_wqe_raddr_seg);
                break;
 
        case IB_QPT_UD:
        case IB_QPT_SMI:
        case IB_QPT_GSI:
-               size = sizeof(struct mlx5_wqe_ctrl_seg) +
+               size += sizeof(struct mlx5_wqe_ctrl_seg) +
                        sizeof(struct mlx5_wqe_datagram_seg);
                break;
 
        case MLX5_IB_QPT_REG_UMR:
-               size = sizeof(struct mlx5_wqe_ctrl_seg) +
+               size += sizeof(struct mlx5_wqe_ctrl_seg) +
                        sizeof(struct mlx5_wqe_umr_ctrl_seg) +
                        sizeof(struct mlx5_mkey_seg);
                break;
@@ -270,7 +273,8 @@ static int calc_sq_size(struct mlx5_ib_dev *dev, struct ib_qp_init_attr *attr,
                return wqe_size;
 
        if (wqe_size > dev->mdev.caps.max_sq_desc_sz) {
-               mlx5_ib_dbg(dev, "\n");
+               mlx5_ib_dbg(dev, "wqe_size(%d) > max_sq_desc_sz(%d)\n",
+                           wqe_size, dev->mdev.caps.max_sq_desc_sz);
                return -EINVAL;
        }
 
@@ -280,9 +284,15 @@ static int calc_sq_size(struct mlx5_ib_dev *dev, struct ib_qp_init_attr *attr,
 
        wq_size = roundup_pow_of_two(attr->cap.max_send_wr * wqe_size);
        qp->sq.wqe_cnt = wq_size / MLX5_SEND_WQE_BB;
+       if (qp->sq.wqe_cnt > dev->mdev.caps.max_wqes) {
+               mlx5_ib_dbg(dev, "wqe count(%d) exceeds limits(%d)\n",
+                           qp->sq.wqe_cnt, dev->mdev.caps.max_wqes);
+               return -ENOMEM;
+       }
        qp->sq.wqe_shift = ilog2(MLX5_SEND_WQE_BB);
        qp->sq.max_gs = attr->cap.max_send_sge;
-       qp->sq.max_post = 1 << ilog2(wq_size / wqe_size);
+       qp->sq.max_post = wq_size / wqe_size;
+       attr->cap.max_send_wr = qp->sq.max_post;
 
        return wq_size;
 }
@@ -1280,6 +1290,11 @@ static enum mlx5_qp_optpar opt_mask[MLX5_QP_NUM_STATE][MLX5_QP_NUM_STATE][MLX5_Q
                                          MLX5_QP_OPTPAR_Q_KEY,
                        [MLX5_QP_ST_MLX] = MLX5_QP_OPTPAR_PKEY_INDEX    |
                                           MLX5_QP_OPTPAR_Q_KEY,
+                       [MLX5_QP_ST_XRC] = MLX5_QP_OPTPAR_ALT_ADDR_PATH |
+                                         MLX5_QP_OPTPAR_RRE            |
+                                         MLX5_QP_OPTPAR_RAE            |
+                                         MLX5_QP_OPTPAR_RWE            |
+                                         MLX5_QP_OPTPAR_PKEY_INDEX,
                },
        },
        [MLX5_QP_STATE_RTR] = {
@@ -1314,6 +1329,11 @@ static enum mlx5_qp_optpar opt_mask[MLX5_QP_NUM_STATE][MLX5_QP_NUM_STATE][MLX5_Q
                [MLX5_QP_STATE_RTS] = {
                        [MLX5_QP_ST_UD]  = MLX5_QP_OPTPAR_Q_KEY,
                        [MLX5_QP_ST_MLX] = MLX5_QP_OPTPAR_Q_KEY,
+                       [MLX5_QP_ST_UC]  = MLX5_QP_OPTPAR_RWE,
+                       [MLX5_QP_ST_RC]  = MLX5_QP_OPTPAR_RNR_TIMEOUT   |
+                                          MLX5_QP_OPTPAR_RWE           |
+                                          MLX5_QP_OPTPAR_RAE           |
+                                          MLX5_QP_OPTPAR_RRE,
                },
        },
 };
@@ -1651,29 +1671,6 @@ static __always_inline void set_raddr_seg(struct mlx5_wqe_raddr_seg *rseg,
        rseg->reserved = 0;
 }
 
-static void set_atomic_seg(struct mlx5_wqe_atomic_seg *aseg, struct ib_send_wr *wr)
-{
-       if (wr->opcode == IB_WR_ATOMIC_CMP_AND_SWP) {
-               aseg->swap_add = cpu_to_be64(wr->wr.atomic.swap);
-               aseg->compare  = cpu_to_be64(wr->wr.atomic.compare_add);
-       } else if (wr->opcode == IB_WR_MASKED_ATOMIC_FETCH_AND_ADD) {
-               aseg->swap_add = cpu_to_be64(wr->wr.atomic.compare_add);
-               aseg->compare  = cpu_to_be64(wr->wr.atomic.compare_add_mask);
-       } else {
-               aseg->swap_add = cpu_to_be64(wr->wr.atomic.compare_add);
-               aseg->compare  = 0;
-       }
-}
-
-static void set_masked_atomic_seg(struct mlx5_wqe_masked_atomic_seg *aseg,
-                                 struct ib_send_wr *wr)
-{
-       aseg->swap_add          = cpu_to_be64(wr->wr.atomic.swap);
-       aseg->swap_add_mask     = cpu_to_be64(wr->wr.atomic.swap_mask);
-       aseg->compare           = cpu_to_be64(wr->wr.atomic.compare_add);
-       aseg->compare_mask      = cpu_to_be64(wr->wr.atomic.compare_add_mask);
-}
-
 static void set_datagram_seg(struct mlx5_wqe_datagram_seg *dseg,
                             struct ib_send_wr *wr)
 {
@@ -2063,28 +2060,11 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
 
                        case IB_WR_ATOMIC_CMP_AND_SWP:
                        case IB_WR_ATOMIC_FETCH_AND_ADD:
-                               set_raddr_seg(seg, wr->wr.atomic.remote_addr,
-                                             wr->wr.atomic.rkey);
-                               seg  += sizeof(struct mlx5_wqe_raddr_seg);
-
-                               set_atomic_seg(seg, wr);
-                               seg  += sizeof(struct mlx5_wqe_atomic_seg);
-
-                               size += (sizeof(struct mlx5_wqe_raddr_seg) +
-                                        sizeof(struct mlx5_wqe_atomic_seg)) / 16;
-                               break;
-
                        case IB_WR_MASKED_ATOMIC_CMP_AND_SWP:
-                               set_raddr_seg(seg, wr->wr.atomic.remote_addr,
-                                             wr->wr.atomic.rkey);
-                               seg  += sizeof(struct mlx5_wqe_raddr_seg);
-
-                               set_masked_atomic_seg(seg, wr);
-                               seg  += sizeof(struct mlx5_wqe_masked_atomic_seg);
-
-                               size += (sizeof(struct mlx5_wqe_raddr_seg) +
-                                        sizeof(struct mlx5_wqe_masked_atomic_seg)) / 16;
-                               break;
+                               mlx5_ib_warn(dev, "Atomic operations are not supported yet\n");
+                               err = -ENOSYS;
+                               *bad_wr = wr;
+                               goto out;
 
                        case IB_WR_LOCAL_INV:
                                next_fence = MLX5_FENCE_MODE_INITIATOR_SMALL;
index 84d297afd6a9889642007a4b3d6b2e0e6e25be74..0aa478bc291ae39aec0ed8c243cce72fe7ed2bdd 100644 (file)
@@ -295,7 +295,7 @@ struct ib_srq *mlx5_ib_create_srq(struct ib_pd *pd,
        mlx5_vfree(in);
        if (err) {
                mlx5_ib_dbg(dev, "create SRQ failed, err %d\n", err);
-               goto err_srq;
+               goto err_usr_kern_srq;
        }
 
        mlx5_ib_dbg(dev, "create SRQ with srqn 0x%x\n", srq->msrq.srqn);
@@ -316,6 +316,8 @@ struct ib_srq *mlx5_ib_create_srq(struct ib_pd *pd,
 
 err_core:
        mlx5_core_destroy_srq(&dev->mdev, &srq->msrq);
+
+err_usr_kern_srq:
        if (pd->uobject)
                destroy_srq_user(pd, srq);
        else
index 7c9d35f39d756950b9470d50201f882ca6fba1e3..69020173899397ee5889287ee79f0c3525ab8991 100644 (file)
@@ -357,7 +357,7 @@ static int mthca_eq_int(struct mthca_dev *dev, struct mthca_eq *eq)
                        mthca_warn(dev, "Unhandled event %02x(%02x) on EQ %d\n",
                                   eqe->type, eqe->subtype, eq->eqn);
                        break;
-               };
+               }
 
                set_eqe_hw(eqe);
                ++eq->cons_index;
index 4ed8235d2d36d818360cce7e2d43010e0840ab62..50219ab2279d56ae6599e7189b06034bf12049d9 100644 (file)
@@ -150,7 +150,7 @@ enum ib_qp_state get_ibqp_state(enum ocrdma_qp_state qps)
                return IB_QPS_SQE;
        case OCRDMA_QPS_ERR:
                return IB_QPS_ERR;
-       };
+       }
        return IB_QPS_ERR;
 }
 
@@ -171,7 +171,7 @@ static enum ocrdma_qp_state get_ocrdma_qp_state(enum ib_qp_state qps)
                return OCRDMA_QPS_SQE;
        case IB_QPS_ERR:
                return OCRDMA_QPS_ERR;
-       };
+       }
        return OCRDMA_QPS_ERR;
 }
 
@@ -1982,7 +1982,7 @@ int ocrdma_mbx_create_qp(struct ocrdma_qp *qp, struct ib_qp_init_attr *attrs,
                break;
        default:
                return -EINVAL;
-       };
+       }
 
        cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_CREATE_QP, sizeof(*cmd));
        if (!cmd)
index 56e004940f1806c9203e788985395ea4ea5bdddb..0ce7674621eaba2aa310fef332695b67f3057971 100644 (file)
@@ -531,7 +531,7 @@ static void ocrdma_event_handler(struct ocrdma_dev *dev, u32 event)
        case BE_DEV_DOWN:
                ocrdma_close(dev);
                break;
-       };
+       }
 }
 
 static struct ocrdma_driver ocrdma_drv = {
index 6e982bb43c3172d2cc36b844c1b97f8bb0960237..69f1d1221a6bea07039fc37b5ead33f941fc74a4 100644 (file)
@@ -141,7 +141,7 @@ static inline void get_link_speed_and_width(struct ocrdma_dev *dev,
                /* Unsupported */
                *ib_speed = IB_SPEED_SDR;
                *ib_width = IB_WIDTH_1X;
-       };
+       }
 }
 
 
@@ -2331,7 +2331,7 @@ static enum ib_wc_status ocrdma_to_ibwc_err(u16 status)
        default:
                ibwc_status = IB_WC_GENERAL_ERR;
                break;
-       };
+       }
        return ibwc_status;
 }
 
@@ -2370,7 +2370,7 @@ static void ocrdma_update_wc(struct ocrdma_qp *qp, struct ib_wc *ibwc,
                pr_err("%s() invalid opcode received = 0x%x\n",
                       __func__, hdr->cw & OCRDMA_WQE_OPCODE_MASK);
                break;
-       };
+       }
 }
 
 static void ocrdma_set_cqe_status_flushed(struct ocrdma_qp *qp,
index 4caa8e6d59d7968584e23a9187bc07f8c81df321..2d2b1b7588d7e476b7fc814a63c82bad2edb1ed6 100644 (file)
@@ -269,6 +269,14 @@ static chunk_t area_location(struct pstore *ps, chunk_t area)
        return NUM_SNAPSHOT_HDR_CHUNKS + ((ps->exceptions_per_area + 1) * area);
 }
 
+static void skip_metadata(struct pstore *ps)
+{
+       uint32_t stride = ps->exceptions_per_area + 1;
+       chunk_t next_free = ps->next_free;
+       if (sector_div(next_free, stride) == NUM_SNAPSHOT_HDR_CHUNKS)
+               ps->next_free++;
+}
+
 /*
  * Read or write a metadata area.  Remembering to skip the first
  * chunk which holds the header.
@@ -502,6 +510,8 @@ static int read_exceptions(struct pstore *ps,
 
        ps->current_area--;
 
+       skip_metadata(ps);
+
        return 0;
 }
 
@@ -616,8 +626,6 @@ static int persistent_prepare_exception(struct dm_exception_store *store,
                                        struct dm_exception *e)
 {
        struct pstore *ps = get_info(store);
-       uint32_t stride;
-       chunk_t next_free;
        sector_t size = get_dev_size(dm_snap_cow(store->snap)->bdev);
 
        /* Is there enough room ? */
@@ -630,10 +638,8 @@ static int persistent_prepare_exception(struct dm_exception_store *store,
         * Move onto the next free pending, making sure to take
         * into account the location of the metadata chunks.
         */
-       stride = (ps->exceptions_per_area + 1);
-       next_free = ++ps->next_free;
-       if (sector_div(next_free, stride) == 1)
-               ps->next_free++;
+       ps->next_free++;
+       skip_metadata(ps);
 
        atomic_inc(&ps->pending_count);
        return 0;
index 5ac3aa48473be0364d70eeae84a7a423b1a3be4d..022b1863d36cdf5af689be720a972baef3a54820 100644 (file)
@@ -569,13 +569,25 @@ static struct mfd_cell early_devs[] = {
        { .name = "arizona-ldo1" },
 };
 
+static const char *wm5102_supplies[] = {
+       "DBVDD2",
+       "DBVDD3",
+       "CPVDD",
+       "SPKVDDL",
+       "SPKVDDR",
+};
+
 static struct mfd_cell wm5102_devs[] = {
        { .name = "arizona-micsupp" },
        { .name = "arizona-extcon" },
        { .name = "arizona-gpio" },
        { .name = "arizona-haptics" },
        { .name = "arizona-pwm" },
-       { .name = "wm5102-codec" },
+       {
+               .name = "wm5102-codec",
+               .parent_supplies = wm5102_supplies,
+               .num_parent_supplies = ARRAY_SIZE(wm5102_supplies),
+       },
 };
 
 static struct mfd_cell wm5110_devs[] = {
@@ -584,7 +596,17 @@ static struct mfd_cell wm5110_devs[] = {
        { .name = "arizona-gpio" },
        { .name = "arizona-haptics" },
        { .name = "arizona-pwm" },
-       { .name = "wm5110-codec" },
+       {
+               .name = "wm5110-codec",
+               .parent_supplies = wm5102_supplies,
+               .num_parent_supplies = ARRAY_SIZE(wm5102_supplies),
+       },
+};
+
+static const char *wm8997_supplies[] = {
+       "DBVDD2",
+       "CPVDD",
+       "SPKVDD",
 };
 
 static struct mfd_cell wm8997_devs[] = {
@@ -593,7 +615,11 @@ static struct mfd_cell wm8997_devs[] = {
        { .name = "arizona-gpio" },
        { .name = "arizona-haptics" },
        { .name = "arizona-pwm" },
-       { .name = "wm8997-codec" },
+       {
+               .name = "wm8997-codec",
+               .parent_supplies = wm8997_supplies,
+               .num_parent_supplies = ARRAY_SIZE(wm8997_supplies),
+       },
 };
 
 int arizona_dev_init(struct arizona *arizona)
index f421586f29fb09b02644ee8b05aa6777fb353835..adc8ea36e7c483e5f9ee05e1587d3fd1b6029719 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/module.h>
 #include <linux/irqdomain.h>
 #include <linux/of.h>
+#include <linux/regulator/consumer.h>
 
 static struct device_type mfd_dev_type = {
        .name   = "mfd_device",
@@ -99,6 +100,13 @@ static int mfd_add_device(struct device *parent, int id,
        pdev->dev.dma_mask = parent->dma_mask;
        pdev->dev.dma_parms = parent->dma_parms;
 
+       ret = devm_regulator_bulk_register_supply_alias(
+                       &pdev->dev, cell->parent_supplies,
+                       parent, cell->parent_supplies,
+                       cell->num_parent_supplies);
+       if (ret < 0)
+               goto fail_res;
+
        if (parent->of_node && cell->of_compatible) {
                for_each_child_of_node(parent->of_node, np) {
                        if (of_device_is_compatible(np, cell->of_compatible)) {
@@ -112,12 +120,12 @@ static int mfd_add_device(struct device *parent, int id,
                ret = platform_device_add_data(pdev,
                                        cell->platform_data, cell->pdata_size);
                if (ret)
-                       goto fail_res;
+                       goto fail_alias;
        }
 
        ret = mfd_platform_add_cell(pdev, cell);
        if (ret)
-               goto fail_res;
+               goto fail_alias;
 
        for (r = 0; r < cell->num_resources; r++) {
                res[r].name = cell->resources[r].name;
@@ -152,17 +160,17 @@ static int mfd_add_device(struct device *parent, int id,
                if (!cell->ignore_resource_conflicts) {
                        ret = acpi_check_resource_conflict(&res[r]);
                        if (ret)
-                               goto fail_res;
+                               goto fail_alias;
                }
        }
 
        ret = platform_device_add_resources(pdev, res, cell->num_resources);
        if (ret)
-               goto fail_res;
+               goto fail_alias;
 
        ret = platform_device_add(pdev);
        if (ret)
-               goto fail_res;
+               goto fail_alias;
 
        if (cell->pm_runtime_no_callbacks)
                pm_runtime_no_callbacks(&pdev->dev);
@@ -171,6 +179,10 @@ static int mfd_add_device(struct device *parent, int id,
 
        return 0;
 
+fail_alias:
+       devm_regulator_bulk_unregister_supply_alias(&pdev->dev,
+                                                   cell->parent_supplies,
+                                                   cell->num_parent_supplies);
 fail_res:
        kfree(res);
 fail_device:
index 5472cbd34028d9038539824c4167a0c3010a3a01..6ca30739625f7ac568d693b5d4b9d3d9e47b46de 100644 (file)
@@ -180,28 +180,32 @@ static int verify_block_sig(struct mlx5_cmd_prot_block *block)
        return 0;
 }
 
-static void calc_block_sig(struct mlx5_cmd_prot_block *block, u8 token)
+static void calc_block_sig(struct mlx5_cmd_prot_block *block, u8 token,
+                          int csum)
 {
        block->token = token;
-       block->ctrl_sig = ~xor8_buf(block->rsvd0, sizeof(*block) - sizeof(block->data) - 2);
-       block->sig = ~xor8_buf(block, sizeof(*block) - 1);
+       if (csum) {
+               block->ctrl_sig = ~xor8_buf(block->rsvd0, sizeof(*block) -
+                                           sizeof(block->data) - 2);
+               block->sig = ~xor8_buf(block, sizeof(*block) - 1);
+       }
 }
 
-static void calc_chain_sig(struct mlx5_cmd_msg *msg, u8 token)
+static void calc_chain_sig(struct mlx5_cmd_msg *msg, u8 token, int csum)
 {
        struct mlx5_cmd_mailbox *next = msg->next;
 
        while (next) {
-               calc_block_sig(next->buf, token);
+               calc_block_sig(next->buf, token, csum);
                next = next->next;
        }
 }
 
-static void set_signature(struct mlx5_cmd_work_ent *ent)
+static void set_signature(struct mlx5_cmd_work_ent *ent, int csum)
 {
        ent->lay->sig = ~xor8_buf(ent->lay, sizeof(*ent->lay));
-       calc_chain_sig(ent->in, ent->token);
-       calc_chain_sig(ent->out, ent->token);
+       calc_chain_sig(ent->in, ent->token, csum);
+       calc_chain_sig(ent->out, ent->token, csum);
 }
 
 static void poll_timeout(struct mlx5_cmd_work_ent *ent)
@@ -539,8 +543,7 @@ static void cmd_work_handler(struct work_struct *work)
        lay->type = MLX5_PCI_CMD_XPORT;
        lay->token = ent->token;
        lay->status_own = CMD_OWNER_HW;
-       if (!cmd->checksum_disabled)
-               set_signature(ent);
+       set_signature(ent, !cmd->checksum_disabled);
        dump_command(dev, ent, 1);
        ktime_get_ts(&ent->ts1);
 
@@ -773,8 +776,6 @@ static int mlx5_copy_from_msg(void *to, struct mlx5_cmd_msg *from, int size)
 
                copy = min_t(int, size, MLX5_CMD_DATA_BLOCK_SIZE);
                block = next->buf;
-               if (xor8_buf(block, sizeof(*block)) != 0xff)
-                       return -EINVAL;
 
                memcpy(to, block->data, copy);
                to += copy;
@@ -1361,6 +1362,7 @@ int mlx5_cmd_init(struct mlx5_core_dev *dev)
                goto err_map;
        }
 
+       cmd->checksum_disabled = 1;
        cmd->max_reg_cmds = (1 << cmd->log_sz) - 1;
        cmd->bitmask = (1 << cmd->max_reg_cmds) - 1;
 
@@ -1510,7 +1512,7 @@ int mlx5_cmd_status_to_err(struct mlx5_outbox_hdr *hdr)
        case MLX5_CMD_STAT_BAD_SYS_STATE_ERR:           return -EIO;
        case MLX5_CMD_STAT_BAD_RES_ERR:                 return -EINVAL;
        case MLX5_CMD_STAT_RES_BUSY:                    return -EBUSY;
-       case MLX5_CMD_STAT_LIM_ERR:                     return -EINVAL;
+       case MLX5_CMD_STAT_LIM_ERR:                     return -ENOMEM;
        case MLX5_CMD_STAT_BAD_RES_STATE_ERR:           return -EINVAL;
        case MLX5_CMD_STAT_IX_ERR:                      return -EINVAL;
        case MLX5_CMD_STAT_NO_RES_ERR:                  return -EAGAIN;
index 443cc4d7b024c02d2cc77861868e1c1b17ee2524..2231d93cc7ad116e55c77e0269fa27878f6c6a4d 100644 (file)
@@ -366,9 +366,11 @@ int mlx5_create_map_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq, u8 vecidx,
                goto err_in;
        }
 
+       snprintf(eq->name, MLX5_MAX_EQ_NAME, "%s@pci:%s",
+                name, pci_name(dev->pdev));
        eq->eqn = out.eq_number;
        err = request_irq(table->msix_arr[vecidx].vector, mlx5_msix_handler, 0,
-                         name, eq);
+                         eq->name, eq);
        if (err)
                goto err_eq;
 
index b47739b0b5f6dfb34139ad74e02ac10db1d4fbbd..bc0f5fb66e249dc2e652b4126f9b907707b87c6c 100644 (file)
@@ -165,9 +165,7 @@ static int handle_hca_cap(struct mlx5_core_dev *dev)
        struct mlx5_cmd_set_hca_cap_mbox_in *set_ctx = NULL;
        struct mlx5_cmd_query_hca_cap_mbox_in query_ctx;
        struct mlx5_cmd_set_hca_cap_mbox_out set_out;
-       struct mlx5_profile *prof = dev->profile;
        u64 flags;
-       int csum = 1;
        int err;
 
        memset(&query_ctx, 0, sizeof(query_ctx));
@@ -197,20 +195,14 @@ static int handle_hca_cap(struct mlx5_core_dev *dev)
        memcpy(&set_ctx->hca_cap, &query_out->hca_cap,
               sizeof(set_ctx->hca_cap));
 
-       if (prof->mask & MLX5_PROF_MASK_CMDIF_CSUM) {
-               csum = !!prof->cmdif_csum;
-               flags = be64_to_cpu(set_ctx->hca_cap.flags);
-               if (csum)
-                       flags |= MLX5_DEV_CAP_FLAG_CMDIF_CSUM;
-               else
-                       flags &= ~MLX5_DEV_CAP_FLAG_CMDIF_CSUM;
-
-               set_ctx->hca_cap.flags = cpu_to_be64(flags);
-       }
-
        if (dev->profile->mask & MLX5_PROF_MASK_QP_SIZE)
                set_ctx->hca_cap.log_max_qp = dev->profile->log_max_qp;
 
+       flags = be64_to_cpu(query_out->hca_cap.flags);
+       /* disable checksum */
+       flags &= ~MLX5_DEV_CAP_FLAG_CMDIF_CSUM;
+
+       set_ctx->hca_cap.flags = cpu_to_be64(flags);
        memset(&set_out, 0, sizeof(set_out));
        set_ctx->hca_cap.log_uar_page_sz = cpu_to_be16(PAGE_SHIFT - 12);
        set_ctx->hdr.opcode = cpu_to_be16(MLX5_CMD_OP_SET_HCA_CAP);
@@ -225,9 +217,6 @@ static int handle_hca_cap(struct mlx5_core_dev *dev)
        if (err)
                goto query_ex;
 
-       if (!csum)
-               dev->cmd.checksum_disabled = 1;
-
 query_ex:
        kfree(query_out);
        kfree(set_ctx);
index 3a2408d448203623754d0aa87e35c16e809da43f..7b12acf210f81cd408a4b0e8a965fd4441165c9f 100644 (file)
@@ -90,6 +90,10 @@ struct mlx5_manage_pages_outbox {
        __be64                  pas[0];
 };
 
+enum {
+       MAX_RECLAIM_TIME_MSECS  = 5000,
+};
+
 static int insert_page(struct mlx5_core_dev *dev, u64 addr, struct page *page, u16 func_id)
 {
        struct rb_root *root = &dev->priv.page_root;
@@ -279,6 +283,9 @@ static int reclaim_pages(struct mlx5_core_dev *dev, u32 func_id, int npages,
        int err;
        int i;
 
+       if (nclaimed)
+               *nclaimed = 0;
+
        memset(&in, 0, sizeof(in));
        outlen = sizeof(*out) + npages * sizeof(out->pas[0]);
        out = mlx5_vzalloc(outlen);
@@ -388,20 +395,25 @@ static int optimal_reclaimed_pages(void)
 
 int mlx5_reclaim_startup_pages(struct mlx5_core_dev *dev)
 {
-       unsigned long end = jiffies + msecs_to_jiffies(5000);
+       unsigned long end = jiffies + msecs_to_jiffies(MAX_RECLAIM_TIME_MSECS);
        struct fw_page *fwp;
        struct rb_node *p;
+       int nclaimed = 0;
        int err;
 
        do {
                p = rb_first(&dev->priv.page_root);
                if (p) {
                        fwp = rb_entry(p, struct fw_page, rb_node);
-                       err = reclaim_pages(dev, fwp->func_id, optimal_reclaimed_pages(), NULL);
+                       err = reclaim_pages(dev, fwp->func_id,
+                                           optimal_reclaimed_pages(),
+                                           &nclaimed);
                        if (err) {
                                mlx5_core_warn(dev, "failed reclaiming pages (%d)\n", err);
                                return err;
                        }
+                       if (nclaimed)
+                               end = jiffies + msecs_to_jiffies(MAX_RECLAIM_TIME_MSECS);
                }
                if (time_after(jiffies, end)) {
                        mlx5_core_warn(dev, "FW did not return all pages. giving up...\n");
index 9d2009a9004d14bc6f80bc9e6192a478fc9362aa..78cc76053328c2c8c70bff559f5dc0f903a241df 100644 (file)
@@ -74,10 +74,4 @@ config OF_MTD
        depends on MTD
        def_bool y
 
-config OF_RESERVED_MEM
-       depends on OF_FLATTREE && (DMA_CMA || (HAVE_GENERIC_DMA_COHERENT && HAVE_MEMBLOCK))
-       def_bool y
-       help
-         Initialization code for DMA reserved memory
-
 endmenu # OF
index ed9660adad7751357b49914fcb046fa64470767c..efd05102c40533100794b7d6a7626f583a1f0cdc 100644 (file)
@@ -9,4 +9,3 @@ obj-$(CONFIG_OF_MDIO)   += of_mdio.o
 obj-$(CONFIG_OF_PCI)   += of_pci.o
 obj-$(CONFIG_OF_PCI_IRQ)  += of_pci_irq.o
 obj-$(CONFIG_OF_MTD)   += of_mtd.o
-obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o
index 865d3f66c86b2735810e1f6d4d7a219dfd9b350e..7d4c70f859e30687bcd0892c195f9cbfc34826dc 100644 (file)
@@ -303,10 +303,8 @@ struct device_node *of_get_cpu_node(int cpu, unsigned int *thread)
        struct device_node *cpun, *cpus;
 
        cpus = of_find_node_by_path("/cpus");
-       if (!cpus) {
-               pr_warn("Missing cpus node, bailing out\n");
+       if (!cpus)
                return NULL;
-       }
 
        for_each_child_of_node(cpus, cpun) {
                if (of_node_cmp(cpun->type, "cpu"))
index 229dd9d69e180529cc7e3135d71001421ab9deea..a4fa9ad31b8f7cfb62f45abf47ada0649d87b867 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
-#include <linux/random.h>
 
 #include <asm/setup.h>  /* for COMMAND_LINE_SIZE */
 #ifdef CONFIG_PPC
@@ -803,14 +802,3 @@ void __init unflatten_device_tree(void)
 }
 
 #endif /* CONFIG_OF_EARLY_FLATTREE */
-
-/* Feed entire flattened device tree into the random pool */
-static int __init add_fdt_randomness(void)
-{
-       if (initial_boot_params)
-               add_device_randomness(initial_boot_params,
-                               be32_to_cpu(initial_boot_params->totalsize));
-
-       return 0;
-}
-core_initcall(add_fdt_randomness);
diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c
deleted file mode 100644 (file)
index 0fe40c7..0000000
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Device tree based initialization code for reserved memory.
- *
- * Copyright (c) 2013 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- * Author: Marek Szyprowski <m.szyprowski@samsung.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License or (at your optional) any later version of the license.
- */
-
-#include <linux/memblock.h>
-#include <linux/err.h>
-#include <linux/of.h>
-#include <linux/of_fdt.h>
-#include <linux/of_platform.h>
-#include <linux/mm.h>
-#include <linux/sizes.h>
-#include <linux/mm_types.h>
-#include <linux/dma-contiguous.h>
-#include <linux/dma-mapping.h>
-#include <linux/of_reserved_mem.h>
-
-#define MAX_RESERVED_REGIONS   16
-struct reserved_mem {
-       phys_addr_t             base;
-       unsigned long           size;
-       struct cma              *cma;
-       char                    name[32];
-};
-static struct reserved_mem reserved_mem[MAX_RESERVED_REGIONS];
-static int reserved_mem_count;
-
-static int __init fdt_scan_reserved_mem(unsigned long node, const char *uname,
-                                       int depth, void *data)
-{
-       struct reserved_mem *rmem = &reserved_mem[reserved_mem_count];
-       phys_addr_t base, size;
-       int is_cma, is_reserved;
-       unsigned long len;
-       const char *status;
-       __be32 *prop;
-
-       is_cma = IS_ENABLED(CONFIG_DMA_CMA) &&
-              of_flat_dt_is_compatible(node, "linux,contiguous-memory-region");
-       is_reserved = of_flat_dt_is_compatible(node, "reserved-memory-region");
-
-       if (!is_reserved && !is_cma) {
-               /* ignore node and scan next one */
-               return 0;
-       }
-
-       status = of_get_flat_dt_prop(node, "status", &len);
-       if (status && strcmp(status, "okay") != 0) {
-               /* ignore disabled node nad scan next one */
-               return 0;
-       }
-
-       prop = of_get_flat_dt_prop(node, "reg", &len);
-       if (!prop || (len < (dt_root_size_cells + dt_root_addr_cells) *
-                            sizeof(__be32))) {
-               pr_err("Reserved mem: node %s, incorrect \"reg\" property\n",
-                      uname);
-               /* ignore node and scan next one */
-               return 0;
-       }
-       base = dt_mem_next_cell(dt_root_addr_cells, &prop);
-       size = dt_mem_next_cell(dt_root_size_cells, &prop);
-
-       if (!size) {
-               /* ignore node and scan next one */
-               return 0;
-       }
-
-       pr_info("Reserved mem: found %s, memory base %lx, size %ld MiB\n",
-               uname, (unsigned long)base, (unsigned long)size / SZ_1M);
-
-       if (reserved_mem_count == ARRAY_SIZE(reserved_mem))
-               return -ENOSPC;
-
-       rmem->base = base;
-       rmem->size = size;
-       strlcpy(rmem->name, uname, sizeof(rmem->name));
-
-       if (is_cma) {
-               struct cma *cma;
-               if (dma_contiguous_reserve_area(size, base, 0, &cma) == 0) {
-                       rmem->cma = cma;
-                       reserved_mem_count++;
-                       if (of_get_flat_dt_prop(node,
-                                               "linux,default-contiguous-region",
-                                               NULL))
-                               dma_contiguous_set_default(cma);
-               }
-       } else if (is_reserved) {
-               if (memblock_remove(base, size) == 0)
-                       reserved_mem_count++;
-               else
-                       pr_err("Failed to reserve memory for %s\n", uname);
-       }
-
-       return 0;
-}
-
-static struct reserved_mem *get_dma_memory_region(struct device *dev)
-{
-       struct device_node *node;
-       const char *name;
-       int i;
-
-       node = of_parse_phandle(dev->of_node, "memory-region", 0);
-       if (!node)
-               return NULL;
-
-       name = kbasename(node->full_name);
-       for (i = 0; i < reserved_mem_count; i++)
-               if (strcmp(name, reserved_mem[i].name) == 0)
-                       return &reserved_mem[i];
-       return NULL;
-}
-
-/**
- * of_reserved_mem_device_init() - assign reserved memory region to given device
- *
- * This function assign memory region pointed by "memory-region" device tree
- * property to the given device.
- */
-void of_reserved_mem_device_init(struct device *dev)
-{
-       struct reserved_mem *region = get_dma_memory_region(dev);
-       if (!region)
-               return;
-
-       if (region->cma) {
-               dev_set_cma_area(dev, region->cma);
-               pr_info("Assigned CMA %s to %s device\n", region->name,
-                       dev_name(dev));
-       } else {
-               if (dma_declare_coherent_memory(dev, region->base, region->base,
-                   region->size, DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE) != 0)
-                       pr_info("Declared reserved memory %s to %s device\n",
-                               region->name, dev_name(dev));
-       }
-}
-
-/**
- * of_reserved_mem_device_release() - release reserved memory device structures
- *
- * This function releases structures allocated for memory region handling for
- * the given device.
- */
-void of_reserved_mem_device_release(struct device *dev)
-{
-       struct reserved_mem *region = get_dma_memory_region(dev);
-       if (!region && !region->cma)
-               dma_release_declared_memory(dev);
-}
-
-/**
- * early_init_dt_scan_reserved_mem() - create reserved memory regions
- *
- * This function grabs memory from early allocator for device exclusive use
- * defined in device tree structures. It should be called by arch specific code
- * once the early allocator (memblock) has been activated and all other
- * subsystems have already allocated/reserved memory.
- */
-void __init early_init_dt_scan_reserved_mem(void)
-{
-       of_scan_flat_dt_by_path("/memory/reserved-memory",
-                               fdt_scan_reserved_mem, NULL);
-}
index 9b439ac63d8e73eef85aa490d5cab6ec825120b7..f6dcde22082155577b3cdf0b0f55f103e059cae6 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/of_device.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
-#include <linux/of_reserved_mem.h>
 #include <linux/platform_device.h>
 
 const struct of_device_id of_default_bus_match_table[] = {
@@ -219,8 +218,6 @@ static struct platform_device *of_platform_device_create_pdata(
        dev->dev.bus = &platform_bus_type;
        dev->dev.platform_data = platform_data;
 
-       of_reserved_mem_device_init(&dev->dev);
-
        /* We do not fill the DMA ops for platform devices by default.
         * This is currently the responsibility of the platform code
         * to do such, possibly using a device notifier
@@ -228,7 +225,6 @@ static struct platform_device *of_platform_device_create_pdata(
 
        if (of_device_add(dev) != 0) {
                platform_device_put(dev);
-               of_reserved_mem_device_release(&dev->dev);
                return NULL;
        }
 
index 0b7d23b4ad954489b657480d0ee08a3b7b2d81d8..be12fbfcae1042e90c00d192bffe46c47821b6c4 100644 (file)
@@ -994,14 +994,16 @@ void acpiphp_enumerate_slots(struct pci_bus *bus)
 
                /*
                 * This bridge should have been registered as a hotplug function
-                * under its parent, so the context has to be there.  If not, we
-                * are in deep goo.
+                * under its parent, so the context should be there, unless the
+                * parent is going to be handled by pciehp, in which case this
+                * bridge is not interesting to us either.
                 */
                mutex_lock(&acpiphp_context_lock);
                context = acpiphp_get_context(handle);
-               if (WARN_ON(!context)) {
+               if (!context) {
                        mutex_unlock(&acpiphp_context_lock);
                        put_device(&bus->dev);
+                       pci_dev_put(bridge->pci_dev);
                        kfree(bridge);
                        return;
                }
index 3459f60dcfd1c7dfc67aa641edd49f697ffb8b94..d333f7eac106f1ae9cab88f0850f2fc4ca03c19f 100644 (file)
@@ -141,18 +141,14 @@ struct pm800_regulators {
 
 /* Ranges are sorted in ascending order. */
 static const struct regulator_linear_range buck1_volt_range[] = {
-       { .min_uV = 600000, .max_uV = 1587500, .min_sel = 0, .max_sel = 0x4f,
-         .uV_step = 12500 },
-       { .min_uV = 1600000, .max_uV = 1800000, .min_sel = 0x50,
-         .max_sel = 0x54, .uV_step = 50000 },
+       REGULATOR_LINEAR_RANGE(600000, 0, 0x4f, 12500),
+       REGULATOR_LINEAR_RANGE(1600000, 0x50, 0x54, 50000),
 };
 
 /* BUCK 2~5 have same ranges. */
 static const struct regulator_linear_range buck2_5_volt_range[] = {
-       { .min_uV = 600000, .max_uV = 1587500,  .min_sel = 0, .max_sel = 0x4f,
-         .uV_step = 12500 },
-       { .min_uV = 1600000, .max_uV = 3300000, .min_sel = 0x50,
-         .max_sel = 0x72, .uV_step = 50000 },
+       REGULATOR_LINEAR_RANGE(600000, 0, 0x4f, 12500),
+       REGULATOR_LINEAR_RANGE(1600000, 0x50, 0x72, 50000),
 };
 
 static const unsigned int ldo1_volt_table[] = {
index 70230974468cb97ae9c76fe9fdb69ebc04e13560..f704d83c93c4a95fc729cc48c510611d4b5cd33f 100644 (file)
@@ -391,7 +391,8 @@ static int pm8607_regulator_probe(struct platform_device *pdev)
        else
                config.regmap = chip->regmap_companion;
 
-       info->regulator = regulator_register(&info->desc, &config);
+       info->regulator = devm_regulator_register(&pdev->dev, &info->desc,
+                                                 &config);
        if (IS_ERR(info->regulator)) {
                dev_err(&pdev->dev, "failed to register regulator %s\n",
                        info->desc.name);
@@ -402,14 +403,6 @@ static int pm8607_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int pm8607_regulator_remove(struct platform_device *pdev)
-{
-       struct pm8607_regulator_info *info = platform_get_drvdata(pdev);
-
-       regulator_unregister(info->regulator);
-       return 0;
-}
-
 static struct platform_device_id pm8607_regulator_driver_ids[] = {
        {
                .name   = "88pm860x-regulator",
@@ -428,7 +421,6 @@ static struct platform_driver pm8607_regulator_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = pm8607_regulator_probe,
-       .remove         = pm8607_regulator_remove,
        .id_table       = pm8607_regulator_driver_ids,
 };
 
index dfe58096b374a22fbeb001a1f430cb6afb2d1461..ce785f481281d2532dca6514e07a304ccfcb7b04 100644 (file)
@@ -28,16 +28,6 @@ config REGULATOR_DEBUG
        help
          Say yes here to enable debugging support.
 
-config REGULATOR_DUMMY
-       bool "Provide a dummy regulator if regulator lookups fail"
-       help
-         If this option is enabled then when a regulator lookup fails
-         and the board has not specified that it has provided full
-         constraints the regulator core will provide an always
-         enabled dummy regulator, allowing consumer drivers to continue.
-
-         A warning will be generated when this substitution is done.
-
 config REGULATOR_FIXED_VOLTAGE
        tristate "Fixed voltage regulator support"
        help
@@ -133,6 +123,14 @@ config REGULATOR_AS3711
          This driver provides support for the voltage regulators on the
          AS3711 PMIC
 
+config REGULATOR_AS3722
+       tristate "AMS AS3722 PMIC Regulators"
+       depends on MFD_AS3722
+       help
+         This driver provides support for the voltage regulators on the
+         AS3722 PMIC. This will enable support for all the software
+         controllable DCDC/LDO regulators.
+
 config REGULATOR_DA903X
        tristate "Dialog Semiconductor DA9030/DA9034 regulators"
        depends on PMIC_DA903X
@@ -429,6 +427,14 @@ config REGULATOR_TI_ABB
          on TI SoCs may be unstable without enabling this as it provides
          device specific optimized bias to allow/optimize functionality.
 
+config REGULATOR_STW481X_VMMC
+       bool "ST Microelectronics STW481X VMMC regulator"
+       depends on MFD_STW481X
+       default y if MFD_STW481X
+       help
+         This driver supports the internal VMMC regulator in the STw481x
+         PMIC chips.
+
 config REGULATOR_TPS51632
        tristate "TI TPS51632 Power Regulator"
        depends on I2C
index 185cce246022d25f510ae5bd247a81acf3605882..01c597ea17441353dfbeded58ac2db4da7810bc8 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 
-obj-$(CONFIG_REGULATOR) += core.o dummy.o fixed-helper.o helpers.o
+obj-$(CONFIG_REGULATOR) += core.o dummy.o fixed-helper.o helpers.o devres.o
 obj-$(CONFIG_OF) += of_regulator.o
 obj-$(CONFIG_REGULATOR_FIXED_VOLTAGE) += fixed.o
 obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o
@@ -18,6 +18,7 @@ obj-$(CONFIG_REGULATOR_AD5398) += ad5398.o
 obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o
 obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o arizona-ldo1.o
 obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o
+obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o
 obj-$(CONFIG_REGULATOR_DA903X) += da903x.o
 obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o
 obj-$(CONFIG_REGULATOR_DA9055) += da9055-regulator.o
@@ -56,6 +57,7 @@ obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
 obj-$(CONFIG_REGULATOR_RC5T583)  += rc5t583-regulator.o
 obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o
 obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
+obj-$(CONFIG_REGULATOR_STW481X_VMMC) += stw481x-vmmc.o
 obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o
 obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o
 obj-$(CONFIG_REGULATOR_TPS62360) += tps62360-regulator.o
index 881159dfcb5e70fc3532d7a9ccc20cad99354459..f70a9bfa5ff2e9b4845d9493e3cbda9cb012e042 100644 (file)
@@ -176,7 +176,7 @@ static int aat2870_regulator_probe(struct platform_device *pdev)
        config.driver_data = ri;
        config.init_data = dev_get_platdata(&pdev->dev);
 
-       rdev = regulator_register(&ri->desc, &config);
+       rdev = devm_regulator_register(&pdev->dev, &ri->desc, &config);
        if (IS_ERR(rdev)) {
                dev_err(&pdev->dev, "Failed to register regulator %s\n",
                        ri->desc.name);
@@ -187,21 +187,12 @@ static int aat2870_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int aat2870_regulator_remove(struct platform_device *pdev)
-{
-       struct regulator_dev *rdev = platform_get_drvdata(pdev);
-
-       regulator_unregister(rdev);
-       return 0;
-}
-
 static struct platform_driver aat2870_regulator_driver = {
        .driver = {
                .name   = "aat2870-regulator",
                .owner  = THIS_MODULE,
        },
        .probe  = aat2870_regulator_probe,
-       .remove = aat2870_regulator_remove,
 };
 
 static int __init aat2870_regulator_init(void)
index 7d5eaa874b2da9337e387b1271bd2e38a3d25d2e..77b46d0b37a604fa31f7b90fb270d8ac59023e0c 100644 (file)
@@ -535,7 +535,7 @@ static int ab3100_regulator_register(struct platform_device *pdev,
        config.dev = &pdev->dev;
        config.driver_data = reg;
 
-       rdev = regulator_register(desc, &config);
+       rdev = devm_regulator_register(&pdev->dev, desc, &config);
        if (IS_ERR(rdev)) {
                err = PTR_ERR(rdev);
                dev_err(&pdev->dev,
@@ -616,7 +616,6 @@ static int ab3100_regulators_remove(struct platform_device *pdev)
        for (i = 0; i < AB3100_NUM_REGULATORS; i++) {
                struct ab3100_regulator *reg = &ab3100_regulators[i];
 
-               regulator_unregister(reg->rdev);
                reg->rdev = NULL;
        }
        return 0;
index 02ff691cdb8b291b44ecc1569339a9251aa59987..29c0faaf8eba4e94f34d8848d91b7d0d85dea2ec 100644 (file)
@@ -413,16 +413,12 @@ static int ab8500_ext_regulator_probe(struct platform_device *pdev)
                        &pdata->ext_regulator[i];
 
                /* register regulator with framework */
-               info->rdev = regulator_register(&info->desc, &config);
+               info->rdev = devm_regulator_register(&pdev->dev, &info->desc,
+                                                    &config);
                if (IS_ERR(info->rdev)) {
                        err = PTR_ERR(info->rdev);
                        dev_err(&pdev->dev, "failed to register regulator %s\n",
                                        info->desc.name);
-                       /* when we fail, un-register all earlier regulators */
-                       while (--i >= 0) {
-                               info = &ab8500_ext_regulator_info[i];
-                               regulator_unregister(info->rdev);
-                       }
                        return err;
                }
 
@@ -433,26 +429,8 @@ static int ab8500_ext_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int ab8500_ext_regulator_remove(struct platform_device *pdev)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(ab8500_ext_regulator_info); i++) {
-               struct ab8500_ext_regulator_info *info = NULL;
-               info = &ab8500_ext_regulator_info[i];
-
-               dev_vdbg(rdev_get_dev(info->rdev),
-                       "%s-remove\n", info->desc.name);
-
-               regulator_unregister(info->rdev);
-       }
-
-       return 0;
-}
-
 static struct platform_driver ab8500_ext_regulator_driver = {
        .probe = ab8500_ext_regulator_probe,
-       .remove = ab8500_ext_regulator_remove,
        .driver         = {
                .name   = "ab8500-ext-regulator",
                .owner  = THIS_MODULE,
index b2b203cb6b2f9373a0d09f5773f3d912922614dd..48016a050d5fb9b9c19981075755bd3831be0652 100644 (file)
@@ -219,7 +219,6 @@ static int ad5398_probe(struct i2c_client *client,
        struct ad5398_chip_info *chip;
        const struct ad5398_current_data_format *df =
                        (struct ad5398_current_data_format *)id->driver_data;
-       int ret;
 
        if (!init_data)
                return -EINVAL;
@@ -240,33 +239,21 @@ static int ad5398_probe(struct i2c_client *client,
        chip->current_offset = df->current_offset;
        chip->current_mask = (chip->current_level - 1) << chip->current_offset;
 
-       chip->rdev = regulator_register(&ad5398_reg, &config);
+       chip->rdev = devm_regulator_register(&client->dev, &ad5398_reg,
+                                            &config);
        if (IS_ERR(chip->rdev)) {
-               ret = PTR_ERR(chip->rdev);
                dev_err(&client->dev, "failed to register %s %s\n",
                        id->name, ad5398_reg.name);
-               goto err;
+               return PTR_ERR(chip->rdev);
        }
 
        i2c_set_clientdata(client, chip);
        dev_dbg(&client->dev, "%s regulator driver is registered.\n", id->name);
        return 0;
-
-err:
-       return ret;
-}
-
-static int ad5398_remove(struct i2c_client *client)
-{
-       struct ad5398_chip_info *chip = i2c_get_clientdata(client);
-
-       regulator_unregister(chip->rdev);
-       return 0;
 }
 
 static struct i2c_driver ad5398_driver = {
        .probe = ad5398_probe,
-       .remove = ad5398_remove,
        .driver         = {
                .name   = "ad5398",
        },
index 0d4a8ccbb53616275bda7d8f4ca817d8d68ad104..c734d098082641a814488a67c505b15d912958d7 100644 (file)
@@ -200,7 +200,7 @@ static int anatop_regulator_probe(struct platform_device *pdev)
        config.regmap = sreg->anatop;
 
        /* register regulator */
-       rdev = regulator_register(rdesc, &config);
+       rdev = devm_regulator_register(dev, rdesc, &config);
        if (IS_ERR(rdev)) {
                dev_err(dev, "failed to register %s\n",
                        rdesc->name);
@@ -223,7 +223,6 @@ static int anatop_regulator_remove(struct platform_device *pdev)
        struct anatop_regulator *sreg = rdev_get_drvdata(rdev);
        const char *name = sreg->name;
 
-       regulator_unregister(rdev);
        kfree(name);
 
        return 0;
@@ -256,7 +255,7 @@ static void __exit anatop_regulator_exit(void)
 }
 module_exit(anatop_regulator_exit);
 
-MODULE_AUTHOR("Nancy Chen <Nancy.Chen@freescale.com>, "
-             "Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>");
+MODULE_AUTHOR("Nancy Chen <Nancy.Chen@freescale.com>");
+MODULE_AUTHOR("Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>");
 MODULE_DESCRIPTION("ANATOP Regulator driver");
 MODULE_LICENSE("GPL v2");
index 81d8681c31959557fa78a7121d64e85c957e719b..4f6c2055f6b210436a5c1a9565b9f302ecdd21da 100644 (file)
@@ -226,7 +226,7 @@ static int arizona_ldo1_probe(struct platform_device *pdev)
        else
                config.init_data = &ldo1->init_data;
 
-       ldo1->regulator = regulator_register(desc, &config);
+       ldo1->regulator = devm_regulator_register(&pdev->dev, desc, &config);
        if (IS_ERR(ldo1->regulator)) {
                ret = PTR_ERR(ldo1->regulator);
                dev_err(arizona->dev, "Failed to register LDO1 supply: %d\n",
@@ -239,18 +239,8 @@ static int arizona_ldo1_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int arizona_ldo1_remove(struct platform_device *pdev)
-{
-       struct arizona_ldo1 *ldo1 = platform_get_drvdata(pdev);
-
-       regulator_unregister(ldo1->regulator);
-
-       return 0;
-}
-
 static struct platform_driver arizona_ldo1_driver = {
        .probe = arizona_ldo1_probe,
-       .remove = arizona_ldo1_remove,
        .driver         = {
                .name   = "arizona-ldo1",
                .owner  = THIS_MODULE,
index e87536bf0bed038f09af9bc251c85d0b00fb6c97..724706a97dc40c5cf7e21d89f7c58bc2385f6226 100644 (file)
@@ -225,7 +225,9 @@ static int arizona_micsupp_probe(struct platform_device *pdev)
        regmap_update_bits(arizona->regmap, ARIZONA_MIC_CHARGE_PUMP_1,
                           ARIZONA_CPMIC_BYPASS, 0);
 
-       micsupp->regulator = regulator_register(&arizona_micsupp, &config);
+       micsupp->regulator = devm_regulator_register(&pdev->dev,
+                                                    &arizona_micsupp,
+                                                    &config);
        if (IS_ERR(micsupp->regulator)) {
                ret = PTR_ERR(micsupp->regulator);
                dev_err(arizona->dev, "Failed to register mic supply: %d\n",
@@ -238,18 +240,8 @@ static int arizona_micsupp_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int arizona_micsupp_remove(struct platform_device *pdev)
-{
-       struct arizona_micsupp *micsupp = platform_get_drvdata(pdev);
-
-       regulator_unregister(micsupp->regulator);
-
-       return 0;
-}
-
 static struct platform_driver arizona_micsupp_driver = {
        .probe = arizona_micsupp_probe,
-       .remove = arizona_micsupp_remove,
        .driver         = {
                .name   = "arizona-micsupp",
                .owner  = THIS_MODULE,
index 8406cd745da29e6a60a76624d1199516d7d46121..c77a58478cca6b11ffd2c5a69990eddda1900230 100644 (file)
@@ -117,26 +117,19 @@ static struct regulator_ops as3711_dldo_ops = {
 };
 
 static const struct regulator_linear_range as3711_sd_ranges[] = {
-       { .min_uV = 612500, .max_uV = 1400000,
-         .min_sel = 0x1, .max_sel = 0x40, .uV_step = 12500 },
-       { .min_uV = 1425000, .max_uV = 2600000,
-         .min_sel = 0x41, .max_sel = 0x70, .uV_step = 25000 },
-       { .min_uV = 2650000, .max_uV = 3350000,
-         .min_sel = 0x71, .max_sel = 0x7f, .uV_step = 50000 },
+       REGULATOR_LINEAR_RANGE(612500, 0x1, 0x40, 12500),
+       REGULATOR_LINEAR_RANGE(1425000, 0x41, 0x70, 25000),
+       REGULATOR_LINEAR_RANGE(2650000, 0x71, 0x7f, 50000),
 };
 
 static const struct regulator_linear_range as3711_aldo_ranges[] = {
-       { .min_uV = 1200000, .max_uV = 1950000,
-         .min_sel = 0, .max_sel = 0xf, .uV_step = 50000 },
-       { .min_uV = 1800000, .max_uV = 3300000,
-         .min_sel = 0x10, .max_sel = 0x1f, .uV_step = 100000 },
+       REGULATOR_LINEAR_RANGE(1200000, 0, 0xf, 50000),
+       REGULATOR_LINEAR_RANGE(1800000, 0x10, 0x1f, 100000),
 };
 
 static const struct regulator_linear_range as3711_dldo_ranges[] = {
-       { .min_uV = 900000, .max_uV = 1700000,
-         .min_sel = 0, .max_sel = 0x10, .uV_step = 50000 },
-       { .min_uV = 1750000, .max_uV = 3300000,
-         .min_sel = 0x20, .max_sel = 0x3f, .uV_step = 50000 },
+       REGULATOR_LINEAR_RANGE(900000, 0, 0x10, 50000),
+       REGULATOR_LINEAR_RANGE(1750000, 0x20, 0x3f, 50000),
 };
 
 #define AS3711_REG(_id, _en_reg, _en_bit, _vmask, _vshift, _min_uV, _max_uV, _sfx)     \
@@ -273,33 +266,16 @@ static int as3711_regulator_probe(struct platform_device *pdev)
                config.regmap = as3711->regmap;
                config.of_node = of_node[id];
 
-               rdev = regulator_register(&ri->desc, &config);
+               rdev = devm_regulator_register(&pdev->dev, &ri->desc, &config);
                if (IS_ERR(rdev)) {
                        dev_err(&pdev->dev, "Failed to register regulator %s\n",
                                ri->desc.name);
-                       ret = PTR_ERR(rdev);
-                       goto eregreg;
+                       return PTR_ERR(rdev);
                }
                reg->rdev = rdev;
        }
        platform_set_drvdata(pdev, regs);
        return 0;
-
-eregreg:
-       while (--id >= 0)
-               regulator_unregister(regs[id].rdev);
-
-       return ret;
-}
-
-static int as3711_regulator_remove(struct platform_device *pdev)
-{
-       struct as3711_regulator *regs = platform_get_drvdata(pdev);
-       int id;
-
-       for (id = 0; id < AS3711_REGULATOR_NUM; ++id)
-               regulator_unregister(regs[id].rdev);
-       return 0;
 }
 
 static struct platform_driver as3711_regulator_driver = {
@@ -308,7 +284,6 @@ static struct platform_driver as3711_regulator_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = as3711_regulator_probe,
-       .remove         = as3711_regulator_remove,
 };
 
 static int __init as3711_regulator_init(void)
diff --git a/drivers/regulator/as3722-regulator.c b/drivers/regulator/as3722-regulator.c
new file mode 100644 (file)
index 0000000..5917fe3
--- /dev/null
@@ -0,0 +1,908 @@
+/*
+ * Voltage regulator support for AMS AS3722 PMIC
+ *
+ * Copyright (C) 2013 ams
+ *
+ * Author: Florian Lobmaier <florian.lobmaier@ams.com>
+ * Author: Laxman Dewangan <ldewangan@nvidia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mfd/as3722.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/slab.h>
+
+/* Regulator IDs */
+enum as3722_regulators_id {
+       AS3722_REGULATOR_ID_SD0,
+       AS3722_REGULATOR_ID_SD1,
+       AS3722_REGULATOR_ID_SD2,
+       AS3722_REGULATOR_ID_SD3,
+       AS3722_REGULATOR_ID_SD4,
+       AS3722_REGULATOR_ID_SD5,
+       AS3722_REGULATOR_ID_SD6,
+       AS3722_REGULATOR_ID_LDO0,
+       AS3722_REGULATOR_ID_LDO1,
+       AS3722_REGULATOR_ID_LDO2,
+       AS3722_REGULATOR_ID_LDO3,
+       AS3722_REGULATOR_ID_LDO4,
+       AS3722_REGULATOR_ID_LDO5,
+       AS3722_REGULATOR_ID_LDO6,
+       AS3722_REGULATOR_ID_LDO7,
+       AS3722_REGULATOR_ID_LDO9,
+       AS3722_REGULATOR_ID_LDO10,
+       AS3722_REGULATOR_ID_LDO11,
+       AS3722_REGULATOR_ID_MAX,
+};
+
+struct as3722_register_mapping {
+       u8 regulator_id;
+       const char *name;
+       const char *sname;
+       u8 vsel_reg;
+       u8 vsel_mask;
+       int n_voltages;
+       u32 enable_reg;
+       u8 enable_mask;
+       u32 control_reg;
+       u8 mode_mask;
+       u32 sleep_ctrl_reg;
+       u8 sleep_ctrl_mask;
+};
+
+struct as3722_regulator_config_data {
+       struct regulator_init_data *reg_init;
+       bool enable_tracking;
+       int ext_control;
+};
+
+struct as3722_regulators {
+       struct device *dev;
+       struct as3722 *as3722;
+       struct regulator_dev *rdevs[AS3722_REGULATOR_ID_MAX];
+       struct regulator_desc desc[AS3722_REGULATOR_ID_MAX];
+       struct as3722_regulator_config_data
+                       reg_config_data[AS3722_REGULATOR_ID_MAX];
+};
+
+static const struct as3722_register_mapping as3722_reg_lookup[] = {
+       {
+               .regulator_id = AS3722_REGULATOR_ID_SD0,
+               .name = "as3722-sd0",
+               .vsel_reg = AS3722_SD0_VOLTAGE_REG,
+               .vsel_mask = AS3722_SD_VSEL_MASK,
+               .enable_reg = AS3722_SD_CONTROL_REG,
+               .enable_mask = AS3722_SDn_CTRL(0),
+               .sleep_ctrl_reg = AS3722_ENABLE_CTRL1_REG,
+               .sleep_ctrl_mask = AS3722_SD0_EXT_ENABLE_MASK,
+               .control_reg = AS3722_SD0_CONTROL_REG,
+               .mode_mask = AS3722_SD0_MODE_FAST,
+               .n_voltages = AS3722_SD0_VSEL_MAX + 1,
+       },
+       {
+               .regulator_id = AS3722_REGULATOR_ID_SD1,
+               .name = "as3722-sd1",
+               .vsel_reg = AS3722_SD1_VOLTAGE_REG,
+               .vsel_mask = AS3722_SD_VSEL_MASK,
+               .enable_reg = AS3722_SD_CONTROL_REG,
+               .enable_mask = AS3722_SDn_CTRL(1),
+               .sleep_ctrl_reg = AS3722_ENABLE_CTRL1_REG,
+               .sleep_ctrl_mask = AS3722_SD1_EXT_ENABLE_MASK,
+               .control_reg = AS3722_SD1_CONTROL_REG,
+               .mode_mask = AS3722_SD1_MODE_FAST,
+               .n_voltages = AS3722_SD0_VSEL_MAX + 1,
+       },
+       {
+               .regulator_id = AS3722_REGULATOR_ID_SD2,
+               .name = "as3722-sd2",
+               .sname = "vsup-sd2",
+               .vsel_reg = AS3722_SD2_VOLTAGE_REG,
+               .vsel_mask = AS3722_SD_VSEL_MASK,
+               .enable_reg = AS3722_SD_CONTROL_REG,
+               .enable_mask = AS3722_SDn_CTRL(2),
+               .sleep_ctrl_reg = AS3722_ENABLE_CTRL1_REG,
+               .sleep_ctrl_mask = AS3722_SD2_EXT_ENABLE_MASK,
+               .control_reg = AS3722_SD23_CONTROL_REG,
+               .mode_mask = AS3722_SD2_MODE_FAST,
+               .n_voltages = AS3722_SD2_VSEL_MAX + 1,
+       },
+       {
+               .regulator_id = AS3722_REGULATOR_ID_SD3,
+               .name = "as3722-sd3",
+               .sname = "vsup-sd3",
+               .vsel_reg = AS3722_SD3_VOLTAGE_REG,
+               .vsel_mask = AS3722_SD_VSEL_MASK,
+               .enable_reg = AS3722_SD_CONTROL_REG,
+               .enable_mask = AS3722_SDn_CTRL(3),
+               .sleep_ctrl_reg = AS3722_ENABLE_CTRL1_REG,
+               .sleep_ctrl_mask = AS3722_SD3_EXT_ENABLE_MASK,
+               .control_reg = AS3722_SD23_CONTROL_REG,
+               .mode_mask = AS3722_SD3_MODE_FAST,
+               .n_voltages = AS3722_SD2_VSEL_MAX + 1,
+       },
+       {
+               .regulator_id = AS3722_REGULATOR_ID_SD4,
+               .name = "as3722-sd4",
+               .sname = "vsup-sd4",
+               .vsel_reg = AS3722_SD4_VOLTAGE_REG,
+               .vsel_mask = AS3722_SD_VSEL_MASK,
+               .enable_reg = AS3722_SD_CONTROL_REG,
+               .enable_mask = AS3722_SDn_CTRL(4),
+               .sleep_ctrl_reg = AS3722_ENABLE_CTRL2_REG,
+               .sleep_ctrl_mask = AS3722_SD4_EXT_ENABLE_MASK,
+               .control_reg = AS3722_SD4_CONTROL_REG,
+               .mode_mask = AS3722_SD4_MODE_FAST,
+               .n_voltages = AS3722_SD2_VSEL_MAX + 1,
+       },
+       {
+               .regulator_id = AS3722_REGULATOR_ID_SD5,
+               .name = "as3722-sd5",
+               .sname = "vsup-sd5",
+               .vsel_reg = AS3722_SD5_VOLTAGE_REG,
+               .vsel_mask = AS3722_SD_VSEL_MASK,
+               .enable_reg = AS3722_SD_CONTROL_REG,
+               .enable_mask = AS3722_SDn_CTRL(5),
+               .sleep_ctrl_reg = AS3722_ENABLE_CTRL2_REG,
+               .sleep_ctrl_mask = AS3722_SD5_EXT_ENABLE_MASK,
+               .control_reg = AS3722_SD5_CONTROL_REG,
+               .mode_mask = AS3722_SD5_MODE_FAST,
+               .n_voltages = AS3722_SD2_VSEL_MAX + 1,
+       },
+       {
+               .regulator_id = AS3722_REGULATOR_ID_SD6,
+               .name = "as3722-sd6",
+               .vsel_reg = AS3722_SD6_VOLTAGE_REG,
+               .vsel_mask = AS3722_SD_VSEL_MASK,
+               .enable_reg = AS3722_SD_CONTROL_REG,
+               .enable_mask = AS3722_SDn_CTRL(6),
+               .sleep_ctrl_reg = AS3722_ENABLE_CTRL2_REG,
+               .sleep_ctrl_mask = AS3722_SD6_EXT_ENABLE_MASK,
+               .control_reg = AS3722_SD6_CONTROL_REG,
+               .mode_mask = AS3722_SD6_MODE_FAST,
+               .n_voltages = AS3722_SD0_VSEL_MAX + 1,
+       },
+       {
+               .regulator_id = AS3722_REGULATOR_ID_LDO0,
+               .name = "as3722-ldo0",
+               .sname = "vin-ldo0",
+               .vsel_reg = AS3722_LDO0_VOLTAGE_REG,
+               .vsel_mask = AS3722_LDO0_VSEL_MASK,
+               .enable_reg = AS3722_LDOCONTROL0_REG,
+               .enable_mask = AS3722_LDO0_CTRL,
+               .sleep_ctrl_reg = AS3722_ENABLE_CTRL3_REG,
+               .sleep_ctrl_mask = AS3722_LDO0_EXT_ENABLE_MASK,
+               .n_voltages = AS3722_LDO0_NUM_VOLT,
+       },
+       {
+               .regulator_id = AS3722_REGULATOR_ID_LDO1,
+               .name = "as3722-ldo1",
+               .sname = "vin-ldo1-6",
+               .vsel_reg = AS3722_LDO1_VOLTAGE_REG,
+               .vsel_mask = AS3722_LDO_VSEL_MASK,
+               .enable_reg = AS3722_LDOCONTROL0_REG,
+               .enable_mask = AS3722_LDO1_CTRL,
+               .sleep_ctrl_reg = AS3722_ENABLE_CTRL3_REG,
+               .sleep_ctrl_mask = AS3722_LDO1_EXT_ENABLE_MASK,
+               .n_voltages = AS3722_LDO_NUM_VOLT,
+       },
+       {
+               .regulator_id = AS3722_REGULATOR_ID_LDO2,
+               .name = "as3722-ldo2",
+               .sname = "vin-ldo2-5-7",
+               .vsel_reg = AS3722_LDO2_VOLTAGE_REG,
+               .vsel_mask = AS3722_LDO_VSEL_MASK,
+               .enable_reg = AS3722_LDOCONTROL0_REG,
+               .enable_mask = AS3722_LDO2_CTRL,
+               .sleep_ctrl_reg = AS3722_ENABLE_CTRL3_REG,
+               .sleep_ctrl_mask = AS3722_LDO2_EXT_ENABLE_MASK,
+               .n_voltages = AS3722_LDO_NUM_VOLT,
+       },
+       {
+               .regulator_id = AS3722_REGULATOR_ID_LDO3,
+               .name = "as3722-ldo3",
+               .name = "vin-ldo3-4",
+               .vsel_reg = AS3722_LDO3_VOLTAGE_REG,
+               .vsel_mask = AS3722_LDO3_VSEL_MASK,
+               .enable_reg = AS3722_LDOCONTROL0_REG,
+               .enable_mask = AS3722_LDO3_CTRL,
+               .sleep_ctrl_reg = AS3722_ENABLE_CTRL3_REG,
+               .sleep_ctrl_mask = AS3722_LDO3_EXT_ENABLE_MASK,
+               .n_voltages = AS3722_LDO3_NUM_VOLT,
+       },
+       {
+               .regulator_id = AS3722_REGULATOR_ID_LDO4,
+               .name = "as3722-ldo4",
+               .name = "vin-ldo3-4",
+               .vsel_reg = AS3722_LDO4_VOLTAGE_REG,
+               .vsel_mask = AS3722_LDO_VSEL_MASK,
+               .enable_reg = AS3722_LDOCONTROL0_REG,
+               .enable_mask = AS3722_LDO4_CTRL,
+               .sleep_ctrl_reg = AS3722_ENABLE_CTRL4_REG,
+               .sleep_ctrl_mask = AS3722_LDO4_EXT_ENABLE_MASK,
+               .n_voltages = AS3722_LDO_NUM_VOLT,
+       },
+       {
+               .regulator_id = AS3722_REGULATOR_ID_LDO5,
+               .name = "as3722-ldo5",
+               .sname = "vin-ldo2-5-7",
+               .vsel_reg = AS3722_LDO5_VOLTAGE_REG,
+               .vsel_mask = AS3722_LDO_VSEL_MASK,
+               .enable_reg = AS3722_LDOCONTROL0_REG,
+               .enable_mask = AS3722_LDO5_CTRL,
+               .sleep_ctrl_reg = AS3722_ENABLE_CTRL4_REG,
+               .sleep_ctrl_mask = AS3722_LDO5_EXT_ENABLE_MASK,
+               .n_voltages = AS3722_LDO_NUM_VOLT,
+       },
+       {
+               .regulator_id = AS3722_REGULATOR_ID_LDO6,
+               .name = "as3722-ldo6",
+               .sname = "vin-ldo1-6",
+               .vsel_reg = AS3722_LDO6_VOLTAGE_REG,
+               .vsel_mask = AS3722_LDO_VSEL_MASK,
+               .enable_reg = AS3722_LDOCONTROL0_REG,
+               .enable_mask = AS3722_LDO6_CTRL,
+               .sleep_ctrl_reg = AS3722_ENABLE_CTRL4_REG,
+               .sleep_ctrl_mask = AS3722_LDO6_EXT_ENABLE_MASK,
+               .n_voltages = AS3722_LDO_NUM_VOLT,
+       },
+       {
+               .regulator_id = AS3722_REGULATOR_ID_LDO7,
+               .name = "as3722-ldo7",
+               .sname = "vin-ldo2-5-7",
+               .vsel_reg = AS3722_LDO7_VOLTAGE_REG,
+               .vsel_mask = AS3722_LDO_VSEL_MASK,
+               .enable_reg = AS3722_LDOCONTROL0_REG,
+               .enable_mask = AS3722_LDO7_CTRL,
+               .sleep_ctrl_reg = AS3722_ENABLE_CTRL4_REG,
+               .sleep_ctrl_mask = AS3722_LDO7_EXT_ENABLE_MASK,
+               .n_voltages = AS3722_LDO_NUM_VOLT,
+       },
+       {
+               .regulator_id = AS3722_REGULATOR_ID_LDO9,
+               .name = "as3722-ldo9",
+               .sname = "vin-ldo9-10",
+               .vsel_reg = AS3722_LDO9_VOLTAGE_REG,
+               .vsel_mask = AS3722_LDO_VSEL_MASK,
+               .enable_reg = AS3722_LDOCONTROL1_REG,
+               .enable_mask = AS3722_LDO9_CTRL,
+               .sleep_ctrl_reg = AS3722_ENABLE_CTRL5_REG,
+               .sleep_ctrl_mask = AS3722_LDO9_EXT_ENABLE_MASK,
+               .n_voltages = AS3722_LDO_NUM_VOLT,
+       },
+       {
+               .regulator_id = AS3722_REGULATOR_ID_LDO10,
+               .name = "as3722-ldo10",
+               .sname = "vin-ldo9-10",
+               .vsel_reg = AS3722_LDO10_VOLTAGE_REG,
+               .vsel_mask = AS3722_LDO_VSEL_MASK,
+               .enable_reg = AS3722_LDOCONTROL1_REG,
+               .enable_mask = AS3722_LDO10_CTRL,
+               .sleep_ctrl_reg = AS3722_ENABLE_CTRL5_REG,
+               .sleep_ctrl_mask = AS3722_LDO10_EXT_ENABLE_MASK,
+               .n_voltages = AS3722_LDO_NUM_VOLT,
+       },
+       {
+               .regulator_id = AS3722_REGULATOR_ID_LDO11,
+               .name = "as3722-ldo11",
+               .sname = "vin-ldo11",
+               .vsel_reg = AS3722_LDO11_VOLTAGE_REG,
+               .vsel_mask = AS3722_LDO_VSEL_MASK,
+               .enable_reg = AS3722_LDOCONTROL1_REG,
+               .enable_mask = AS3722_LDO11_CTRL,
+               .sleep_ctrl_reg = AS3722_ENABLE_CTRL5_REG,
+               .sleep_ctrl_mask = AS3722_LDO11_EXT_ENABLE_MASK,
+               .n_voltages = AS3722_LDO_NUM_VOLT,
+       },
+};
+
+
+static const int as3722_ldo_current[] = { 150000, 300000 };
+static const int as3722_sd016_current[] = { 2500000, 3000000, 3500000 };
+
+static int as3722_current_to_index(int min_uA, int max_uA,
+               const int *curr_table, int n_currents)
+{
+       int i;
+
+       for (i = n_currents - 1; i >= 0; i--) {
+               if ((min_uA <= curr_table[i]) && (curr_table[i] <= max_uA))
+                       return i;
+       }
+       return -EINVAL;
+}
+
+static int as3722_ldo_get_current_limit(struct regulator_dev *rdev)
+{
+       struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev);
+       struct as3722 *as3722 = as3722_regs->as3722;
+       int id = rdev_get_id(rdev);
+       u32 val;
+       int ret;
+
+       ret = as3722_read(as3722, as3722_reg_lookup[id].vsel_reg, &val);
+       if (ret < 0) {
+               dev_err(as3722_regs->dev, "Reg 0x%02x read failed: %d\n",
+                       as3722_reg_lookup[id].vsel_reg, ret);
+               return ret;
+       }
+       if (val & AS3722_LDO_ILIMIT_MASK)
+               return 300000;
+       return 150000;
+}
+
+static int as3722_ldo_set_current_limit(struct regulator_dev *rdev,
+               int min_uA, int max_uA)
+{
+       struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev);
+       struct as3722 *as3722 = as3722_regs->as3722;
+       int id = rdev_get_id(rdev);
+       int ret;
+       u32 reg = 0;
+
+       ret = as3722_current_to_index(min_uA, max_uA, as3722_ldo_current,
+                               ARRAY_SIZE(as3722_ldo_current));
+       if (ret < 0) {
+               dev_err(as3722_regs->dev,
+                       "Current range min:max = %d:%d does not support\n",
+                       min_uA, max_uA);
+               return ret;
+       }
+       if (ret)
+               reg = AS3722_LDO_ILIMIT_BIT;
+       return as3722_update_bits(as3722, as3722_reg_lookup[id].vsel_reg,
+                       AS3722_LDO_ILIMIT_MASK, reg);
+}
+
+static struct regulator_ops as3722_ldo0_ops = {
+       .is_enabled = regulator_is_enabled_regmap,
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+       .list_voltage = regulator_list_voltage_linear,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .get_current_limit = as3722_ldo_get_current_limit,
+       .set_current_limit = as3722_ldo_set_current_limit,
+};
+
+static struct regulator_ops as3722_ldo0_extcntrl_ops = {
+       .list_voltage = regulator_list_voltage_linear,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .get_current_limit = as3722_ldo_get_current_limit,
+       .set_current_limit = as3722_ldo_set_current_limit,
+};
+
+static int as3722_ldo3_set_tracking_mode(struct as3722_regulators *as3722_reg,
+               int id, u8 mode)
+{
+       struct as3722 *as3722 = as3722_reg->as3722;
+
+       switch (mode) {
+       case AS3722_LDO3_MODE_PMOS:
+       case AS3722_LDO3_MODE_PMOS_TRACKING:
+       case AS3722_LDO3_MODE_NMOS:
+       case AS3722_LDO3_MODE_SWITCH:
+               return as3722_update_bits(as3722,
+                       as3722_reg_lookup[id].vsel_reg,
+                       AS3722_LDO3_MODE_MASK, mode);
+
+       default:
+               return -EINVAL;
+       }
+}
+
+static int as3722_ldo3_get_current_limit(struct regulator_dev *rdev)
+{
+       return 150000;
+}
+
+static struct regulator_ops as3722_ldo3_ops = {
+       .is_enabled = regulator_is_enabled_regmap,
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+       .list_voltage = regulator_list_voltage_linear,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .get_current_limit = as3722_ldo3_get_current_limit,
+};
+
+static struct regulator_ops as3722_ldo3_extcntrl_ops = {
+       .list_voltage = regulator_list_voltage_linear,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .get_current_limit = as3722_ldo3_get_current_limit,
+};
+
+static const struct regulator_linear_range as3722_ldo_ranges[] = {
+       REGULATOR_LINEAR_RANGE(825000, 0x01, 0x24, 25000),
+       REGULATOR_LINEAR_RANGE(1725000, 0x40, 0x7F, 25000),
+};
+
+static struct regulator_ops as3722_ldo_ops = {
+       .is_enabled = regulator_is_enabled_regmap,
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+       .map_voltage = regulator_map_voltage_linear_range,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+       .list_voltage = regulator_list_voltage_linear_range,
+       .get_current_limit = as3722_ldo_get_current_limit,
+       .set_current_limit = as3722_ldo_set_current_limit,
+};
+
+static struct regulator_ops as3722_ldo_extcntrl_ops = {
+       .map_voltage = regulator_map_voltage_linear_range,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+       .list_voltage = regulator_list_voltage_linear_range,
+       .get_current_limit = as3722_ldo_get_current_limit,
+       .set_current_limit = as3722_ldo_set_current_limit,
+};
+
+static unsigned int as3722_sd_get_mode(struct regulator_dev *rdev)
+{
+       struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev);
+       struct as3722 *as3722 = as3722_regs->as3722;
+       int id = rdev_get_id(rdev);
+       u32 val;
+       int ret;
+
+       if (!as3722_reg_lookup[id].control_reg)
+               return -ENOTSUPP;
+
+       ret = as3722_read(as3722, as3722_reg_lookup[id].control_reg, &val);
+       if (ret < 0) {
+               dev_err(as3722_regs->dev, "Reg 0x%02x read failed: %d\n",
+                       as3722_reg_lookup[id].control_reg, ret);
+               return ret;
+       }
+
+       if (val & as3722_reg_lookup[id].mode_mask)
+               return REGULATOR_MODE_FAST;
+       else
+               return REGULATOR_MODE_NORMAL;
+}
+
+static int as3722_sd_set_mode(struct regulator_dev *rdev,
+               unsigned int mode)
+{
+       struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev);
+       struct as3722 *as3722 = as3722_regs->as3722;
+       u8 id = rdev_get_id(rdev);
+       u8 val = 0;
+       int ret;
+
+       if (!as3722_reg_lookup[id].control_reg)
+               return -ERANGE;
+
+       switch (mode) {
+       case REGULATOR_MODE_FAST:
+               val = as3722_reg_lookup[id].mode_mask;
+       case REGULATOR_MODE_NORMAL: /* fall down */
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       ret = as3722_update_bits(as3722, as3722_reg_lookup[id].control_reg,
+                       as3722_reg_lookup[id].mode_mask, val);
+       if (ret < 0) {
+               dev_err(as3722_regs->dev, "Reg 0x%02x update failed: %d\n",
+                       as3722_reg_lookup[id].control_reg, ret);
+               return ret;
+       }
+       return ret;
+}
+
+static int as3722_sd016_get_current_limit(struct regulator_dev *rdev)
+{
+       struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev);
+       struct as3722 *as3722 = as3722_regs->as3722;
+       int id = rdev_get_id(rdev);
+       u32 val, reg;
+       int mask;
+       int ret;
+
+       switch (id) {
+       case AS3722_REGULATOR_ID_SD0:
+               reg = AS3722_OVCURRENT_REG;
+               mask = AS3722_OVCURRENT_SD0_TRIP_MASK;
+               break;
+       case AS3722_REGULATOR_ID_SD1:
+               reg = AS3722_OVCURRENT_REG;
+               mask = AS3722_OVCURRENT_SD1_TRIP_MASK;
+               break;
+       case AS3722_REGULATOR_ID_SD6:
+               reg = AS3722_OVCURRENT_DEB_REG;
+               mask = AS3722_OVCURRENT_SD6_TRIP_MASK;
+               break;
+       default:
+               return -EINVAL;
+       }
+       ret = as3722_read(as3722, reg, &val);
+       if (ret < 0) {
+               dev_err(as3722_regs->dev, "Reg 0x%02x read failed: %d\n",
+                       reg, ret);
+               return ret;
+       }
+       val &= mask;
+       val >>= ffs(mask) - 1;
+       if (val == 3)
+               return -EINVAL;
+       return as3722_sd016_current[val];
+}
+
+static int as3722_sd016_set_current_limit(struct regulator_dev *rdev,
+               int min_uA, int max_uA)
+{
+       struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev);
+       struct as3722 *as3722 = as3722_regs->as3722;
+       int id = rdev_get_id(rdev);
+       int ret;
+       int val;
+       int mask;
+       u32 reg;
+
+       ret = as3722_current_to_index(min_uA, max_uA, as3722_sd016_current,
+                               ARRAY_SIZE(as3722_sd016_current));
+       if (ret < 0) {
+               dev_err(as3722_regs->dev,
+                       "Current range min:max = %d:%d does not support\n",
+                       min_uA, max_uA);
+               return ret;
+       }
+
+       switch (id) {
+       case AS3722_REGULATOR_ID_SD0:
+               reg = AS3722_OVCURRENT_REG;
+               mask = AS3722_OVCURRENT_SD0_TRIP_MASK;
+               break;
+       case AS3722_REGULATOR_ID_SD1:
+               reg = AS3722_OVCURRENT_REG;
+               mask = AS3722_OVCURRENT_SD1_TRIP_MASK;
+               break;
+       case AS3722_REGULATOR_ID_SD6:
+               reg = AS3722_OVCURRENT_DEB_REG;
+               mask = AS3722_OVCURRENT_SD6_TRIP_MASK;
+               break;
+       default:
+               return -EINVAL;
+       }
+       val = ret & mask;
+       val <<= ffs(mask) - 1;
+       return as3722_update_bits(as3722, reg, mask, val);
+}
+
+static const struct regulator_linear_range as3722_sd2345_ranges[] = {
+       REGULATOR_LINEAR_RANGE(612500, 0x01, 0x40, 12500),
+       REGULATOR_LINEAR_RANGE(1425000, 0x41, 0x70, 25000),
+       REGULATOR_LINEAR_RANGE(2650000, 0x71, 0x7F, 50000),
+};
+
+static struct regulator_ops as3722_sd016_ops = {
+       .is_enabled = regulator_is_enabled_regmap,
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+       .list_voltage = regulator_list_voltage_linear,
+       .map_voltage = regulator_map_voltage_linear,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .get_current_limit = as3722_sd016_get_current_limit,
+       .set_current_limit = as3722_sd016_set_current_limit,
+       .get_mode = as3722_sd_get_mode,
+       .set_mode = as3722_sd_set_mode,
+};
+
+static struct regulator_ops as3722_sd016_extcntrl_ops = {
+       .list_voltage = regulator_list_voltage_linear,
+       .map_voltage = regulator_map_voltage_linear,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .get_current_limit = as3722_sd016_get_current_limit,
+       .set_current_limit = as3722_sd016_set_current_limit,
+       .get_mode = as3722_sd_get_mode,
+       .set_mode = as3722_sd_set_mode,
+};
+
+static struct regulator_ops as3722_sd2345_ops = {
+       .is_enabled = regulator_is_enabled_regmap,
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+       .list_voltage = regulator_list_voltage_linear_range,
+       .map_voltage = regulator_map_voltage_linear_range,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+       .get_mode = as3722_sd_get_mode,
+       .set_mode = as3722_sd_set_mode,
+};
+
+static struct regulator_ops as3722_sd2345_extcntrl_ops = {
+       .list_voltage = regulator_list_voltage_linear_range,
+       .map_voltage = regulator_map_voltage_linear_range,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+       .get_mode = as3722_sd_get_mode,
+       .set_mode = as3722_sd_set_mode,
+};
+
+static int as3722_extreg_init(struct as3722_regulators *as3722_regs, int id,
+               int ext_pwr_ctrl)
+{
+       int ret;
+       unsigned int val;
+
+       if ((ext_pwr_ctrl < AS3722_EXT_CONTROL_ENABLE1) ||
+               (ext_pwr_ctrl > AS3722_EXT_CONTROL_ENABLE3))
+               return -EINVAL;
+
+       val =  ext_pwr_ctrl << (ffs(as3722_reg_lookup[id].sleep_ctrl_mask) - 1);
+       ret = as3722_update_bits(as3722_regs->as3722,
+                       as3722_reg_lookup[id].sleep_ctrl_reg,
+                       as3722_reg_lookup[id].sleep_ctrl_mask, val);
+       if (ret < 0)
+               dev_err(as3722_regs->dev, "Reg 0x%02x update failed: %d\n",
+                       as3722_reg_lookup[id].sleep_ctrl_reg, ret);
+       return ret;
+}
+
+static struct of_regulator_match as3722_regulator_matches[] = {
+       { .name = "sd0", },
+       { .name = "sd1", },
+       { .name = "sd2", },
+       { .name = "sd3", },
+       { .name = "sd4", },
+       { .name = "sd5", },
+       { .name = "sd6", },
+       { .name = "ldo0", },
+       { .name = "ldo1", },
+       { .name = "ldo2", },
+       { .name = "ldo3", },
+       { .name = "ldo4", },
+       { .name = "ldo5", },
+       { .name = "ldo6", },
+       { .name = "ldo7", },
+       { .name = "ldo9", },
+       { .name = "ldo10", },
+       { .name = "ldo11", },
+};
+
+static int as3722_get_regulator_dt_data(struct platform_device *pdev,
+               struct as3722_regulators *as3722_regs)
+{
+       struct device_node *np;
+       struct as3722_regulator_config_data *reg_config;
+       u32 prop;
+       int id;
+       int ret;
+
+       np = of_get_child_by_name(pdev->dev.parent->of_node, "regulators");
+       if (!np) {
+               dev_err(&pdev->dev, "Device is not having regulators node\n");
+               return -ENODEV;
+       }
+       pdev->dev.of_node = np;
+
+       ret = of_regulator_match(&pdev->dev, np, as3722_regulator_matches,
+                       ARRAY_SIZE(as3722_regulator_matches));
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Parsing of regulator node failed: %d\n",
+                       ret);
+               return ret;
+       }
+
+       for (id = 0; id < ARRAY_SIZE(as3722_regulator_matches); ++id) {
+               struct device_node *reg_node;
+
+               reg_config = &as3722_regs->reg_config_data[id];
+               reg_config->reg_init = as3722_regulator_matches[id].init_data;
+               reg_node = as3722_regulator_matches[id].of_node;
+
+               if (!reg_config->reg_init || !reg_node)
+                       continue;
+
+               ret = of_property_read_u32(reg_node, "ams,ext-control", &prop);
+               if (!ret) {
+                       if (prop < 3)
+                               reg_config->ext_control = prop;
+                       else
+                               dev_warn(&pdev->dev,
+                                       "ext-control have invalid option: %u\n",
+                                       prop);
+               }
+               reg_config->enable_tracking =
+                       of_property_read_bool(reg_node, "ams,enable-tracking");
+       }
+       return 0;
+}
+
+static int as3722_regulator_probe(struct platform_device *pdev)
+{
+       struct as3722 *as3722 = dev_get_drvdata(pdev->dev.parent);
+       struct as3722_regulators *as3722_regs;
+       struct as3722_regulator_config_data *reg_config;
+       struct regulator_dev *rdev;
+       struct regulator_config config = { };
+       struct regulator_ops *ops;
+       int id;
+       int ret;
+
+       as3722_regs = devm_kzalloc(&pdev->dev, sizeof(*as3722_regs),
+                               GFP_KERNEL);
+       if (!as3722_regs)
+               return -ENOMEM;
+
+       as3722_regs->dev = &pdev->dev;
+       as3722_regs->as3722 = as3722;
+       platform_set_drvdata(pdev, as3722_regs);
+
+       ret = as3722_get_regulator_dt_data(pdev, as3722_regs);
+       if (ret < 0)
+               return ret;
+
+       config.dev = &pdev->dev;
+       config.driver_data = as3722_regs;
+       config.regmap = as3722->regmap;
+
+       for (id = 0; id < AS3722_REGULATOR_ID_MAX; id++) {
+               reg_config = &as3722_regs->reg_config_data[id];
+
+               as3722_regs->desc[id].name = as3722_reg_lookup[id].name;
+               as3722_regs->desc[id].supply_name = as3722_reg_lookup[id].sname;
+               as3722_regs->desc[id].id = as3722_reg_lookup[id].regulator_id;
+               as3722_regs->desc[id].n_voltages =
+                                       as3722_reg_lookup[id].n_voltages;
+               as3722_regs->desc[id].type = REGULATOR_VOLTAGE;
+               as3722_regs->desc[id].owner = THIS_MODULE;
+               as3722_regs->desc[id].enable_reg =
+                                       as3722_reg_lookup[id].enable_reg;
+               as3722_regs->desc[id].enable_mask =
+                                       as3722_reg_lookup[id].enable_mask;
+               as3722_regs->desc[id].vsel_reg = as3722_reg_lookup[id].vsel_reg;
+               as3722_regs->desc[id].vsel_mask =
+                                       as3722_reg_lookup[id].vsel_mask;
+               switch (id) {
+               case AS3722_REGULATOR_ID_LDO0:
+                       if (reg_config->ext_control)
+                               ops = &as3722_ldo0_extcntrl_ops;
+                       else
+                               ops = &as3722_ldo0_ops;
+                       as3722_regs->desc[id].min_uV = 825000;
+                       as3722_regs->desc[id].uV_step = 25000;
+                       as3722_regs->desc[id].linear_min_sel = 1;
+                       as3722_regs->desc[id].enable_time = 500;
+                       break;
+               case AS3722_REGULATOR_ID_LDO3:
+                       if (reg_config->ext_control)
+                               ops = &as3722_ldo3_extcntrl_ops;
+                       else
+                               ops = &as3722_ldo3_ops;
+                       as3722_regs->desc[id].min_uV = 620000;
+                       as3722_regs->desc[id].uV_step = 20000;
+                       as3722_regs->desc[id].linear_min_sel = 1;
+                       as3722_regs->desc[id].enable_time = 500;
+                       if (reg_config->enable_tracking) {
+                               ret = as3722_ldo3_set_tracking_mode(as3722_regs,
+                                       id, AS3722_LDO3_MODE_PMOS_TRACKING);
+                               if (ret < 0) {
+                                       dev_err(&pdev->dev,
+                                               "LDO3 tracking failed: %d\n",
+                                               ret);
+                                       return ret;
+                               }
+                       }
+                       break;
+               case AS3722_REGULATOR_ID_SD0:
+               case AS3722_REGULATOR_ID_SD1:
+               case AS3722_REGULATOR_ID_SD6:
+                       if (reg_config->ext_control)
+                               ops = &as3722_sd016_extcntrl_ops;
+                       else
+                               ops = &as3722_sd016_ops;
+                       as3722_regs->desc[id].min_uV = 610000;
+                       as3722_regs->desc[id].uV_step = 10000;
+                       as3722_regs->desc[id].linear_min_sel = 1;
+                       break;
+               case AS3722_REGULATOR_ID_SD2:
+               case AS3722_REGULATOR_ID_SD3:
+               case AS3722_REGULATOR_ID_SD4:
+               case AS3722_REGULATOR_ID_SD5:
+                       if (reg_config->ext_control)
+                               ops = &as3722_sd2345_extcntrl_ops;
+                       else
+                               ops = &as3722_sd2345_ops;
+                       as3722_regs->desc[id].linear_ranges =
+                                               as3722_sd2345_ranges;
+                       as3722_regs->desc[id].n_linear_ranges =
+                                       ARRAY_SIZE(as3722_sd2345_ranges);
+                       break;
+               default:
+                       if (reg_config->ext_control)
+                               ops = &as3722_ldo_extcntrl_ops;
+                       else
+                               ops = &as3722_ldo_ops;
+                       as3722_regs->desc[id].min_uV = 825000;
+                       as3722_regs->desc[id].uV_step = 25000;
+                       as3722_regs->desc[id].linear_min_sel = 1;
+                       as3722_regs->desc[id].enable_time = 500;
+                       as3722_regs->desc[id].linear_ranges = as3722_ldo_ranges;
+                       as3722_regs->desc[id].n_linear_ranges =
+                                               ARRAY_SIZE(as3722_ldo_ranges);
+                       break;
+               }
+               as3722_regs->desc[id].ops = ops;
+               config.init_data = reg_config->reg_init;
+               config.of_node = as3722_regulator_matches[id].of_node;
+               rdev = devm_regulator_register(&pdev->dev,
+                                       &as3722_regs->desc[id], &config);
+               if (IS_ERR(rdev)) {
+                       ret = PTR_ERR(rdev);
+                       dev_err(&pdev->dev, "regulator %d register failed %d\n",
+                               id, ret);
+                       return ret;
+               }
+
+               as3722_regs->rdevs[id] = rdev;
+               if (reg_config->ext_control) {
+                       ret = regulator_enable_regmap(rdev);
+                       if (ret < 0) {
+                               dev_err(&pdev->dev,
+                                       "Regulator %d enable failed: %d\n",
+                                       id, ret);
+                               return ret;
+                       }
+                       ret = as3722_extreg_init(as3722_regs, id,
+                                       reg_config->ext_control);
+                       if (ret < 0) {
+                               dev_err(&pdev->dev,
+                                       "AS3722 ext control failed: %d", ret);
+                               return ret;
+                       }
+               }
+       }
+       return 0;
+}
+
+static const struct of_device_id of_as3722_regulator_match[] = {
+       { .compatible = "ams,as3722-regulator", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, of_as3722_regulator_match);
+
+static struct platform_driver as3722_regulator_driver = {
+       .driver = {
+               .name = "as3722-regulator",
+               .owner = THIS_MODULE,
+               .of_match_table = of_as3722_regulator_match,
+       },
+       .probe = as3722_regulator_probe,
+};
+
+module_platform_driver(as3722_regulator_driver);
+
+MODULE_ALIAS("platform:as3722-regulator");
+MODULE_DESCRIPTION("AS3722 regulator driver");
+MODULE_AUTHOR("Florian Lobmaier <florian.lobmaier@ams.com>");
+MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
+MODULE_LICENSE("GPL");
index a01b8b3b70ca2fc3adb4e81d7f96358282115ba4..6382f0af353bc257e3ee6c3b545f75c0c1f2904e 100644 (file)
@@ -36,6 +36,7 @@
 #include <trace/events/regulator.h>
 
 #include "dummy.h"
+#include "internal.h"
 
 #define rdev_crit(rdev, fmt, ...)                                      \
        pr_crit("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
@@ -52,8 +53,8 @@ static DEFINE_MUTEX(regulator_list_mutex);
 static LIST_HEAD(regulator_list);
 static LIST_HEAD(regulator_map_list);
 static LIST_HEAD(regulator_ena_gpio_list);
+static LIST_HEAD(regulator_supply_alias_list);
 static bool has_full_constraints;
-static bool board_wants_dummy_regulator;
 
 static struct dentry *debugfs_root;
 
@@ -83,22 +84,16 @@ struct regulator_enable_gpio {
 };
 
 /*
- * struct regulator
+ * struct regulator_supply_alias
  *
- * One for each consumer device.
+ * Used to map lookups for a supply onto an alternative device.
  */
-struct regulator {
-       struct device *dev;
+struct regulator_supply_alias {
        struct list_head list;
-       unsigned int always_on:1;
-       unsigned int bypass:1;
-       int uA_load;
-       int min_uV;
-       int max_uV;
-       char *supply_name;
-       struct device_attribute dev_attr;
-       struct regulator_dev *rdev;
-       struct dentry *debugfs;
+       struct device *src_dev;
+       const char *src_supply;
+       struct device *alias_dev;
+       const char *alias_supply;
 };
 
 static int _regulator_is_enabled(struct regulator_dev *rdev);
@@ -923,6 +918,36 @@ static int machine_constraints_voltage(struct regulator_dev *rdev,
        return 0;
 }
 
+static int machine_constraints_current(struct regulator_dev *rdev,
+       struct regulation_constraints *constraints)
+{
+       struct regulator_ops *ops = rdev->desc->ops;
+       int ret;
+
+       if (!constraints->min_uA && !constraints->max_uA)
+               return 0;
+
+       if (constraints->min_uA > constraints->max_uA) {
+               rdev_err(rdev, "Invalid current constraints\n");
+               return -EINVAL;
+       }
+
+       if (!ops->set_current_limit || !ops->get_current_limit) {
+               rdev_warn(rdev, "Operation of current configuration missing\n");
+               return 0;
+       }
+
+       /* Set regulator current in constraints range */
+       ret = ops->set_current_limit(rdev, constraints->min_uA,
+                       constraints->max_uA);
+       if (ret < 0) {
+               rdev_err(rdev, "Failed to set current constraint, %d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
 /**
  * set_machine_constraints - sets regulator constraints
  * @rdev: regulator source
@@ -953,6 +978,10 @@ static int set_machine_constraints(struct regulator_dev *rdev,
        if (ret != 0)
                goto out;
 
+       ret = machine_constraints_current(rdev, rdev->constraints);
+       if (ret != 0)
+               goto out;
+
        /* do we need to setup our suspend state */
        if (rdev->constraints->initial_state) {
                ret = suspend_prepare(rdev, rdev->constraints->initial_state);
@@ -1186,11 +1215,39 @@ overflow_err:
 
 static int _regulator_get_enable_time(struct regulator_dev *rdev)
 {
+       if (rdev->constraints && rdev->constraints->enable_time)
+               return rdev->constraints->enable_time;
        if (!rdev->desc->ops->enable_time)
                return rdev->desc->enable_time;
        return rdev->desc->ops->enable_time(rdev);
 }
 
+static struct regulator_supply_alias *regulator_find_supply_alias(
+               struct device *dev, const char *supply)
+{
+       struct regulator_supply_alias *map;
+
+       list_for_each_entry(map, &regulator_supply_alias_list, list)
+               if (map->src_dev == dev && strcmp(map->src_supply, supply) == 0)
+                       return map;
+
+       return NULL;
+}
+
+static void regulator_supply_alias(struct device **dev, const char **supply)
+{
+       struct regulator_supply_alias *map;
+
+       map = regulator_find_supply_alias(*dev, *supply);
+       if (map) {
+               dev_dbg(*dev, "Mapping supply %s to %s,%s\n",
+                               *supply, map->alias_supply,
+                               dev_name(map->alias_dev));
+               *dev = map->alias_dev;
+               *supply = map->alias_supply;
+       }
+}
+
 static struct regulator_dev *regulator_dev_lookup(struct device *dev,
                                                  const char *supply,
                                                  int *ret)
@@ -1200,6 +1257,8 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev,
        struct regulator_map *map;
        const char *devname = NULL;
 
+       regulator_supply_alias(&dev, &supply);
+
        /* first do a dt based lookup */
        if (dev && dev->of_node) {
                node = of_get_regulator(dev, supply);
@@ -1243,16 +1302,16 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev,
 
 /* Internal regulator request function */
 static struct regulator *_regulator_get(struct device *dev, const char *id,
-                                       bool exclusive)
+                                       bool exclusive, bool allow_dummy)
 {
        struct regulator_dev *rdev;
        struct regulator *regulator = ERR_PTR(-EPROBE_DEFER);
        const char *devname = NULL;
-       int ret = 0;
+       int ret = -EPROBE_DEFER;
 
        if (id == NULL) {
                pr_err("get() with no identifier\n");
-               return regulator;
+               return ERR_PTR(-EINVAL);
        }
 
        if (dev)
@@ -1264,34 +1323,32 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
        if (rdev)
                goto found;
 
+       regulator = ERR_PTR(ret);
+
        /*
         * If we have return value from dev_lookup fail, we do not expect to
         * succeed, so, quit with appropriate error value
         */
-       if (ret) {
-               regulator = ERR_PTR(ret);
+       if (ret && ret != -ENODEV) {
                goto out;
        }
 
-       if (board_wants_dummy_regulator) {
-               rdev = dummy_regulator_rdev;
-               goto found;
-       }
-
-#ifdef CONFIG_REGULATOR_DUMMY
        if (!devname)
                devname = "deviceless";
 
-       /* If the board didn't flag that it was fully constrained then
-        * substitute in a dummy regulator so consumers can continue.
+       /*
+        * Assume that a regulator is physically present and enabled
+        * even if it isn't hooked up and just provide a dummy.
         */
-       if (!has_full_constraints) {
+       if (has_full_constraints && allow_dummy) {
                pr_warn("%s supply %s not found, using dummy regulator\n",
                        devname, id);
+
                rdev = dummy_regulator_rdev;
                goto found;
+       } else {
+               dev_err(dev, "dummy supplies not allowed\n");
        }
-#endif
 
        mutex_unlock(&regulator_list_mutex);
        return regulator;
@@ -1349,44 +1406,10 @@ out:
  */
 struct regulator *regulator_get(struct device *dev, const char *id)
 {
-       return _regulator_get(dev, id, false);
+       return _regulator_get(dev, id, false, true);
 }
 EXPORT_SYMBOL_GPL(regulator_get);
 
-static void devm_regulator_release(struct device *dev, void *res)
-{
-       regulator_put(*(struct regulator **)res);
-}
-
-/**
- * devm_regulator_get - Resource managed regulator_get()
- * @dev: device for regulator "consumer"
- * @id: Supply name or regulator ID.
- *
- * Managed regulator_get(). Regulators returned from this function are
- * automatically regulator_put() on driver detach. See regulator_get() for more
- * information.
- */
-struct regulator *devm_regulator_get(struct device *dev, const char *id)
-{
-       struct regulator **ptr, *regulator;
-
-       ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL);
-       if (!ptr)
-               return ERR_PTR(-ENOMEM);
-
-       regulator = regulator_get(dev, id);
-       if (!IS_ERR(regulator)) {
-               *ptr = regulator;
-               devres_add(dev, ptr);
-       } else {
-               devres_free(ptr);
-       }
-
-       return regulator;
-}
-EXPORT_SYMBOL_GPL(devm_regulator_get);
-
 /**
  * regulator_get_exclusive - obtain exclusive access to a regulator.
  * @dev: device for regulator "consumer"
@@ -1410,7 +1433,7 @@ EXPORT_SYMBOL_GPL(devm_regulator_get);
  */
 struct regulator *regulator_get_exclusive(struct device *dev, const char *id)
 {
-       return _regulator_get(dev, id, true);
+       return _regulator_get(dev, id, true, false);
 }
 EXPORT_SYMBOL_GPL(regulator_get_exclusive);
 
@@ -1439,40 +1462,10 @@ EXPORT_SYMBOL_GPL(regulator_get_exclusive);
  */
 struct regulator *regulator_get_optional(struct device *dev, const char *id)
 {
-       return _regulator_get(dev, id, 0);
+       return _regulator_get(dev, id, false, false);
 }
 EXPORT_SYMBOL_GPL(regulator_get_optional);
 
-/**
- * devm_regulator_get_optional - Resource managed regulator_get_optional()
- * @dev: device for regulator "consumer"
- * @id: Supply name or regulator ID.
- *
- * Managed regulator_get_optional(). Regulators returned from this
- * function are automatically regulator_put() on driver detach. See
- * regulator_get_optional() for more information.
- */
-struct regulator *devm_regulator_get_optional(struct device *dev,
-                                             const char *id)
-{
-       struct regulator **ptr, *regulator;
-
-       ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL);
-       if (!ptr)
-               return ERR_PTR(-ENOMEM);
-
-       regulator = regulator_get_optional(dev, id);
-       if (!IS_ERR(regulator)) {
-               *ptr = regulator;
-               devres_add(dev, ptr);
-       } else {
-               devres_free(ptr);
-       }
-
-       return regulator;
-}
-EXPORT_SYMBOL_GPL(devm_regulator_get_optional);
-
 /* Locks held by regulator_put() */
 static void _regulator_put(struct regulator *regulator)
 {
@@ -1498,36 +1491,6 @@ static void _regulator_put(struct regulator *regulator)
        module_put(rdev->owner);
 }
 
-/**
- * devm_regulator_get_exclusive - Resource managed regulator_get_exclusive()
- * @dev: device for regulator "consumer"
- * @id: Supply name or regulator ID.
- *
- * Managed regulator_get_exclusive(). Regulators returned from this function
- * are automatically regulator_put() on driver detach. See regulator_get() for
- * more information.
- */
-struct regulator *devm_regulator_get_exclusive(struct device *dev,
-                                              const char *id)
-{
-       struct regulator **ptr, *regulator;
-
-       ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL);
-       if (!ptr)
-               return ERR_PTR(-ENOMEM);
-
-       regulator = _regulator_get(dev, id, 1);
-       if (!IS_ERR(regulator)) {
-               *ptr = regulator;
-               devres_add(dev, ptr);
-       } else {
-               devres_free(ptr);
-       }
-
-       return regulator;
-}
-EXPORT_SYMBOL_GPL(devm_regulator_get_exclusive);
-
 /**
  * regulator_put - "free" the regulator source
  * @regulator: regulator source
@@ -1544,34 +1507,133 @@ void regulator_put(struct regulator *regulator)
 }
 EXPORT_SYMBOL_GPL(regulator_put);
 
-static int devm_regulator_match(struct device *dev, void *res, void *data)
+/**
+ * regulator_register_supply_alias - Provide device alias for supply lookup
+ *
+ * @dev: device that will be given as the regulator "consumer"
+ * @id: Supply name or regulator ID
+ * @alias_dev: device that should be used to lookup the supply
+ * @alias_id: Supply name or regulator ID that should be used to lookup the
+ * supply
+ *
+ * All lookups for id on dev will instead be conducted for alias_id on
+ * alias_dev.
+ */
+int regulator_register_supply_alias(struct device *dev, const char *id,
+                                   struct device *alias_dev,
+                                   const char *alias_id)
+{
+       struct regulator_supply_alias *map;
+
+       map = regulator_find_supply_alias(dev, id);
+       if (map)
+               return -EEXIST;
+
+       map = kzalloc(sizeof(struct regulator_supply_alias), GFP_KERNEL);
+       if (!map)
+               return -ENOMEM;
+
+       map->src_dev = dev;
+       map->src_supply = id;
+       map->alias_dev = alias_dev;
+       map->alias_supply = alias_id;
+
+       list_add(&map->list, &regulator_supply_alias_list);
+
+       pr_info("Adding alias for supply %s,%s -> %s,%s\n",
+               id, dev_name(dev), alias_id, dev_name(alias_dev));
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(regulator_register_supply_alias);
+
+/**
+ * regulator_unregister_supply_alias - Remove device alias
+ *
+ * @dev: device that will be given as the regulator "consumer"
+ * @id: Supply name or regulator ID
+ *
+ * Remove a lookup alias if one exists for id on dev.
+ */
+void regulator_unregister_supply_alias(struct device *dev, const char *id)
 {
-       struct regulator **r = res;
-       if (!r || !*r) {
-               WARN_ON(!r || !*r);
-               return 0;
+       struct regulator_supply_alias *map;
+
+       map = regulator_find_supply_alias(dev, id);
+       if (map) {
+               list_del(&map->list);
+               kfree(map);
        }
-       return *r == data;
 }
+EXPORT_SYMBOL_GPL(regulator_unregister_supply_alias);
 
 /**
- * devm_regulator_put - Resource managed regulator_put()
- * @regulator: regulator to free
+ * regulator_bulk_register_supply_alias - register multiple aliases
+ *
+ * @dev: device that will be given as the regulator "consumer"
+ * @id: List of supply names or regulator IDs
+ * @alias_dev: device that should be used to lookup the supply
+ * @alias_id: List of supply names or regulator IDs that should be used to
+ * lookup the supply
+ * @num_id: Number of aliases to register
+ *
+ * @return 0 on success, an errno on failure.
  *
- * Deallocate a regulator allocated with devm_regulator_get(). Normally
- * this function will not need to be called and the resource management
- * code will ensure that the resource is freed.
+ * This helper function allows drivers to register several supply
+ * aliases in one operation.  If any of the aliases cannot be
+ * registered any aliases that were registered will be removed
+ * before returning to the caller.
  */
-void devm_regulator_put(struct regulator *regulator)
+int regulator_bulk_register_supply_alias(struct device *dev, const char **id,
+                                        struct device *alias_dev,
+                                        const char **alias_id,
+                                        int num_id)
 {
-       int rc;
+       int i;
+       int ret;
+
+       for (i = 0; i < num_id; ++i) {
+               ret = regulator_register_supply_alias(dev, id[i], alias_dev,
+                                                     alias_id[i]);
+               if (ret < 0)
+                       goto err;
+       }
+
+       return 0;
+
+err:
+       dev_err(dev,
+               "Failed to create supply alias %s,%s -> %s,%s\n",
+               id[i], dev_name(dev), alias_id[i], dev_name(alias_dev));
+
+       while (--i >= 0)
+               regulator_unregister_supply_alias(dev, id[i]);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(regulator_bulk_register_supply_alias);
+
+/**
+ * regulator_bulk_unregister_supply_alias - unregister multiple aliases
+ *
+ * @dev: device that will be given as the regulator "consumer"
+ * @id: List of supply names or regulator IDs
+ * @num_id: Number of aliases to unregister
+ *
+ * This helper function allows drivers to unregister several supply
+ * aliases in one operation.
+ */
+void regulator_bulk_unregister_supply_alias(struct device *dev,
+                                           const char **id,
+                                           int num_id)
+{
+       int i;
 
-       rc = devres_release(regulator->dev, devm_regulator_release,
-                           devm_regulator_match, regulator);
-       if (rc != 0)
-               WARN_ON(rc);
+       for (i = 0; i < num_id; ++i)
+               regulator_unregister_supply_alias(dev, id[i]);
 }
-EXPORT_SYMBOL_GPL(devm_regulator_put);
+EXPORT_SYMBOL_GPL(regulator_bulk_unregister_supply_alias);
+
 
 /* Manage enable GPIO list. Same GPIO pin can be shared among regulators */
 static int regulator_ena_gpio_request(struct regulator_dev *rdev,
@@ -1704,11 +1766,39 @@ static int _regulator_do_enable(struct regulator_dev *rdev)
         * together.  */
        trace_regulator_enable_delay(rdev_get_name(rdev));
 
-       if (delay >= 1000) {
-               mdelay(delay / 1000);
-               udelay(delay % 1000);
-       } else if (delay) {
-               udelay(delay);
+       /*
+        * Delay for the requested amount of time as per the guidelines in:
+        *
+        *     Documentation/timers/timers-howto.txt
+        *
+        * The assumption here is that regulators will never be enabled in
+        * atomic context and therefore sleeping functions can be used.
+        */
+       if (delay) {
+               unsigned int ms = delay / 1000;
+               unsigned int us = delay % 1000;
+
+               if (ms > 0) {
+                       /*
+                        * For small enough values, handle super-millisecond
+                        * delays in the usleep_range() call below.
+                        */
+                       if (ms < 20)
+                               us += ms * 1000;
+                       else
+                               msleep(ms);
+               }
+
+               /*
+                * Give the scheduler some room to coalesce with any other
+                * wakeup sources. For delays shorter than 10 us, don't even
+                * bother setting up high-resolution timers and just busy-
+                * loop.
+                */
+               if (us >= 10)
+                       usleep_range(us, us + 100);
+               else
+                       udelay(us);
        }
 
        trace_regulator_enable_complete(rdev_get_name(rdev));
@@ -2489,6 +2579,8 @@ static int _regulator_get_voltage(struct regulator_dev *rdev)
                ret = rdev->desc->ops->get_voltage(rdev);
        } else if (rdev->desc->ops->list_voltage) {
                ret = rdev->desc->ops->list_voltage(rdev, 0);
+       } else if (rdev->desc->fixed_uV && (rdev->desc->n_voltages == 1)) {
+               ret = rdev->desc->fixed_uV;
        } else {
                return -EINVAL;
        }
@@ -2912,52 +3004,6 @@ err:
 }
 EXPORT_SYMBOL_GPL(regulator_bulk_get);
 
-/**
- * devm_regulator_bulk_get - managed get multiple regulator consumers
- *
- * @dev:           Device to supply
- * @num_consumers: Number of consumers to register
- * @consumers:     Configuration of consumers; clients are stored here.
- *
- * @return 0 on success, an errno on failure.
- *
- * This helper function allows drivers to get several regulator
- * consumers in one operation with management, the regulators will
- * automatically be freed when the device is unbound.  If any of the
- * regulators cannot be acquired then any regulators that were
- * allocated will be freed before returning to the caller.
- */
-int devm_regulator_bulk_get(struct device *dev, int num_consumers,
-                           struct regulator_bulk_data *consumers)
-{
-       int i;
-       int ret;
-
-       for (i = 0; i < num_consumers; i++)
-               consumers[i].consumer = NULL;
-
-       for (i = 0; i < num_consumers; i++) {
-               consumers[i].consumer = devm_regulator_get(dev,
-                                                          consumers[i].supply);
-               if (IS_ERR(consumers[i].consumer)) {
-                       ret = PTR_ERR(consumers[i].consumer);
-                       dev_err(dev, "Failed to get supply '%s': %d\n",
-                               consumers[i].supply, ret);
-                       consumers[i].consumer = NULL;
-                       goto err;
-               }
-       }
-
-       return 0;
-
-err:
-       for (i = 0; i < num_consumers && consumers[i].consumer; i++)
-               devm_regulator_put(consumers[i].consumer);
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(devm_regulator_bulk_get);
-
 static void regulator_bulk_enable_async(void *data, async_cookie_t cookie)
 {
        struct regulator_bulk_data *bulk = data;
@@ -3170,7 +3216,8 @@ static int add_regulator_attributes(struct regulator_dev *rdev)
        /* some attributes need specific methods to be displayed */
        if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) ||
            (ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0) ||
-           (ops->list_voltage && ops->list_voltage(rdev, 0) >= 0)) {
+           (ops->list_voltage && ops->list_voltage(rdev, 0) >= 0) ||
+               (rdev->desc->fixed_uV && (rdev->desc->n_voltages == 1))) {
                status = device_create_file(dev, &dev_attr_microvolts);
                if (status < 0)
                        return status;
@@ -3613,22 +3660,6 @@ void regulator_has_full_constraints(void)
 }
 EXPORT_SYMBOL_GPL(regulator_has_full_constraints);
 
-/**
- * regulator_use_dummy_regulator - Provide a dummy regulator when none is found
- *
- * Calling this function will cause the regulator API to provide a
- * dummy regulator to consumers if no physical regulator is found,
- * allowing most consumers to proceed as though a regulator were
- * configured.  This allows systems such as those with software
- * controllable regulators for the CPU core only to be brought up more
- * readily.
- */
-void regulator_use_dummy_regulator(void)
-{
-       board_wants_dummy_regulator = true;
-}
-EXPORT_SYMBOL_GPL(regulator_use_dummy_regulator);
-
 /**
  * rdev_get_drvdata - get rdev regulator driver data
  * @rdev: regulator
index f06854cf8cf50739866386538668f4eb5acbc34a..b431ae357fcd310e062bcb3fdb0ffd864b2f0603 100644 (file)
@@ -253,10 +253,8 @@ static int da9034_set_dvc_voltage_sel(struct regulator_dev *rdev,
 }
 
 static const struct regulator_linear_range da9034_ldo12_ranges[] = {
-       { .min_uV = 1700000, .max_uV = 2050000, .min_sel =  0, .max_sel = 7,
-         .uV_step =  50000 },
-       { .min_uV = 2700000, .max_uV = 3050000, .min_sel =  8, .max_sel = 15,
-         .uV_step =  50000 },
+       REGULATOR_LINEAR_RANGE(1700000, 0, 7, 50000),
+       REGULATOR_LINEAR_RANGE(2700000, 8, 15, 50000),
 };
 
 static struct regulator_ops da903x_regulator_ldo_ops = {
@@ -463,7 +461,7 @@ static int da903x_regulator_probe(struct platform_device *pdev)
        config.init_data = dev_get_platdata(&pdev->dev);
        config.driver_data = ri;
 
-       rdev = regulator_register(&ri->desc, &config);
+       rdev = devm_regulator_register(&pdev->dev, &ri->desc, &config);
        if (IS_ERR(rdev)) {
                dev_err(&pdev->dev, "failed to register regulator %s\n",
                                ri->desc.name);
@@ -474,21 +472,12 @@ static int da903x_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int da903x_regulator_remove(struct platform_device *pdev)
-{
-       struct regulator_dev *rdev = platform_get_drvdata(pdev);
-
-       regulator_unregister(rdev);
-       return 0;
-}
-
 static struct platform_driver da903x_regulator_driver = {
        .driver = {
                .name   = "da903x-regulator",
                .owner  = THIS_MODULE,
        },
        .probe          = da903x_regulator_probe,
-       .remove         = da903x_regulator_remove,
 };
 
 static int __init da903x_regulator_init(void)
index 1e4d483f616373a6fb19b339ce6325be7c8a3b33..c427e42472e8d544ce11e0decc871b38405e8a06 100644 (file)
@@ -389,8 +389,9 @@ static int da9052_regulator_probe(struct platform_device *pdev)
 #endif
        }
 
-       regulator->rdev = regulator_register(&regulator->info->reg_desc,
-                                            &config);
+       regulator->rdev = devm_regulator_register(&pdev->dev,
+                                                 &regulator->info->reg_desc,
+                                                 &config);
        if (IS_ERR(regulator->rdev)) {
                dev_err(&pdev->dev, "failed to register regulator %s\n",
                        regulator->info->reg_desc.name);
@@ -402,17 +403,8 @@ static int da9052_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int da9052_regulator_remove(struct platform_device *pdev)
-{
-       struct da9052_regulator *regulator = platform_get_drvdata(pdev);
-
-       regulator_unregister(regulator->rdev);
-       return 0;
-}
-
 static struct platform_driver da9052_regulator_driver = {
        .probe = da9052_regulator_probe,
-       .remove = da9052_regulator_remove,
        .driver = {
                .name = "da9052-regulator",
                .owner = THIS_MODULE,
index 77b53e5a231cabda9eaa915efa718ad9ce5e18f5..7f340206d329d452710a319deba4869a2d6c603b 100644 (file)
@@ -564,13 +564,13 @@ static int da9055_regulator_probe(struct platform_device *pdev)
        if (ret < 0)
                return ret;
 
-       regulator->rdev = regulator_register(&regulator->info->reg_desc,
-                                            &config);
+       regulator->rdev = devm_regulator_register(&pdev->dev,
+                                                 &regulator->info->reg_desc,
+                                                 &config);
        if (IS_ERR(regulator->rdev)) {
                dev_err(&pdev->dev, "Failed to register regulator %s\n",
                        regulator->info->reg_desc.name);
-               ret = PTR_ERR(regulator->rdev);
-               return ret;
+               return PTR_ERR(regulator->rdev);
        }
 
        /* Only LDO 5 and 6 has got the over current interrupt */
@@ -588,32 +588,18 @@ static int da9055_regulator_probe(struct platform_device *pdev)
                                dev_err(&pdev->dev,
                                "Failed to request Regulator IRQ %d: %d\n",
                                irq, ret);
-                               goto err_regulator;
+                               return ret;
                        }
                }
        }
 
        platform_set_drvdata(pdev, regulator);
 
-       return 0;
-
-err_regulator:
-       regulator_unregister(regulator->rdev);
-       return ret;
-}
-
-static int da9055_regulator_remove(struct platform_device *pdev)
-{
-       struct da9055_regulator *regulator = platform_get_drvdata(pdev);
-
-       regulator_unregister(regulator->rdev);
-
        return 0;
 }
 
 static struct platform_driver da9055_regulator_driver = {
        .probe = da9055_regulator_probe,
-       .remove = da9055_regulator_remove,
        .driver = {
                .name = "da9055-regulator",
                .owner = THIS_MODULE,
index b9f2653e4ef90f315de25752fe24821a98497848..56727eb745df69171d77fac8313e6ea3ab2499ef 100644 (file)
@@ -717,7 +717,7 @@ static int da9063_regulator_probe(struct platform_device *pdev)
 {
        struct da9063 *da9063 = dev_get_drvdata(pdev->dev.parent);
        struct da9063_pdata *da9063_pdata = dev_get_platdata(da9063->dev);
-       struct of_regulator_match *da9063_reg_matches;
+       struct of_regulator_match *da9063_reg_matches = NULL;
        struct da9063_regulators_pdata *regl_pdata;
        const struct da9063_dev_model *model;
        struct da9063_regulators *regulators;
@@ -847,13 +847,13 @@ static int da9063_regulator_probe(struct platform_device *pdev)
                if (da9063_reg_matches)
                        config.of_node = da9063_reg_matches[id].of_node;
                config.regmap = da9063->regmap;
-               regl->rdev = regulator_register(&regl->desc, &config);
+               regl->rdev = devm_regulator_register(&pdev->dev, &regl->desc,
+                                                    &config);
                if (IS_ERR(regl->rdev)) {
                        dev_err(&pdev->dev,
                                "Failed to register %s regulator\n",
                                regl->desc.name);
-                       ret = PTR_ERR(regl->rdev);
-                       goto err;
+                       return PTR_ERR(regl->rdev);
                }
                id++;
                n++;
@@ -862,9 +862,8 @@ static int da9063_regulator_probe(struct platform_device *pdev)
        /* LDOs overcurrent event support */
        irq = platform_get_irq_byname(pdev, "LDO_LIM");
        if (irq < 0) {
-               ret = irq;
                dev_err(&pdev->dev, "Failed to get IRQ.\n");
-               goto err;
+               return irq;
        }
 
        regulators->irq_ldo_lim = regmap_irq_get_virq(da9063->regmap_irq, irq);
@@ -881,27 +880,15 @@ static int da9063_regulator_probe(struct platform_device *pdev)
        }
 
        return 0;
-
-err:
-       /* Wind back regulators registeration */
-       while (--n >= 0)
-               regulator_unregister(regulators->regulator[n].rdev);
-
-       return ret;
 }
 
 static int da9063_regulator_remove(struct platform_device *pdev)
 {
        struct da9063_regulators *regulators = platform_get_drvdata(pdev);
-       struct da9063_regulator *regl;
 
        free_irq(regulators->irq_ldo_lim, regulators);
        free_irq(regulators->irq_uvov, regulators);
 
-       for (regl = &regulators->regulator[regulators->n_regulators - 1];
-            regl >= &regulators->regulator[0]; regl--)
-               regulator_unregister(regl->rdev);
-
        return 0;
 }
 
index f0fe54b3897736327250d6dfe7a664369273df81..6f5ecbe1132e7da4f02496672578ef2301285767 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/slab.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
 #include <linux/regmap.h>
 
 #include "da9210-regulator.h"
@@ -126,7 +127,8 @@ static int da9210_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
        struct da9210 *chip;
-       struct da9210_pdata *pdata = i2c->dev.platform_data;
+       struct device *dev = &i2c->dev;
+       struct da9210_pdata *pdata = dev_get_platdata(dev);
        struct regulator_dev *rdev = NULL;
        struct regulator_config config = { };
        int error;
@@ -147,12 +149,13 @@ static int da9210_i2c_probe(struct i2c_client *i2c,
        }
 
        config.dev = &i2c->dev;
-       if (pdata)
-               config.init_data = &pdata->da9210_constraints;
+       config.init_data = pdata ? &pdata->da9210_constraints :
+               of_get_regulator_init_data(dev, dev->of_node);
        config.driver_data = chip;
        config.regmap = chip->regmap;
+       config.of_node = dev->of_node;
 
-       rdev = regulator_register(&da9210_reg, &config);
+       rdev = devm_regulator_register(&i2c->dev, &da9210_reg, &config);
        if (IS_ERR(rdev)) {
                dev_err(&i2c->dev, "Failed to register DA9210 regulator\n");
                return PTR_ERR(rdev);
@@ -165,13 +168,6 @@ static int da9210_i2c_probe(struct i2c_client *i2c,
        return 0;
 }
 
-static int da9210_i2c_remove(struct i2c_client *i2c)
-{
-       struct da9210 *chip = i2c_get_clientdata(i2c);
-       regulator_unregister(chip->rdev);
-       return 0;
-}
-
 static const struct i2c_device_id da9210_i2c_id[] = {
        {"da9210", 0},
        {},
@@ -185,7 +181,6 @@ static struct i2c_driver da9210_regulator_driver = {
                .owner = THIS_MODULE,
        },
        .probe = da9210_i2c_probe,
-       .remove = da9210_i2c_remove,
        .id_table = da9210_i2c_id,
 };
 
diff --git a/drivers/regulator/devres.c b/drivers/regulator/devres.c
new file mode 100644 (file)
index 0000000..f44818b
--- /dev/null
@@ -0,0 +1,415 @@
+/*
+ * devres.c  --  Voltage/Current Regulator framework devres implementation.
+ *
+ * Copyright 2013 Linaro Ltd
+ *
+ *  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/kernel.h>
+#include <linux/err.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/driver.h>
+#include <linux/module.h>
+
+#include "internal.h"
+
+enum {
+       NORMAL_GET,
+       EXCLUSIVE_GET,
+       OPTIONAL_GET,
+};
+
+static void devm_regulator_release(struct device *dev, void *res)
+{
+       regulator_put(*(struct regulator **)res);
+}
+
+static struct regulator *_devm_regulator_get(struct device *dev, const char *id,
+                                            int get_type)
+{
+       struct regulator **ptr, *regulator;
+
+       ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL);
+       if (!ptr)
+               return ERR_PTR(-ENOMEM);
+
+       switch (get_type) {
+       case NORMAL_GET:
+               regulator = regulator_get(dev, id);
+               break;
+       case EXCLUSIVE_GET:
+               regulator = regulator_get_exclusive(dev, id);
+               break;
+       case OPTIONAL_GET:
+               regulator = regulator_get_optional(dev, id);
+               break;
+       default:
+               regulator = ERR_PTR(-EINVAL);
+       }
+
+       if (!IS_ERR(regulator)) {
+               *ptr = regulator;
+               devres_add(dev, ptr);
+       } else {
+               devres_free(ptr);
+       }
+
+       return regulator;
+}
+
+/**
+ * devm_regulator_get - Resource managed regulator_get()
+ * @dev: device for regulator "consumer"
+ * @id: Supply name or regulator ID.
+ *
+ * Managed regulator_get(). Regulators returned from this function are
+ * automatically regulator_put() on driver detach. See regulator_get() for more
+ * information.
+ */
+struct regulator *devm_regulator_get(struct device *dev, const char *id)
+{
+       return _devm_regulator_get(dev, id, NORMAL_GET);
+}
+EXPORT_SYMBOL_GPL(devm_regulator_get);
+
+/**
+ * devm_regulator_get_exclusive - Resource managed regulator_get_exclusive()
+ * @dev: device for regulator "consumer"
+ * @id: Supply name or regulator ID.
+ *
+ * Managed regulator_get_exclusive(). Regulators returned from this function
+ * are automatically regulator_put() on driver detach. See regulator_get() for
+ * more information.
+ */
+struct regulator *devm_regulator_get_exclusive(struct device *dev,
+                                              const char *id)
+{
+       return _devm_regulator_get(dev, id, EXCLUSIVE_GET);
+}
+EXPORT_SYMBOL_GPL(devm_regulator_get_exclusive);
+
+/**
+ * devm_regulator_get_optional - Resource managed regulator_get_optional()
+ * @dev: device for regulator "consumer"
+ * @id: Supply name or regulator ID.
+ *
+ * Managed regulator_get_optional(). Regulators returned from this
+ * function are automatically regulator_put() on driver detach. See
+ * regulator_get_optional() for more information.
+ */
+struct regulator *devm_regulator_get_optional(struct device *dev,
+                                             const char *id)
+{
+       return _devm_regulator_get(dev, id, OPTIONAL_GET);
+}
+EXPORT_SYMBOL_GPL(devm_regulator_get_optional);
+
+static int devm_regulator_match(struct device *dev, void *res, void *data)
+{
+       struct regulator **r = res;
+       if (!r || !*r) {
+               WARN_ON(!r || !*r);
+               return 0;
+       }
+       return *r == data;
+}
+
+/**
+ * devm_regulator_put - Resource managed regulator_put()
+ * @regulator: regulator to free
+ *
+ * Deallocate a regulator allocated with devm_regulator_get(). Normally
+ * this function will not need to be called and the resource management
+ * code will ensure that the resource is freed.
+ */
+void devm_regulator_put(struct regulator *regulator)
+{
+       int rc;
+
+       rc = devres_release(regulator->dev, devm_regulator_release,
+                           devm_regulator_match, regulator);
+       if (rc != 0)
+               WARN_ON(rc);
+}
+EXPORT_SYMBOL_GPL(devm_regulator_put);
+
+/**
+ * devm_regulator_bulk_get - managed get multiple regulator consumers
+ *
+ * @dev:           Device to supply
+ * @num_consumers: Number of consumers to register
+ * @consumers:     Configuration of consumers; clients are stored here.
+ *
+ * @return 0 on success, an errno on failure.
+ *
+ * This helper function allows drivers to get several regulator
+ * consumers in one operation with management, the regulators will
+ * automatically be freed when the device is unbound.  If any of the
+ * regulators cannot be acquired then any regulators that were
+ * allocated will be freed before returning to the caller.
+ */
+int devm_regulator_bulk_get(struct device *dev, int num_consumers,
+                           struct regulator_bulk_data *consumers)
+{
+       int i;
+       int ret;
+
+       for (i = 0; i < num_consumers; i++)
+               consumers[i].consumer = NULL;
+
+       for (i = 0; i < num_consumers; i++) {
+               consumers[i].consumer = devm_regulator_get(dev,
+                                                          consumers[i].supply);
+               if (IS_ERR(consumers[i].consumer)) {
+                       ret = PTR_ERR(consumers[i].consumer);
+                       dev_err(dev, "Failed to get supply '%s': %d\n",
+                               consumers[i].supply, ret);
+                       consumers[i].consumer = NULL;
+                       goto err;
+               }
+       }
+
+       return 0;
+
+err:
+       for (i = 0; i < num_consumers && consumers[i].consumer; i++)
+               devm_regulator_put(consumers[i].consumer);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(devm_regulator_bulk_get);
+
+static void devm_rdev_release(struct device *dev, void *res)
+{
+       regulator_unregister(*(struct regulator_dev **)res);
+}
+
+/**
+ * devm_regulator_register - Resource managed regulator_register()
+ * @regulator_desc: regulator to register
+ * @config: runtime configuration for regulator
+ *
+ * Called by regulator drivers to register a regulator.  Returns a
+ * valid pointer to struct regulator_dev on success or an ERR_PTR() on
+ * error.  The regulator will automatically be released when the device
+ * is unbound.
+ */
+struct regulator_dev *devm_regulator_register(struct device *dev,
+                                 const struct regulator_desc *regulator_desc,
+                                 const struct regulator_config *config)
+{
+       struct regulator_dev **ptr, *rdev;
+
+       ptr = devres_alloc(devm_rdev_release, sizeof(*ptr),
+                          GFP_KERNEL);
+       if (!ptr)
+               return ERR_PTR(-ENOMEM);
+
+       rdev = regulator_register(regulator_desc, config);
+       if (!IS_ERR(rdev)) {
+               *ptr = rdev;
+               devres_add(dev, ptr);
+       } else {
+               devres_free(ptr);
+       }
+
+       return rdev;
+}
+EXPORT_SYMBOL_GPL(devm_regulator_register);
+
+static int devm_rdev_match(struct device *dev, void *res, void *data)
+{
+       struct regulator_dev **r = res;
+       if (!r || !*r) {
+               WARN_ON(!r || !*r);
+               return 0;
+       }
+       return *r == data;
+}
+
+/**
+ * devm_regulator_unregister - Resource managed regulator_unregister()
+ * @regulator: regulator to free
+ *
+ * Unregister a regulator registered with devm_regulator_register().
+ * Normally this function will not need to be called and the resource
+ * management code will ensure that the resource is freed.
+ */
+void devm_regulator_unregister(struct device *dev, struct regulator_dev *rdev)
+{
+       int rc;
+
+       rc = devres_release(dev, devm_rdev_release, devm_rdev_match, rdev);
+       if (rc != 0)
+               WARN_ON(rc);
+}
+EXPORT_SYMBOL_GPL(devm_regulator_unregister);
+
+struct regulator_supply_alias_match {
+       struct device *dev;
+       const char *id;
+};
+
+static int devm_regulator_match_supply_alias(struct device *dev, void *res,
+                                            void *data)
+{
+       struct regulator_supply_alias_match *match = res;
+       struct regulator_supply_alias_match *target = data;
+
+       return match->dev == target->dev && strcmp(match->id, target->id) == 0;
+}
+
+static void devm_regulator_destroy_supply_alias(struct device *dev, void *res)
+{
+       struct regulator_supply_alias_match *match = res;
+
+       regulator_unregister_supply_alias(match->dev, match->id);
+}
+
+/**
+ * devm_regulator_register_supply_alias - Resource managed
+ * regulator_register_supply_alias()
+ *
+ * @dev: device that will be given as the regulator "consumer"
+ * @id: Supply name or regulator ID
+ * @alias_dev: device that should be used to lookup the supply
+ * @alias_id: Supply name or regulator ID that should be used to lookup the
+ * supply
+ *
+ * The supply alias will automatically be unregistered when the source
+ * device is unbound.
+ */
+int devm_regulator_register_supply_alias(struct device *dev, const char *id,
+                                        struct device *alias_dev,
+                                        const char *alias_id)
+{
+       struct regulator_supply_alias_match *match;
+       int ret;
+
+       match = devres_alloc(devm_regulator_destroy_supply_alias,
+                          sizeof(struct regulator_supply_alias_match),
+                          GFP_KERNEL);
+       if (!match)
+               return -ENOMEM;
+
+       match->dev = dev;
+       match->id = id;
+
+       ret = regulator_register_supply_alias(dev, id, alias_dev, alias_id);
+       if (ret < 0) {
+               devres_free(match);
+               return ret;
+       }
+
+       devres_add(dev, match);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(devm_regulator_register_supply_alias);
+
+/**
+ * devm_regulator_unregister_supply_alias - Resource managed
+ * regulator_unregister_supply_alias()
+ *
+ * @dev: device that will be given as the regulator "consumer"
+ * @id: Supply name or regulator ID
+ *
+ * Unregister an alias registered with
+ * devm_regulator_register_supply_alias(). Normally this function
+ * will not need to be called and the resource management code
+ * will ensure that the resource is freed.
+ */
+void devm_regulator_unregister_supply_alias(struct device *dev, const char *id)
+{
+       struct regulator_supply_alias_match match;
+       int rc;
+
+       match.dev = dev;
+       match.id = id;
+
+       rc = devres_release(dev, devm_regulator_destroy_supply_alias,
+                           devm_regulator_match_supply_alias, &match);
+       if (rc != 0)
+               WARN_ON(rc);
+}
+EXPORT_SYMBOL_GPL(devm_regulator_unregister_supply_alias);
+
+/**
+ * devm_regulator_bulk_register_supply_alias - Managed register
+ * multiple aliases
+ *
+ * @dev: device that will be given as the regulator "consumer"
+ * @id: List of supply names or regulator IDs
+ * @alias_dev: device that should be used to lookup the supply
+ * @alias_id: List of supply names or regulator IDs that should be used to
+ * lookup the supply
+ * @num_id: Number of aliases to register
+ *
+ * @return 0 on success, an errno on failure.
+ *
+ * This helper function allows drivers to register several supply
+ * aliases in one operation, the aliases will be automatically
+ * unregisters when the source device is unbound.  If any of the
+ * aliases cannot be registered any aliases that were registered
+ * will be removed before returning to the caller.
+ */
+int devm_regulator_bulk_register_supply_alias(struct device *dev,
+                                             const char **id,
+                                             struct device *alias_dev,
+                                             const char **alias_id,
+                                             int num_id)
+{
+       int i;
+       int ret;
+
+       for (i = 0; i < num_id; ++i) {
+               ret = devm_regulator_register_supply_alias(dev, id[i],
+                                                          alias_dev,
+                                                          alias_id[i]);
+               if (ret < 0)
+                       goto err;
+       }
+
+       return 0;
+
+err:
+       dev_err(dev,
+               "Failed to create supply alias %s,%s -> %s,%s\n",
+               id[i], dev_name(dev), alias_id[i], dev_name(alias_dev));
+
+       while (--i >= 0)
+               devm_regulator_unregister_supply_alias(dev, id[i]);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(devm_regulator_bulk_register_supply_alias);
+
+/**
+ * devm_regulator_bulk_unregister_supply_alias - Managed unregister
+ * multiple aliases
+ *
+ * @dev: device that will be given as the regulator "consumer"
+ * @id: List of supply names or regulator IDs
+ * @num_id: Number of aliases to unregister
+ *
+ * Unregister aliases registered with
+ * devm_regulator_bulk_register_supply_alias(). Normally this function
+ * will not need to be called and the resource management code
+ * will ensure that the resource is freed.
+ */
+void devm_regulator_bulk_unregister_supply_alias(struct device *dev,
+                                                const char **id,
+                                                int num_id)
+{
+       int i;
+
+       for (i = 0; i < num_id; ++i)
+               devm_regulator_unregister_supply_alias(dev, id[i]);
+}
+EXPORT_SYMBOL_GPL(devm_regulator_bulk_unregister_supply_alias);
index 70b7220c587faccd1e41548f6d5e9343b0233838..7ca3d9e3b0fe22e426fb5419d76b9a4089224c7f 100644 (file)
@@ -218,9 +218,8 @@ static int fan53555_regulator_register(struct fan53555_device_info *di,
        rdesc->vsel_mask = VSEL_NSEL_MASK;
        rdesc->owner = THIS_MODULE;
 
-       di->rdev = regulator_register(&di->desc, config);
+       di->rdev = devm_regulator_register(di->dev, &di->desc, config);
        return PTR_ERR_OR_ZERO(di->rdev);
-
 }
 
 static struct regmap_config fan53555_regmap_config = {
@@ -291,14 +290,6 @@ static int fan53555_regulator_probe(struct i2c_client *client,
 
 }
 
-static int fan53555_regulator_remove(struct i2c_client *client)
-{
-       struct fan53555_device_info *di = i2c_get_clientdata(client);
-
-       regulator_unregister(di->rdev);
-       return 0;
-}
-
 static const struct i2c_device_id fan53555_id[] = {
        {"fan53555", -1},
        { },
@@ -309,7 +300,6 @@ static struct i2c_driver fan53555_regulator_driver = {
                .name = "fan53555-regulator",
        },
        .probe = fan53555_regulator_probe,
-       .remove = fan53555_regulator_remove,
        .id_table = fan53555_id,
 };
 
index 7610920014d789925368fd4316d35c1104fbf9ac..5ea64b94341c5f7a926b07d83536c9d4fe0dba32 100644 (file)
@@ -34,7 +34,6 @@
 struct fixed_voltage_data {
        struct regulator_desc desc;
        struct regulator_dev *dev;
-       int microvolts;
 };
 
 
@@ -108,30 +107,7 @@ of_get_fixed_voltage_config(struct device *dev)
        return config;
 }
 
-static int fixed_voltage_get_voltage(struct regulator_dev *dev)
-{
-       struct fixed_voltage_data *data = rdev_get_drvdata(dev);
-
-       if (data->microvolts)
-               return data->microvolts;
-       else
-               return -EINVAL;
-}
-
-static int fixed_voltage_list_voltage(struct regulator_dev *dev,
-                                     unsigned selector)
-{
-       struct fixed_voltage_data *data = rdev_get_drvdata(dev);
-
-       if (selector != 0)
-               return -EINVAL;
-
-       return data->microvolts;
-}
-
 static struct regulator_ops fixed_voltage_ops = {
-       .get_voltage = fixed_voltage_get_voltage,
-       .list_voltage = fixed_voltage_list_voltage,
 };
 
 static int reg_fixed_voltage_probe(struct platform_device *pdev)
@@ -186,23 +162,21 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
        if (config->microvolts)
                drvdata->desc.n_voltages = 1;
 
-       drvdata->microvolts = config->microvolts;
+       drvdata->desc.fixed_uV = config->microvolts;
 
        if (config->gpio >= 0)
                cfg.ena_gpio = config->gpio;
        cfg.ena_gpio_invert = !config->enable_high;
        if (config->enabled_at_boot) {
-               if (config->enable_high) {
+               if (config->enable_high)
                        cfg.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH;
-               } else {
+               else
                        cfg.ena_gpio_flags |= GPIOF_OUT_INIT_LOW;
-               }
        } else {
-               if (config->enable_high) {
+               if (config->enable_high)
                        cfg.ena_gpio_flags |= GPIOF_OUT_INIT_LOW;
-               } else {
+               else
                        cfg.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH;
-               }
        }
        if (config->gpio_is_open_drain)
                cfg.ena_gpio_flags |= GPIOF_OPEN_DRAIN;
@@ -222,7 +196,7 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, drvdata);
 
        dev_dbg(&pdev->dev, "%s supplying %duV\n", drvdata->desc.name,
-               drvdata->microvolts);
+               drvdata->desc.fixed_uV);
 
        return 0;
 
index 98a98ffa7fe07d2bcb23f2c9cad593b416aaf203..04406a918c041b5773adcf9adf331eadf289caf4 100644 (file)
@@ -283,7 +283,6 @@ static int gpio_regulator_probe(struct platform_device *pdev)
                dev_err(&pdev->dev, "No regulator type set\n");
                ret = -EINVAL;
                goto err_memgpio;
-               break;
        }
 
        drvdata->nr_gpios = config->nr_gpios;
index 6e30df14714bf15b944740c371d751413421ed3c..e221a271ba56601d12f5fc3d14a09db967a7d292 100644 (file)
@@ -284,9 +284,13 @@ int regulator_map_voltage_linear_range(struct regulator_dev *rdev,
        }
 
        for (i = 0; i < rdev->desc->n_linear_ranges; i++) {
+               int linear_max_uV;
+
                range = &rdev->desc->linear_ranges[i];
+               linear_max_uV = range->min_uV +
+                       (range->max_sel - range->min_sel) * range->uV_step;
 
-               if (!(min_uV <= range->max_uV && max_uV >= range->min_uV))
+               if (!(min_uV <= linear_max_uV && max_uV >= range->min_uV))
                        continue;
 
                if (min_uV <= range->min_uV)
diff --git a/drivers/regulator/internal.h b/drivers/regulator/internal.h
new file mode 100644 (file)
index 0000000..84bbda1
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * internal.h  --  Voltage/Current Regulator framework internal code
+ *
+ * Copyright 2007, 2008 Wolfson Microelectronics PLC.
+ * Copyright 2008 SlimLogic Ltd.
+ *
+ * Author: Liam Girdwood <lrg@slimlogic.co.uk>
+ *
+ *  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.
+ *
+ */
+
+#ifndef __REGULATOR_INTERNAL_H
+#define __REGULATOR_INTERNAL_H
+
+/*
+ * struct regulator
+ *
+ * One for each consumer device.
+ */
+struct regulator {
+       struct device *dev;
+       struct list_head list;
+       unsigned int always_on:1;
+       unsigned int bypass:1;
+       int uA_load;
+       int min_uV;
+       int max_uV;
+       char *supply_name;
+       struct device_attribute dev_attr;
+       struct regulator_dev *rdev;
+       struct dentry *debugfs;
+};
+
+#endif
index 88c1a3acf563ebad5aa6301636961eda75528365..6e5da95fa025d4df8c8f3821230ec491be64bd22 100644 (file)
@@ -112,7 +112,7 @@ static int isl6271a_probe(struct i2c_client *i2c,
        struct regulator_config config = { };
        struct regulator_init_data *init_data   = dev_get_platdata(&i2c->dev);
        struct isl_pmic *pmic;
-       int err, i;
+       int i;
 
        if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
                return -EIO;
@@ -133,32 +133,17 @@ static int isl6271a_probe(struct i2c_client *i2c,
                        config.init_data = NULL;
                config.driver_data = pmic;
 
-               pmic->rdev[i] = regulator_register(&isl_rd[i], &config);
+               pmic->rdev[i] = devm_regulator_register(&i2c->dev, &isl_rd[i],
+                                                       &config);
                if (IS_ERR(pmic->rdev[i])) {
                        dev_err(&i2c->dev, "failed to register %s\n", id->name);
-                       err = PTR_ERR(pmic->rdev[i]);
-                       goto error;
+                       return PTR_ERR(pmic->rdev[i]);
                }
        }
 
        i2c_set_clientdata(i2c, pmic);
 
        return 0;
-
-error:
-       while (--i >= 0)
-               regulator_unregister(pmic->rdev[i]);
-       return err;
-}
-
-static int isl6271a_remove(struct i2c_client *i2c)
-{
-       struct isl_pmic *pmic = i2c_get_clientdata(i2c);
-       int i;
-
-       for (i = 0; i < 3; i++)
-               regulator_unregister(pmic->rdev[i]);
-       return 0;
 }
 
 static const struct i2c_device_id isl6271a_id[] = {
@@ -174,7 +159,6 @@ static struct i2c_driver isl6271a_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe = isl6271a_probe,
-       .remove = isl6271a_remove,
        .id_table = isl6271a_id,
 };
 
index 5a4604ee5ea593d33fa0e3412b36ff9baf6bae40..947c05ffe0ab9887899a871a1576936b01b8ba3a 100644 (file)
@@ -474,8 +474,8 @@ static int lp3971_i2c_remove(struct i2c_client *i2c)
 }
 
 static const struct i2c_device_id lp3971_i2c_id[] = {
-       { "lp3971", 0 },
-       { }
+       { "lp3971", 0 },
+       { }
 };
 MODULE_DEVICE_TABLE(i2c, lp3971_i2c_id);
 
index 2b84b727a3c498c6e22f97fe9d297d06ee1470c8..2e4734ff79fce29eaa2cab621b2e13cfa565a0da 100644 (file)
@@ -785,7 +785,7 @@ static int lp872x_regulator_register(struct lp872x *lp)
        struct regulator_desc *desc;
        struct regulator_config cfg = { };
        struct regulator_dev *rdev;
-       int i, ret;
+       int i;
 
        for (i = 0; i < lp->num_regulators; i++) {
                desc = (lp->chipid == LP8720) ? &lp8720_regulator_desc[i] :
@@ -796,34 +796,16 @@ static int lp872x_regulator_register(struct lp872x *lp)
                cfg.driver_data = lp;
                cfg.regmap = lp->regmap;
 
-               rdev = regulator_register(desc, &cfg);
+               rdev = devm_regulator_register(lp->dev, desc, &cfg);
                if (IS_ERR(rdev)) {
                        dev_err(lp->dev, "regulator register err");
-                       ret =  PTR_ERR(rdev);
-                       goto err;
+                       return PTR_ERR(rdev);
                }
 
                *(lp->regulators + i) = rdev;
        }
 
        return 0;
-err:
-       while (--i >= 0) {
-               rdev = *(lp->regulators + i);
-               regulator_unregister(rdev);
-       }
-       return ret;
-}
-
-static void lp872x_regulator_unregister(struct lp872x *lp)
-{
-       struct regulator_dev *rdev;
-       int i;
-
-       for (i = 0; i < lp->num_regulators; i++) {
-               rdev = *(lp->regulators + i);
-               regulator_unregister(rdev);
-       }
 }
 
 static const struct regmap_config lp872x_regmap_config = {
@@ -979,14 +961,6 @@ err_dev:
        return ret;
 }
 
-static int lp872x_remove(struct i2c_client *cl)
-{
-       struct lp872x *lp = i2c_get_clientdata(cl);
-
-       lp872x_regulator_unregister(lp);
-       return 0;
-}
-
 static const struct of_device_id lp872x_dt_ids[] = {
        { .compatible = "ti,lp8720", },
        { .compatible = "ti,lp8725", },
@@ -1008,7 +982,6 @@ static struct i2c_driver lp872x_driver = {
                .of_match_table = of_match_ptr(lp872x_dt_ids),
        },
        .probe = lp872x_probe,
-       .remove = lp872x_remove,
        .id_table = lp872x_ids,
 };
 
index 0b015f2a7fd9e3dd33c0928421f55441b1459467..948afc249e296005207c621d3d3bfbfb39b914e2 100644 (file)
@@ -515,7 +515,7 @@ static int lp8788_buck_probe(struct platform_device *pdev)
        cfg.driver_data = buck;
        cfg.regmap = lp->regmap;
 
-       rdev = regulator_register(&lp8788_buck_desc[id], &cfg);
+       rdev = devm_regulator_register(&pdev->dev, &lp8788_buck_desc[id], &cfg);
        if (IS_ERR(rdev)) {
                ret = PTR_ERR(rdev);
                dev_err(&pdev->dev, "BUCK%d regulator register err = %d\n",
@@ -529,18 +529,8 @@ static int lp8788_buck_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int lp8788_buck_remove(struct platform_device *pdev)
-{
-       struct lp8788_buck *buck = platform_get_drvdata(pdev);
-
-       regulator_unregister(buck->regulator);
-
-       return 0;
-}
-
 static struct platform_driver lp8788_buck_driver = {
        .probe = lp8788_buck_probe,
-       .remove = lp8788_buck_remove,
        .driver = {
                .name = LP8788_DEV_BUCK,
                .owner = THIS_MODULE,
index 0527d87c6dd5adea8c7614ecc61f44fc8599f5f6..b9a29a29933fb8658e3a53202ceafcd41ae27c73 100644 (file)
@@ -543,7 +543,7 @@ static int lp8788_dldo_probe(struct platform_device *pdev)
        cfg.driver_data = ldo;
        cfg.regmap = lp->regmap;
 
-       rdev = regulator_register(&lp8788_dldo_desc[id], &cfg);
+       rdev = devm_regulator_register(&pdev->dev, &lp8788_dldo_desc[id], &cfg);
        if (IS_ERR(rdev)) {
                ret = PTR_ERR(rdev);
                dev_err(&pdev->dev, "DLDO%d regulator register err = %d\n",
@@ -557,18 +557,8 @@ static int lp8788_dldo_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int lp8788_dldo_remove(struct platform_device *pdev)
-{
-       struct lp8788_ldo *ldo = platform_get_drvdata(pdev);
-
-       regulator_unregister(ldo->regulator);
-
-       return 0;
-}
-
 static struct platform_driver lp8788_dldo_driver = {
        .probe = lp8788_dldo_probe,
-       .remove = lp8788_dldo_remove,
        .driver = {
                .name = LP8788_DEV_DLDO,
                .owner = THIS_MODULE,
@@ -603,7 +593,7 @@ static int lp8788_aldo_probe(struct platform_device *pdev)
        cfg.driver_data = ldo;
        cfg.regmap = lp->regmap;
 
-       rdev = regulator_register(&lp8788_aldo_desc[id], &cfg);
+       rdev = devm_regulator_register(&pdev->dev, &lp8788_aldo_desc[id], &cfg);
        if (IS_ERR(rdev)) {
                ret = PTR_ERR(rdev);
                dev_err(&pdev->dev, "ALDO%d regulator register err = %d\n",
@@ -617,18 +607,8 @@ static int lp8788_aldo_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int lp8788_aldo_remove(struct platform_device *pdev)
-{
-       struct lp8788_ldo *ldo = platform_get_drvdata(pdev);
-
-       regulator_unregister(ldo->regulator);
-
-       return 0;
-}
-
 static struct platform_driver lp8788_aldo_driver = {
        .probe = lp8788_aldo_probe,
-       .remove = lp8788_aldo_remove,
        .driver = {
                .name = LP8788_DEV_ALDO,
                .owner = THIS_MODULE,
index 3a599ee0a456000b5058771e5a8325d76afca521..e242dd316d363bb7f4226f2abfdee051c4d095d3 100644 (file)
@@ -166,7 +166,7 @@ static int max1586_pmic_probe(struct i2c_client *client,
        struct max1586_platform_data *pdata = dev_get_platdata(&client->dev);
        struct regulator_config config = { };
        struct max1586_data *max1586;
-       int i, id, ret = -ENOMEM;
+       int i, id;
 
        max1586 = devm_kzalloc(&client->dev, sizeof(struct max1586_data) +
                        sizeof(struct regulator_dev *) * (MAX1586_V6 + 1),
@@ -193,7 +193,7 @@ static int max1586_pmic_probe(struct i2c_client *client,
                        continue;
                if (id < MAX1586_V3 || id > MAX1586_V6) {
                        dev_err(&client->dev, "invalid regulator id %d\n", id);
-                       goto err;
+                       return -EINVAL;
                }
 
                if (id == MAX1586_V3) {
@@ -207,33 +207,18 @@ static int max1586_pmic_probe(struct i2c_client *client,
                config.init_data = pdata->subdevs[i].platform_data;
                config.driver_data = max1586;
 
-               rdev[i] = regulator_register(&max1586_reg[id], &config);
+               rdev[i] = devm_regulator_register(&client->dev,
+                                                 &max1586_reg[id], &config);
                if (IS_ERR(rdev[i])) {
-                       ret = PTR_ERR(rdev[i]);
                        dev_err(&client->dev, "failed to register %s\n",
                                max1586_reg[id].name);
-                       goto err;
+                       return PTR_ERR(rdev[i]);
                }
        }
 
        i2c_set_clientdata(client, max1586);
        dev_info(&client->dev, "Maxim 1586 regulator driver loaded\n");
        return 0;
-
-err:
-       while (--i >= 0)
-               regulator_unregister(rdev[i]);
-       return ret;
-}
-
-static int max1586_pmic_remove(struct i2c_client *client)
-{
-       struct max1586_data *max1586 = i2c_get_clientdata(client);
-       int i;
-
-       for (i = 0; i <= MAX1586_V6; i++)
-               regulator_unregister(max1586->rdev[i]);
-       return 0;
 }
 
 static const struct i2c_device_id max1586_id[] = {
@@ -244,7 +229,6 @@ MODULE_DEVICE_TABLE(i2c, max1586_id);
 
 static struct i2c_driver max1586_pmic_driver = {
        .probe = max1586_pmic_probe,
-       .remove = max1586_pmic_remove,
        .driver         = {
                .name   = "max1586",
                .owner  = THIS_MODULE,
index f563057e56904c868a5344a43e80e41e97ced60d..ae001ccf26f42d952bec37c2a821c250e2307b3c 100644 (file)
@@ -478,31 +478,15 @@ static int max77686_pmic_probe(struct platform_device *pdev)
                config.of_node = pdata->regulators[i].of_node;
 
                max77686->opmode[i] = regulators[i].enable_mask;
-               max77686->rdev[i] = regulator_register(&regulators[i], &config);
+               max77686->rdev[i] = devm_regulator_register(&pdev->dev,
+                                               &regulators[i], &config);
                if (IS_ERR(max77686->rdev[i])) {
-                       ret = PTR_ERR(max77686->rdev[i]);
                        dev_err(&pdev->dev,
                                "regulator init failed for %d\n", i);
-                       max77686->rdev[i] = NULL;
-                       goto err;
+                       return PTR_ERR(max77686->rdev[i]);
                }
        }
 
-       return 0;
-err:
-       while (--i >= 0)
-               regulator_unregister(max77686->rdev[i]);
-       return ret;
-}
-
-static int max77686_pmic_remove(struct platform_device *pdev)
-{
-       struct max77686_data *max77686 = platform_get_drvdata(pdev);
-       int i;
-
-       for (i = 0; i < MAX77686_REGULATORS; i++)
-               regulator_unregister(max77686->rdev[i]);
-
        return 0;
 }
 
@@ -518,7 +502,6 @@ static struct platform_driver max77686_pmic_driver = {
                .owner = THIS_MODULE,
        },
        .probe = max77686_pmic_probe,
-       .remove = max77686_pmic_remove,
        .id_table = max77686_pmic_id,
 };
 
index ce4b96c15ebaaf37cb26daa2d4a51df68d1e31e3..feb20bf4ccab4b056003896773ae86dec5c7219e 100644 (file)
@@ -230,7 +230,7 @@ static int max77693_pmic_probe(struct platform_device *pdev)
        struct max77693_dev *iodev = dev_get_drvdata(pdev->dev.parent);
        struct max77693_pmic_dev *max77693_pmic;
        struct max77693_regulator_data *rdata = NULL;
-       int num_rdata, i, ret;
+       int num_rdata, i;
        struct regulator_config config;
 
        num_rdata = max77693_pmic_init_rdata(&pdev->dev, &rdata);
@@ -266,35 +266,15 @@ static int max77693_pmic_probe(struct platform_device *pdev)
                config.init_data = rdata[i].initdata;
                config.of_node = rdata[i].of_node;
 
-               max77693_pmic->rdev[i] = regulator_register(&regulators[id],
-                                                           &config);
+               max77693_pmic->rdev[i] = devm_regulator_register(&pdev->dev,
+                                               &regulators[id], &config);
                if (IS_ERR(max77693_pmic->rdev[i])) {
-                       ret = PTR_ERR(max77693_pmic->rdev[i]);
                        dev_err(max77693_pmic->dev,
                                "Failed to initialize regulator-%d\n", id);
-                       max77693_pmic->rdev[i] = NULL;
-                       goto err;
+                       return PTR_ERR(max77693_pmic->rdev[i]);
                }
        }
 
-       return 0;
- err:
-       while (--i >= 0)
-               regulator_unregister(max77693_pmic->rdev[i]);
-
-       return ret;
-}
-
-static int max77693_pmic_remove(struct platform_device *pdev)
-{
-       struct max77693_pmic_dev *max77693_pmic = platform_get_drvdata(pdev);
-       struct regulator_dev **rdev = max77693_pmic->rdev;
-       int i;
-
-       for (i = 0; i < max77693_pmic->num_regulators; i++)
-               if (rdev[i])
-                       regulator_unregister(rdev[i]);
-
        return 0;
 }
 
@@ -311,7 +291,6 @@ static struct platform_driver max77693_pmic_driver = {
                   .owner = THIS_MODULE,
                   },
        .probe = max77693_pmic_probe,
-       .remove = max77693_pmic_remove,
        .id_table = max77693_pmic_id,
 };
 
index 19c6f08eafd5bddfe5a626696bafcea8bf5f36ec..7f049c92ee52406bbbc7bd3e08573bdd89f25159 100644 (file)
@@ -234,7 +234,8 @@ static int max8649_regulator_probe(struct i2c_client *client,
        config.driver_data = info;
        config.regmap = info->regmap;
 
-       info->regulator = regulator_register(&dcdc_desc, &config);
+       info->regulator = devm_regulator_register(&client->dev, &dcdc_desc,
+                                                 &config);
        if (IS_ERR(info->regulator)) {
                dev_err(info->dev, "failed to register regulator %s\n",
                        dcdc_desc.name);
@@ -244,16 +245,6 @@ static int max8649_regulator_probe(struct i2c_client *client,
        return 0;
 }
 
-static int max8649_regulator_remove(struct i2c_client *client)
-{
-       struct max8649_regulator_info *info = i2c_get_clientdata(client);
-
-       if (info)
-               regulator_unregister(info->regulator);
-
-       return 0;
-}
-
 static const struct i2c_device_id max8649_id[] = {
        { "max8649", 0 },
        { }
@@ -262,7 +253,6 @@ MODULE_DEVICE_TABLE(i2c, max8649_id);
 
 static struct i2c_driver max8649_driver = {
        .probe          = max8649_regulator_probe,
-       .remove         = max8649_regulator_remove,
        .driver         = {
                .name   = "max8649",
        },
index 144bcacd734dbe39e44801e411990e15a45d18eb..8d94d3d7f97f22336fb973d5659ed50b4a3e6a97 100644 (file)
@@ -439,7 +439,7 @@ static int max8660_probe(struct i2c_client *client,
        for (i = 0; i < pdata->num_subdevs; i++) {
 
                if (!pdata->subdevs[i].platform_data)
-                       goto err_out;
+                       return ret;
 
                boot_on = pdata->subdevs[i].platform_data->constraints.boot_on;
 
@@ -465,7 +465,7 @@ static int max8660_probe(struct i2c_client *client,
                case MAX8660_V7:
                        if (type == MAX8661) {
                                dev_err(dev, "Regulator not on this chip!\n");
-                               goto err_out;
+                               return -EINVAL;
                        }
 
                        if (boot_on)
@@ -475,7 +475,7 @@ static int max8660_probe(struct i2c_client *client,
                default:
                        dev_err(dev, "invalid regulator %s\n",
                                 pdata->subdevs[i].name);
-                       goto err_out;
+                       return ret;
                }
        }
 
@@ -489,33 +489,18 @@ static int max8660_probe(struct i2c_client *client,
                config.of_node = of_node[i];
                config.driver_data = max8660;
 
-               rdev[i] = regulator_register(&max8660_reg[id], &config);
+               rdev[i] = devm_regulator_register(&client->dev,
+                                                 &max8660_reg[id], &config);
                if (IS_ERR(rdev[i])) {
                        ret = PTR_ERR(rdev[i]);
-                       dev_err(dev, "failed to register %s\n",
+                       dev_err(&client->dev, "failed to register %s\n",
                                max8660_reg[id].name);
-                       goto err_unregister;
+                       return PTR_ERR(rdev[i]);
                }
        }
 
        i2c_set_clientdata(client, max8660);
        return 0;
-
-err_unregister:
-       while (--i >= 0)
-               regulator_unregister(rdev[i]);
-err_out:
-       return ret;
-}
-
-static int max8660_remove(struct i2c_client *client)
-{
-       struct max8660 *max8660 = i2c_get_clientdata(client);
-       int i;
-
-       for (i = 0; i < MAX8660_V_END; i++)
-               regulator_unregister(max8660->rdev[i]);
-       return 0;
 }
 
 static const struct i2c_device_id max8660_id[] = {
@@ -527,7 +512,6 @@ MODULE_DEVICE_TABLE(i2c, max8660_id);
 
 static struct i2c_driver max8660_driver = {
        .probe = max8660_probe,
-       .remove = max8660_remove,
        .driver         = {
                .name   = "max8660",
                .owner  = THIS_MODULE,
index 4568c15fa78dea0eafda170f64f9fc86db251faa..0c5fe6c6ac26eb22ba248c3b64bbe9c98129283b 100644 (file)
@@ -350,33 +350,17 @@ static int max8907_regulator_probe(struct platform_device *pdev)
                                pmic->desc[i].ops = &max8907_out5v_hwctl_ops;
                }
 
-               pmic->rdev[i] = regulator_register(&pmic->desc[i], &config);
+               pmic->rdev[i] = devm_regulator_register(&pdev->dev,
+                                               &pmic->desc[i], &config);
                if (IS_ERR(pmic->rdev[i])) {
                        dev_err(&pdev->dev,
                                "failed to register %s regulator\n",
                                pmic->desc[i].name);
-                       ret = PTR_ERR(pmic->rdev[i]);
-                       goto err_unregister_regulator;
+                       return PTR_ERR(pmic->rdev[i]);
                }
        }
 
        return 0;
-
-err_unregister_regulator:
-       while (--i >= 0)
-               regulator_unregister(pmic->rdev[i]);
-       return ret;
-}
-
-static int max8907_regulator_remove(struct platform_device *pdev)
-{
-       struct max8907_regulator *pmic = platform_get_drvdata(pdev);
-       int i;
-
-       for (i = 0; i < MAX8907_NUM_REGULATORS; i++)
-               regulator_unregister(pmic->rdev[i]);
-
-       return 0;
 }
 
 static struct platform_driver max8907_regulator_driver = {
@@ -385,7 +369,6 @@ static struct platform_driver max8907_regulator_driver = {
                   .owner = THIS_MODULE,
                   },
        .probe = max8907_regulator_probe,
-       .remove = max8907_regulator_remove,
 };
 
 static int __init max8907_regulator_init(void)
index d80b5fa758ae5012585acb0a2e2b2947005177ce..759510789e71db39b0b287f9849cea88827d50c4 100644 (file)
@@ -312,7 +312,7 @@ static int max8925_regulator_probe(struct platform_device *pdev)
                if (pdata)
                        config.init_data = pdata;
 
-       rdev = regulator_register(&ri->desc, &config);
+       rdev = devm_regulator_register(&pdev->dev, &ri->desc, &config);
        if (IS_ERR(rdev)) {
                dev_err(&pdev->dev, "failed to register regulator %s\n",
                                ri->desc.name);
@@ -323,22 +323,12 @@ static int max8925_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int max8925_regulator_remove(struct platform_device *pdev)
-{
-       struct regulator_dev *rdev = platform_get_drvdata(pdev);
-
-       regulator_unregister(rdev);
-
-       return 0;
-}
-
 static struct platform_driver max8925_regulator_driver = {
        .driver         = {
                .name   = "max8925-regulator",
                .owner  = THIS_MODULE,
        },
        .probe          = max8925_regulator_probe,
-       .remove         = max8925_regulator_remove,
 };
 
 static int __init max8925_regulator_init(void)
index 5b77ab7762e43c6915dc039e4f7a935a0a4d1adf..892aa1e5b96c65dc2d879be20b3bb97b290af67a 100644 (file)
@@ -467,7 +467,7 @@ static int max8973_probe(struct i2c_client *client,
        config.regmap = max->regmap;
 
        /* Register the regulators */
-       rdev = regulator_register(&max->desc, &config);
+       rdev = devm_regulator_register(&client->dev, &max->desc, &config);
        if (IS_ERR(rdev)) {
                ret = PTR_ERR(rdev);
                dev_err(max->dev, "regulator register failed, err %d\n", ret);
@@ -478,14 +478,6 @@ static int max8973_probe(struct i2c_client *client,
        return 0;
 }
 
-static int max8973_remove(struct i2c_client *client)
-{
-       struct max8973_chip *max = i2c_get_clientdata(client);
-
-       regulator_unregister(max->rdev);
-       return 0;
-}
-
 static const struct i2c_device_id max8973_id[] = {
        {.name = "max8973",},
        {},
@@ -499,7 +491,6 @@ static struct i2c_driver max8973_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe = max8973_probe,
-       .remove = max8973_remove,
        .id_table = max8973_id,
 };
 
index df20069f05375ae3bb7661f029119496fe7d8b21..2d618fc9c1af51da55ebce43be2e7c62db8c3eab 100644 (file)
@@ -690,8 +690,9 @@ static int max8997_set_voltage_buck(struct regulator_dev *rdev,
        if (max8997->ignore_gpiodvs_side_effect == false)
                return -EINVAL;
 
-       dev_warn(&rdev->dev, "MAX8997 GPIO-DVS Side Effect Warning: GPIO SET:"
-                       " %d -> %d\n", max8997->buck125_gpioindex, tmp_idx);
+       dev_warn(&rdev->dev,
+               "MAX8997 GPIO-DVS Side Effect Warning: GPIO SET:  %d -> %d\n",
+               max8997->buck125_gpioindex, tmp_idx);
 
 out:
        if (new_idx < 0 || new_val < 0)
@@ -1081,7 +1082,7 @@ static int max8997_pmic_probe(struct platform_device *pdev)
                                        pdata->buck1_voltage[i] +
                                        buck1245_voltage_map_desc.step);
                if (ret < 0)
-                       goto err_out;
+                       return ret;
 
                max8997->buck2_vol[i] = ret =
                        max8997_get_voltage_proper_val(
@@ -1090,7 +1091,7 @@ static int max8997_pmic_probe(struct platform_device *pdev)
                                        pdata->buck2_voltage[i] +
                                        buck1245_voltage_map_desc.step);
                if (ret < 0)
-                       goto err_out;
+                       return ret;
 
                max8997->buck5_vol[i] = ret =
                        max8997_get_voltage_proper_val(
@@ -1099,7 +1100,7 @@ static int max8997_pmic_probe(struct platform_device *pdev)
                                        pdata->buck5_voltage[i] +
                                        buck1245_voltage_map_desc.step);
                if (ret < 0)
-                       goto err_out;
+                       return ret;
 
                if (max_buck1 < max8997->buck1_vol[i])
                        max_buck1 = max8997->buck1_vol[i];
@@ -1143,24 +1144,23 @@ static int max8997_pmic_probe(struct platform_device *pdev)
                                !gpio_is_valid(pdata->buck125_gpios[1]) ||
                                !gpio_is_valid(pdata->buck125_gpios[2])) {
                        dev_err(&pdev->dev, "GPIO NOT VALID\n");
-                       ret = -EINVAL;
-                       goto err_out;
+                       return -EINVAL;
                }
 
                ret = devm_gpio_request(&pdev->dev, pdata->buck125_gpios[0],
                                        "MAX8997 SET1");
                if (ret)
-                       goto err_out;
+                       return ret;
 
                ret = devm_gpio_request(&pdev->dev, pdata->buck125_gpios[1],
                                        "MAX8997 SET2");
                if (ret)
-                       goto err_out;
+                       return ret;
 
                ret = devm_gpio_request(&pdev->dev, pdata->buck125_gpios[2],
                                "MAX8997 SET3");
                if (ret)
-                       goto err_out;
+                       return ret;
 
                gpio_direction_output(pdata->buck125_gpios[0],
                                (max8997->buck125_gpioindex >> 2)
@@ -1205,33 +1205,16 @@ static int max8997_pmic_probe(struct platform_device *pdev)
                config.driver_data = max8997;
                config.of_node = pdata->regulators[i].reg_node;
 
-               rdev[i] = regulator_register(&regulators[id], &config);
+               rdev[i] = devm_regulator_register(&pdev->dev, &regulators[id],
+                                                 &config);
                if (IS_ERR(rdev[i])) {
-                       ret = PTR_ERR(rdev[i]);
                        dev_err(max8997->dev, "regulator init failed for %d\n",
                                        id);
-                       rdev[i] = NULL;
-                       goto err;
+                       return PTR_ERR(rdev[i]);
                }
        }
 
        return 0;
-err:
-       while (--i >= 0)
-               regulator_unregister(rdev[i]);
-err_out:
-       return ret;
-}
-
-static int max8997_pmic_remove(struct platform_device *pdev)
-{
-       struct max8997_data *max8997 = platform_get_drvdata(pdev);
-       struct regulator_dev **rdev = max8997->rdev;
-       int i;
-
-       for (i = 0; i < max8997->num_regulators; i++)
-               regulator_unregister(rdev[i]);
-       return 0;
 }
 
 static const struct platform_device_id max8997_pmic_id[] = {
@@ -1246,7 +1229,6 @@ static struct platform_driver max8997_pmic_driver = {
                .owner = THIS_MODULE,
        },
        .probe = max8997_pmic_probe,
-       .remove = max8997_pmic_remove,
        .id_table = max8997_pmic_id,
 };
 
index a4c53b2d1aaf5210482976fd97504485e90fd247..ae3f0656feb00c406ca438642c051a6453ab9171 100644 (file)
@@ -790,16 +790,14 @@ static int max8998_pmic_probe(struct platform_device *pdev)
                        dev_err(&pdev->dev,
                                "MAX8998 SET1 GPIO defined as 0 !\n");
                        WARN_ON(!pdata->buck1_set1);
-                       ret = -EIO;
-                       goto err_out;
+                       return -EIO;
                }
                /* Check if SET2 is not equal to 0 */
                if (!pdata->buck1_set2) {
                        dev_err(&pdev->dev,
                                "MAX8998 SET2 GPIO defined as 0 !\n");
                        WARN_ON(!pdata->buck1_set2);
-                       ret = -EIO;
-                       goto err_out;
+                       return -EIO;
                }
 
                gpio_request(pdata->buck1_set1, "MAX8998 BUCK1_SET1");
@@ -823,7 +821,7 @@ static int max8998_pmic_probe(struct platform_device *pdev)
                        ret = max8998_write_reg(i2c,
                                        MAX8998_REG_BUCK1_VOLTAGE1 + v, i);
                        if (ret)
-                               goto err_out;
+                               return ret;
                }
        }
 
@@ -833,8 +831,7 @@ static int max8998_pmic_probe(struct platform_device *pdev)
                        dev_err(&pdev->dev,
                                "MAX8998 SET3 GPIO defined as 0 !\n");
                        WARN_ON(!pdata->buck2_set3);
-                       ret = -EIO;
-                       goto err_out;
+                       return -EIO;
                }
                gpio_request(pdata->buck2_set3, "MAX8998 BUCK2_SET3");
                gpio_direction_output(pdata->buck2_set3,
@@ -852,7 +849,7 @@ static int max8998_pmic_probe(struct platform_device *pdev)
                        ret = max8998_write_reg(i2c,
                                        MAX8998_REG_BUCK2_VOLTAGE1 + v, i);
                        if (ret)
-                               goto err_out;
+                               return ret;
                }
        }
 
@@ -875,33 +872,18 @@ static int max8998_pmic_probe(struct platform_device *pdev)
                config.init_data = pdata->regulators[i].initdata;
                config.driver_data = max8998;
 
-               rdev[i] = regulator_register(&regulators[index], &config);
+               rdev[i] = devm_regulator_register(&pdev->dev,
+                                                 &regulators[index], &config);
                if (IS_ERR(rdev[i])) {
                        ret = PTR_ERR(rdev[i]);
                        dev_err(max8998->dev, "regulator %s init failed (%d)\n",
                                                regulators[index].name, ret);
                        rdev[i] = NULL;
-                       goto err;
+                       return ret;
                }
        }
 
 
-       return 0;
-err:
-       while (--i >= 0)
-               regulator_unregister(rdev[i]);
-err_out:
-       return ret;
-}
-
-static int max8998_pmic_remove(struct platform_device *pdev)
-{
-       struct max8998_data *max8998 = platform_get_drvdata(pdev);
-       struct regulator_dev **rdev = max8998->rdev;
-       int i;
-
-       for (i = 0; i < max8998->num_regulators; i++)
-               regulator_unregister(rdev[i]);
        return 0;
 }
 
@@ -918,7 +900,6 @@ static struct platform_driver max8998_pmic_driver = {
                .owner = THIS_MODULE,
        },
        .probe = max8998_pmic_probe,
-       .remove = max8998_pmic_remove,
        .id_table = max8998_pmic_id,
 };
 
index 5ff99d2703db0db55e947be9cf88a6fca46c53cc..7f4a67edf780ed5ab8e007996fe3bcdfc51db2d8 100644 (file)
@@ -258,34 +258,34 @@ static struct mc13xxx_regulator mc13783_regulators[] = {
 
        MC13783_FIXED_DEFINE(REG, VAUDIO, REGULATORMODE0, mc13783_vaudio_val),
        MC13783_FIXED_DEFINE(REG, VIOHI, REGULATORMODE0, mc13783_viohi_val),
-       MC13783_DEFINE_REGU(VIOLO, REGULATORMODE0, REGULATORSETTING0,   \
+       MC13783_DEFINE_REGU(VIOLO, REGULATORMODE0, REGULATORSETTING0,
                            mc13783_violo_val),
-       MC13783_DEFINE_REGU(VDIG, REGULATORMODE0, REGULATORSETTING0,    \
+       MC13783_DEFINE_REGU(VDIG, REGULATORMODE0, REGULATORSETTING0,
                            mc13783_vdig_val),
-       MC13783_DEFINE_REGU(VGEN, REGULATORMODE0, REGULATORSETTING0,    \
+       MC13783_DEFINE_REGU(VGEN, REGULATORMODE0, REGULATORSETTING0,
                            mc13783_vgen_val),
-       MC13783_DEFINE_REGU(VRFDIG, REGULATORMODE0, REGULATORSETTING0,  \
+       MC13783_DEFINE_REGU(VRFDIG, REGULATORMODE0, REGULATORSETTING0,
                            mc13783_vrfdig_val),
-       MC13783_DEFINE_REGU(VRFREF, REGULATORMODE0, REGULATORSETTING0,  \
+       MC13783_DEFINE_REGU(VRFREF, REGULATORMODE0, REGULATORSETTING0,
                            mc13783_vrfref_val),
-       MC13783_DEFINE_REGU(VRFCP, REGULATORMODE0, REGULATORSETTING0,   \
+       MC13783_DEFINE_REGU(VRFCP, REGULATORMODE0, REGULATORSETTING0,
                            mc13783_vrfcp_val),
-       MC13783_DEFINE_REGU(VSIM, REGULATORMODE1, REGULATORSETTING0,    \
+       MC13783_DEFINE_REGU(VSIM, REGULATORMODE1, REGULATORSETTING0,
                            mc13783_vsim_val),
-       MC13783_DEFINE_REGU(VESIM, REGULATORMODE1, REGULATORSETTING0,   \
+       MC13783_DEFINE_REGU(VESIM, REGULATORMODE1, REGULATORSETTING0,
                            mc13783_vesim_val),
-       MC13783_DEFINE_REGU(VCAM, REGULATORMODE1, REGULATORSETTING0,    \
+       MC13783_DEFINE_REGU(VCAM, REGULATORMODE1, REGULATORSETTING0,
                            mc13783_vcam_val),
        MC13783_FIXED_DEFINE(REG, VRFBG, REGULATORMODE1, mc13783_vrfbg_val),
-       MC13783_DEFINE_REGU(VVIB, REGULATORMODE1, REGULATORSETTING1,    \
+       MC13783_DEFINE_REGU(VVIB, REGULATORMODE1, REGULATORSETTING1,
                            mc13783_vvib_val),
-       MC13783_DEFINE_REGU(VRF1, REGULATORMODE1, REGULATORSETTING1,    \
+       MC13783_DEFINE_REGU(VRF1, REGULATORMODE1, REGULATORSETTING1,
                            mc13783_vrf_val),
-       MC13783_DEFINE_REGU(VRF2, REGULATORMODE1, REGULATORSETTING1,    \
+       MC13783_DEFINE_REGU(VRF2, REGULATORMODE1, REGULATORSETTING1,
                            mc13783_vrf_val),
-       MC13783_DEFINE_REGU(VMMC1, REGULATORMODE1, REGULATORSETTING1,   \
+       MC13783_DEFINE_REGU(VMMC1, REGULATORMODE1, REGULATORSETTING1,
                            mc13783_vmmc_val),
-       MC13783_DEFINE_REGU(VMMC2, REGULATORMODE1, REGULATORSETTING1,   \
+       MC13783_DEFINE_REGU(VMMC2, REGULATORMODE1, REGULATORSETTING1,
                            mc13783_vmmc_val),
        MC13783_GPO_DEFINE(REG, GPO1, POWERMISC, mc13783_gpo_val),
        MC13783_GPO_DEFINE(REG, GPO2, POWERMISC, mc13783_gpo_val),
@@ -400,7 +400,7 @@ static int mc13783_regulator_probe(struct platform_device *pdev)
                dev_get_platdata(&pdev->dev);
        struct mc13xxx_regulator_init_data *mc13xxx_data;
        struct regulator_config config = { };
-       int i, ret, num_regulators;
+       int i, num_regulators;
 
        num_regulators = mc13xxx_get_num_regulators_dt(pdev);
 
@@ -444,31 +444,15 @@ static int mc13783_regulator_probe(struct platform_device *pdev)
                config.driver_data = priv;
                config.of_node = node;
 
-               priv->regulators[i] = regulator_register(desc, &config);
+               priv->regulators[i] = devm_regulator_register(&pdev->dev, desc,
+                                                             &config);
                if (IS_ERR(priv->regulators[i])) {
                        dev_err(&pdev->dev, "failed to register regulator %s\n",
                                mc13783_regulators[i].desc.name);
-                       ret = PTR_ERR(priv->regulators[i]);
-                       goto err;
+                       return PTR_ERR(priv->regulators[i]);
                }
        }
 
-       return 0;
-err:
-       while (--i >= 0)
-               regulator_unregister(priv->regulators[i]);
-
-       return ret;
-}
-
-static int mc13783_regulator_remove(struct platform_device *pdev)
-{
-       struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev);
-       int i;
-
-       for (i = 0; i < priv->num_regulators; i++)
-               regulator_unregister(priv->regulators[i]);
-
        return 0;
 }
 
@@ -477,7 +461,6 @@ static struct platform_driver mc13783_regulator_driver = {
                .name   = "mc13783-regulator",
                .owner  = THIS_MODULE,
        },
-       .remove         = mc13783_regulator_remove,
        .probe          = mc13783_regulator_probe,
 };
 
index 1037e07937cfba7080de781a0db63b42cb6db679..96c9f80d9550b28ceafdab692fe996588c6dd180 100644 (file)
@@ -611,43 +611,27 @@ static int mc13892_regulator_probe(struct platform_device *pdev)
                config.driver_data = priv;
                config.of_node = node;
 
-               priv->regulators[i] = regulator_register(desc, &config);
+               priv->regulators[i] = devm_regulator_register(&pdev->dev, desc,
+                                                             &config);
                if (IS_ERR(priv->regulators[i])) {
                        dev_err(&pdev->dev, "failed to register regulator %s\n",
                                mc13892_regulators[i].desc.name);
-                       ret = PTR_ERR(priv->regulators[i]);
-                       goto err;
+                       return PTR_ERR(priv->regulators[i]);
                }
        }
 
        return 0;
-err:
-       while (--i >= 0)
-               regulator_unregister(priv->regulators[i]);
-       return ret;
 
 err_unlock:
        mc13xxx_unlock(mc13892);
        return ret;
 }
 
-static int mc13892_regulator_remove(struct platform_device *pdev)
-{
-       struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev);
-       int i;
-
-       for (i = 0; i < priv->num_regulators; i++)
-               regulator_unregister(priv->regulators[i]);
-
-       return 0;
-}
-
 static struct platform_driver mc13892_regulator_driver = {
        .driver = {
                .name   = "mc13892-regulator",
                .owner  = THIS_MODULE,
        },
-       .remove = mc13892_regulator_remove,
        .probe  = mc13892_regulator_probe,
 };
 
index 7827384680d64a7f62b5e248d687953e5ca8ae7b..ea4f36f2cbe2f1e5432e594711fdb5d4c2c677c6 100644 (file)
@@ -23,6 +23,8 @@ static void of_get_regulation_constraints(struct device_node *np,
        const __be32 *min_uA, *max_uA, *ramp_delay;
        struct property *prop;
        struct regulation_constraints *constraints = &(*init_data)->constraints;
+       int ret;
+       u32 pval;
 
        constraints->name = of_get_property(np, "regulator-name", NULL);
 
@@ -73,6 +75,10 @@ static void of_get_regulation_constraints(struct device_node *np,
                else
                        constraints->ramp_disable = true;
        }
+
+       ret = of_property_read_u32(np, "regulator-enable-ramp-delay", &pval);
+       if (!ret)
+               constraints->enable_time = pval;
 }
 
 /**
index 7e2b165972e6edd6e3eee6b26478cb263db5d048..9c62b1d34685815c30be33d3157faa0b063d0c4d 100644 (file)
@@ -33,6 +33,7 @@ struct regs_info {
        u8      vsel_addr;
        u8      ctrl_addr;
        u8      tstep_addr;
+       int     sleep_id;
 };
 
 static const struct regs_info palmas_regs_info[] = {
@@ -42,6 +43,7 @@ static const struct regs_info palmas_regs_info[] = {
                .vsel_addr      = PALMAS_SMPS12_VOLTAGE,
                .ctrl_addr      = PALMAS_SMPS12_CTRL,
                .tstep_addr     = PALMAS_SMPS12_TSTEP,
+               .sleep_id       = PALMAS_EXTERNAL_REQSTR_ID_SMPS12,
        },
        {
                .name           = "SMPS123",
@@ -49,12 +51,14 @@ static const struct regs_info palmas_regs_info[] = {
                .vsel_addr      = PALMAS_SMPS12_VOLTAGE,
                .ctrl_addr      = PALMAS_SMPS12_CTRL,
                .tstep_addr     = PALMAS_SMPS12_TSTEP,
+               .sleep_id       = PALMAS_EXTERNAL_REQSTR_ID_SMPS12,
        },
        {
                .name           = "SMPS3",
                .sname          = "smps3-in",
                .vsel_addr      = PALMAS_SMPS3_VOLTAGE,
                .ctrl_addr      = PALMAS_SMPS3_CTRL,
+               .sleep_id       = PALMAS_EXTERNAL_REQSTR_ID_SMPS3,
        },
        {
                .name           = "SMPS45",
@@ -62,6 +66,7 @@ static const struct regs_info palmas_regs_info[] = {
                .vsel_addr      = PALMAS_SMPS45_VOLTAGE,
                .ctrl_addr      = PALMAS_SMPS45_CTRL,
                .tstep_addr     = PALMAS_SMPS45_TSTEP,
+               .sleep_id       = PALMAS_EXTERNAL_REQSTR_ID_SMPS45,
        },
        {
                .name           = "SMPS457",
@@ -69,6 +74,7 @@ static const struct regs_info palmas_regs_info[] = {
                .vsel_addr      = PALMAS_SMPS45_VOLTAGE,
                .ctrl_addr      = PALMAS_SMPS45_CTRL,
                .tstep_addr     = PALMAS_SMPS45_TSTEP,
+               .sleep_id       = PALMAS_EXTERNAL_REQSTR_ID_SMPS45,
        },
        {
                .name           = "SMPS6",
@@ -76,12 +82,14 @@ static const struct regs_info palmas_regs_info[] = {
                .vsel_addr      = PALMAS_SMPS6_VOLTAGE,
                .ctrl_addr      = PALMAS_SMPS6_CTRL,
                .tstep_addr     = PALMAS_SMPS6_TSTEP,
+               .sleep_id       = PALMAS_EXTERNAL_REQSTR_ID_SMPS6,
        },
        {
                .name           = "SMPS7",
                .sname          = "smps7-in",
                .vsel_addr      = PALMAS_SMPS7_VOLTAGE,
                .ctrl_addr      = PALMAS_SMPS7_CTRL,
+               .sleep_id       = PALMAS_EXTERNAL_REQSTR_ID_SMPS7,
        },
        {
                .name           = "SMPS8",
@@ -89,108 +97,128 @@ static const struct regs_info palmas_regs_info[] = {
                .vsel_addr      = PALMAS_SMPS8_VOLTAGE,
                .ctrl_addr      = PALMAS_SMPS8_CTRL,
                .tstep_addr     = PALMAS_SMPS8_TSTEP,
+               .sleep_id       = PALMAS_EXTERNAL_REQSTR_ID_SMPS8,
        },
        {
                .name           = "SMPS9",
                .sname          = "smps9-in",
                .vsel_addr      = PALMAS_SMPS9_VOLTAGE,
                .ctrl_addr      = PALMAS_SMPS9_CTRL,
+               .sleep_id       = PALMAS_EXTERNAL_REQSTR_ID_SMPS9,
        },
        {
                .name           = "SMPS10_OUT2",
                .sname          = "smps10-in",
                .ctrl_addr      = PALMAS_SMPS10_CTRL,
+               .sleep_id       = PALMAS_EXTERNAL_REQSTR_ID_SMPS10,
        },
        {
                .name           = "SMPS10_OUT1",
                .sname          = "smps10-out2",
                .ctrl_addr      = PALMAS_SMPS10_CTRL,
+               .sleep_id       = PALMAS_EXTERNAL_REQSTR_ID_SMPS10,
        },
        {
                .name           = "LDO1",
                .sname          = "ldo1-in",
                .vsel_addr      = PALMAS_LDO1_VOLTAGE,
                .ctrl_addr      = PALMAS_LDO1_CTRL,
+               .sleep_id       = PALMAS_EXTERNAL_REQSTR_ID_LDO1,
        },
        {
                .name           = "LDO2",
                .sname          = "ldo2-in",
                .vsel_addr      = PALMAS_LDO2_VOLTAGE,
                .ctrl_addr      = PALMAS_LDO2_CTRL,
+               .sleep_id       = PALMAS_EXTERNAL_REQSTR_ID_LDO2,
        },
        {
                .name           = "LDO3",
                .sname          = "ldo3-in",
                .vsel_addr      = PALMAS_LDO3_VOLTAGE,
                .ctrl_addr      = PALMAS_LDO3_CTRL,
+               .sleep_id       = PALMAS_EXTERNAL_REQSTR_ID_LDO3,
        },
        {
                .name           = "LDO4",
                .sname          = "ldo4-in",
                .vsel_addr      = PALMAS_LDO4_VOLTAGE,
                .ctrl_addr      = PALMAS_LDO4_CTRL,
+               .sleep_id       = PALMAS_EXTERNAL_REQSTR_ID_LDO4,
        },
        {
                .name           = "LDO5",
                .sname          = "ldo5-in",
                .vsel_addr      = PALMAS_LDO5_VOLTAGE,
                .ctrl_addr      = PALMAS_LDO5_CTRL,
+               .sleep_id       = PALMAS_EXTERNAL_REQSTR_ID_LDO5,
        },
        {
                .name           = "LDO6",
                .sname          = "ldo6-in",
                .vsel_addr      = PALMAS_LDO6_VOLTAGE,
                .ctrl_addr      = PALMAS_LDO6_CTRL,
+               .sleep_id       = PALMAS_EXTERNAL_REQSTR_ID_LDO6,
        },
        {
                .name           = "LDO7",
                .sname          = "ldo7-in",
                .vsel_addr      = PALMAS_LDO7_VOLTAGE,
                .ctrl_addr      = PALMAS_LDO7_CTRL,
+               .sleep_id       = PALMAS_EXTERNAL_REQSTR_ID_LDO7,
        },
        {
                .name           = "LDO8",
                .sname          = "ldo8-in",
                .vsel_addr      = PALMAS_LDO8_VOLTAGE,
                .ctrl_addr      = PALMAS_LDO8_CTRL,
+               .sleep_id       = PALMAS_EXTERNAL_REQSTR_ID_LDO8,
        },
        {
                .name           = "LDO9",
                .sname          = "ldo9-in",
                .vsel_addr      = PALMAS_LDO9_VOLTAGE,
                .ctrl_addr      = PALMAS_LDO9_CTRL,
+               .sleep_id       = PALMAS_EXTERNAL_REQSTR_ID_LDO9,
        },
        {
                .name           = "LDOLN",
                .sname          = "ldoln-in",
                .vsel_addr      = PALMAS_LDOLN_VOLTAGE,
                .ctrl_addr      = PALMAS_LDOLN_CTRL,
+               .sleep_id       = PALMAS_EXTERNAL_REQSTR_ID_LDOLN,
        },
        {
                .name           = "LDOUSB",
                .sname          = "ldousb-in",
                .vsel_addr      = PALMAS_LDOUSB_VOLTAGE,
                .ctrl_addr      = PALMAS_LDOUSB_CTRL,
+               .sleep_id       = PALMAS_EXTERNAL_REQSTR_ID_LDOUSB,
        },
        {
                .name           = "REGEN1",
                .ctrl_addr      = PALMAS_REGEN1_CTRL,
+               .sleep_id       = PALMAS_EXTERNAL_REQSTR_ID_REGEN1,
        },
        {
                .name           = "REGEN2",
                .ctrl_addr      = PALMAS_REGEN2_CTRL,
+               .sleep_id       = PALMAS_EXTERNAL_REQSTR_ID_REGEN2,
        },
        {
                .name           = "REGEN3",
                .ctrl_addr      = PALMAS_REGEN3_CTRL,
+               .sleep_id       = PALMAS_EXTERNAL_REQSTR_ID_REGEN3,
        },
        {
                .name           = "SYSEN1",
                .ctrl_addr      = PALMAS_SYSEN1_CTRL,
+               .sleep_id       = PALMAS_EXTERNAL_REQSTR_ID_SYSEN1,
        },
        {
                .name           = "SYSEN2",
                .ctrl_addr      = PALMAS_SYSEN2_CTRL,
+               .sleep_id       = PALMAS_EXTERNAL_REQSTR_ID_SYSEN2,
        },
 };
 
@@ -478,6 +506,17 @@ static struct regulator_ops palmas_ops_smps = {
        .set_ramp_delay         = palmas_smps_set_ramp_delay,
 };
 
+static struct regulator_ops palmas_ops_ext_control_smps = {
+       .set_mode               = palmas_set_mode_smps,
+       .get_mode               = palmas_get_mode_smps,
+       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
+       .list_voltage           = palmas_list_voltage_smps,
+       .map_voltage            = palmas_map_voltage_smps,
+       .set_voltage_time_sel   = palma_smps_set_voltage_smps_time_sel,
+       .set_ramp_delay         = palmas_smps_set_ramp_delay,
+};
+
 static struct regulator_ops palmas_ops_smps10 = {
        .is_enabled             = regulator_is_enabled_regmap,
        .enable                 = regulator_enable_regmap,
@@ -513,12 +552,37 @@ static struct regulator_ops palmas_ops_ldo = {
        .map_voltage            = regulator_map_voltage_linear,
 };
 
+static struct regulator_ops palmas_ops_ext_control_ldo = {
+       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
+       .list_voltage           = regulator_list_voltage_linear,
+       .map_voltage            = regulator_map_voltage_linear,
+};
+
 static struct regulator_ops palmas_ops_extreg = {
        .is_enabled             = regulator_is_enabled_regmap,
        .enable                 = regulator_enable_regmap,
        .disable                = regulator_disable_regmap,
 };
 
+static struct regulator_ops palmas_ops_ext_control_extreg = {
+};
+
+static int palmas_regulator_config_external(struct palmas *palmas, int id,
+               struct palmas_reg_init *reg_init)
+{
+       int sleep_id = palmas_regs_info[id].sleep_id;
+       int ret;
+
+       ret = palmas_ext_control_req_config(palmas, sleep_id,
+                                       reg_init->roof_floor, true);
+       if (ret < 0)
+               dev_err(palmas->dev,
+                       "Ext control config for regulator %d failed %d\n",
+                       id, ret);
+       return ret;
+}
+
 /*
  * setup the hardware based sleep configuration of the SMPS/LDO regulators
  * from the platform data. This is different to the software based control
@@ -577,7 +641,22 @@ static int palmas_smps_init(struct palmas *palmas, int id,
                        return ret;
        }
 
+       if (reg_init->roof_floor && (id != PALMAS_REG_SMPS10_OUT1) &&
+                       (id != PALMAS_REG_SMPS10_OUT2)) {
+               /* Enable externally controlled regulator */
+               addr = palmas_regs_info[id].ctrl_addr;
+               ret = palmas_smps_read(palmas, addr, &reg);
+               if (ret < 0)
+                       return ret;
 
+               if (!(reg & PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK)) {
+                       reg |= SMPS_CTRL_MODE_ON;
+                       ret = palmas_smps_write(palmas, addr, reg);
+                       if (ret < 0)
+                               return ret;
+               }
+               return palmas_regulator_config_external(palmas, id, reg_init);
+       }
        return 0;
 }
 
@@ -608,6 +687,20 @@ static int palmas_ldo_init(struct palmas *palmas, int id,
        if (ret)
                return ret;
 
+       if (reg_init->roof_floor) {
+               /* Enable externally controlled regulator */
+               addr = palmas_regs_info[id].ctrl_addr;
+               ret = palmas_update_bits(palmas, PALMAS_LDO_BASE,
+                               addr, PALMAS_LDO1_CTRL_MODE_ACTIVE,
+                               PALMAS_LDO1_CTRL_MODE_ACTIVE);
+               if (ret < 0) {
+                       dev_err(palmas->dev,
+                               "LDO Register 0x%02x update failed %d\n",
+                               addr, ret);
+                       return ret;
+               }
+               return palmas_regulator_config_external(palmas, id, reg_init);
+       }
        return 0;
 }
 
@@ -630,6 +723,21 @@ static int palmas_extreg_init(struct palmas *palmas, int id,
                        addr, ret);
                return ret;
        }
+
+       if (reg_init->roof_floor) {
+               /* Enable externally controlled regulator */
+               addr = palmas_regs_info[id].ctrl_addr;
+               ret = palmas_update_bits(palmas, PALMAS_RESOURCE_BASE,
+                               addr, PALMAS_REGEN1_CTRL_MODE_ACTIVE,
+                               PALMAS_REGEN1_CTRL_MODE_ACTIVE);
+               if (ret < 0) {
+                       dev_err(palmas->dev,
+                               "Resource Register 0x%02x update failed %d\n",
+                               addr, ret);
+                       return ret;
+               }
+               return palmas_regulator_config_external(palmas, id, reg_init);
+       }
        return 0;
 }
 
@@ -712,7 +820,7 @@ static void palmas_dt_to_pdata(struct device *dev,
        int idx, ret;
 
        node = of_node_get(node);
-       regulators = of_find_node_by_name(node, "regulators");
+       regulators = of_get_child_by_name(node, "regulators");
        if (!regulators) {
                dev_info(dev, "regulator node not found\n");
                return;
@@ -740,9 +848,35 @@ static void palmas_dt_to_pdata(struct device *dev,
                        of_property_read_bool(palmas_matches[idx].of_node,
                                             "ti,warm-reset");
 
-               pdata->reg_init[idx]->roof_floor =
-                       of_property_read_bool(palmas_matches[idx].of_node,
-                                             "ti,roof-floor");
+               ret = of_property_read_u32(palmas_matches[idx].of_node,
+                                             "ti,roof-floor", &prop);
+               /* EINVAL: Property not found */
+               if (ret != -EINVAL) {
+                       int econtrol;
+
+                       /* use default value, when no value is specified */
+                       econtrol = PALMAS_EXT_CONTROL_NSLEEP;
+                       if (!ret) {
+                               switch (prop) {
+                               case 1:
+                                       econtrol = PALMAS_EXT_CONTROL_ENABLE1;
+                                       break;
+                               case 2:
+                                       econtrol = PALMAS_EXT_CONTROL_ENABLE2;
+                                       break;
+                               case 3:
+                                       econtrol = PALMAS_EXT_CONTROL_NSLEEP;
+                                       break;
+                               default:
+                                       WARN_ON(1);
+                                       dev_warn(dev,
+                                       "%s: Invalid roof-floor option: %u\n",
+                                            palmas_matches[idx].name, prop);
+                                       break;
+                               }
+                       }
+                       pdata->reg_init[idx]->roof_floor = econtrol;
+               }
 
                ret = of_property_read_u32(palmas_matches[idx].of_node,
                                "ti,mode-sleep", &prop);
@@ -856,7 +990,7 @@ static int palmas_regulators_probe(struct platform_device *pdev)
                        if (ret < 0) {
                                dev_err(&pdev->dev,
                                        "reading TSTEP reg failed: %d\n", ret);
-                               goto err_unregister_regulator;
+                               return ret;
                        }
                        pmic->desc[id].ramp_delay =
                                        palmas_smps_ramp_delay[reg & 0x3];
@@ -868,7 +1002,9 @@ static int palmas_regulators_probe(struct platform_device *pdev)
                        reg_init = pdata->reg_init[id];
                        ret = palmas_smps_init(palmas, id, reg_init);
                        if (ret)
-                               goto err_unregister_regulator;
+                               return ret;
+               } else {
+                       reg_init = NULL;
                }
 
                /* Register the regulators */
@@ -909,11 +1045,15 @@ static int palmas_regulators_probe(struct platform_device *pdev)
 
                        ret = palmas_smps_read(pmic->palmas, addr, &reg);
                        if (ret)
-                               goto err_unregister_regulator;
+                               return ret;
                        if (reg & PALMAS_SMPS12_VOLTAGE_RANGE)
                                pmic->range[id] = 1;
 
-                       pmic->desc[id].ops = &palmas_ops_smps;
+                       if (reg_init && reg_init->roof_floor)
+                               pmic->desc[id].ops =
+                                               &palmas_ops_ext_control_smps;
+                       else
+                               pmic->desc[id].ops = &palmas_ops_smps;
                        pmic->desc[id].n_voltages = PALMAS_SMPS_NUM_VOLTAGES;
                        pmic->desc[id].vsel_reg =
                                        PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE,
@@ -925,7 +1065,7 @@ static int palmas_regulators_probe(struct platform_device *pdev)
                        addr = palmas_regs_info[id].ctrl_addr;
                        ret = palmas_smps_read(pmic->palmas, addr, &reg);
                        if (ret)
-                               goto err_unregister_regulator;
+                               return ret;
                        pmic->current_reg_mode[id] = reg &
                                        PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK;
                }
@@ -941,13 +1081,13 @@ static int palmas_regulators_probe(struct platform_device *pdev)
                pmic->desc[id].supply_name = palmas_regs_info[id].sname;
                config.of_node = palmas_matches[id].of_node;
 
-               rdev = regulator_register(&pmic->desc[id], &config);
+               rdev = devm_regulator_register(&pdev->dev, &pmic->desc[id],
+                                              &config);
                if (IS_ERR(rdev)) {
                        dev_err(&pdev->dev,
                                "failed to register %s regulator\n",
                                pdev->name);
-                       ret = PTR_ERR(rdev);
-                       goto err_unregister_regulator;
+                       return PTR_ERR(rdev);
                }
 
                /* Save regulator for cleanup */
@@ -956,6 +1096,10 @@ static int palmas_regulators_probe(struct platform_device *pdev)
 
        /* Start this loop from the id left from previous loop */
        for (; id < PALMAS_NUM_REGS; id++) {
+               if (pdata && pdata->reg_init[id])
+                       reg_init = pdata->reg_init[id];
+               else
+                       reg_init = NULL;
 
                /* Miss out regulators which are not available due
                 * to alternate functions.
@@ -969,7 +1113,11 @@ static int palmas_regulators_probe(struct platform_device *pdev)
 
                if (id < PALMAS_REG_REGEN1) {
                        pmic->desc[id].n_voltages = PALMAS_LDO_NUM_VOLTAGES;
-                       pmic->desc[id].ops = &palmas_ops_ldo;
+                       if (reg_init && reg_init->roof_floor)
+                               pmic->desc[id].ops =
+                                       &palmas_ops_ext_control_ldo;
+                       else
+                               pmic->desc[id].ops = &palmas_ops_ldo;
                        pmic->desc[id].min_uV = 900000;
                        pmic->desc[id].uV_step = 50000;
                        pmic->desc[id].linear_min_sel = 1;
@@ -999,7 +1147,11 @@ static int palmas_regulators_probe(struct platform_device *pdev)
                                pmic->desc[id].enable_time = 2000;
                } else {
                        pmic->desc[id].n_voltages = 1;
-                       pmic->desc[id].ops = &palmas_ops_extreg;
+                       if (reg_init && reg_init->roof_floor)
+                               pmic->desc[id].ops =
+                                       &palmas_ops_ext_control_extreg;
+                       else
+                               pmic->desc[id].ops = &palmas_ops_extreg;
                        pmic->desc[id].enable_reg =
                                        PALMAS_BASE_TO_REG(PALMAS_RESOURCE_BASE,
                                                palmas_regs_info[id].ctrl_addr);
@@ -1015,13 +1167,13 @@ static int palmas_regulators_probe(struct platform_device *pdev)
                pmic->desc[id].supply_name = palmas_regs_info[id].sname;
                config.of_node = palmas_matches[id].of_node;
 
-               rdev = regulator_register(&pmic->desc[id], &config);
+               rdev = devm_regulator_register(&pdev->dev, &pmic->desc[id],
+                                              &config);
                if (IS_ERR(rdev)) {
                        dev_err(&pdev->dev,
                                "failed to register %s regulator\n",
                                pdev->name);
-                       ret = PTR_ERR(rdev);
-                       goto err_unregister_regulator;
+                       return PTR_ERR(rdev);
                }
 
                /* Save regulator for cleanup */
@@ -1037,31 +1189,14 @@ static int palmas_regulators_probe(struct platform_device *pdev)
                                else
                                        ret = palmas_extreg_init(palmas,
                                                        id, reg_init);
-                               if (ret) {
-                                       regulator_unregister(pmic->rdev[id]);
-                                       goto err_unregister_regulator;
-                               }
+                               if (ret)
+                                       return ret;
                        }
                }
        }
 
 
        return 0;
-
-err_unregister_regulator:
-       while (--id >= 0)
-               regulator_unregister(pmic->rdev[id]);
-       return ret;
-}
-
-static int palmas_regulators_remove(struct platform_device *pdev)
-{
-       struct palmas_pmic *pmic = platform_get_drvdata(pdev);
-       int id;
-
-       for (id = 0; id < PALMAS_NUM_REGS; id++)
-               regulator_unregister(pmic->rdev[id]);
-       return 0;
 }
 
 static struct of_device_id of_palmas_match_tbl[] = {
@@ -1083,7 +1218,6 @@ static struct platform_driver palmas_driver = {
                .owner = THIS_MODULE,
        },
        .probe = palmas_regulators_probe,
-       .remove = palmas_regulators_remove,
 };
 
 static int __init palmas_init(void)
index b49eaeedea849f5c380059417050bd9d75f2901e..3727b7d0e9ac3c1f633f801f715fdb1520d01fe8 100644 (file)
@@ -246,7 +246,8 @@ static int pcap_regulator_probe(struct platform_device *pdev)
        config.init_data = dev_get_platdata(&pdev->dev);
        config.driver_data = pcap;
 
-       rdev = regulator_register(&pcap_regulators[pdev->id], &config);
+       rdev = devm_regulator_register(&pdev->dev, &pcap_regulators[pdev->id],
+                                      &config);
        if (IS_ERR(rdev))
                return PTR_ERR(rdev);
 
@@ -255,22 +256,12 @@ static int pcap_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int pcap_regulator_remove(struct platform_device *pdev)
-{
-       struct regulator_dev *rdev = platform_get_drvdata(pdev);
-
-       regulator_unregister(rdev);
-
-       return 0;
-}
-
 static struct platform_driver pcap_regulator_driver = {
        .driver = {
                .name   = "pcap-regulator",
                .owner  = THIS_MODULE,
        },
        .probe  = pcap_regulator_probe,
-       .remove = pcap_regulator_remove,
 };
 
 static int __init pcap_regulator_init(void)
index 0f3576d48abf9733cb87a27231f471ca263cade9..d7da1c15a6da447d699e080a4bfda259f734c5f0 100644 (file)
@@ -90,7 +90,8 @@ static int pcf50633_regulator_probe(struct platform_device *pdev)
        config.driver_data = pcf;
        config.regmap = pcf->regmap;
 
-       rdev = regulator_register(&regulators[pdev->id], &config);
+       rdev = devm_regulator_register(&pdev->dev, &regulators[pdev->id],
+                                      &config);
        if (IS_ERR(rdev))
                return PTR_ERR(rdev);
 
@@ -102,21 +103,11 @@ static int pcf50633_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int pcf50633_regulator_remove(struct platform_device *pdev)
-{
-       struct regulator_dev *rdev = platform_get_drvdata(pdev);
-
-       regulator_unregister(rdev);
-
-       return 0;
-}
-
 static struct platform_driver pcf50633_regulator_driver = {
        .driver = {
                .name = "pcf50633-regltr",
        },
        .probe = pcf50633_regulator_probe,
-       .remove = pcf50633_regulator_remove,
 };
 
 static int __init pcf50633_regulator_init(void)
index 5885b450459697bce78d8fd27b00c3e9468c79de..b58affb33143903d9044a8de2a614a8f20ee0e5f 100644 (file)
@@ -173,33 +173,16 @@ skip_ext_pwr_config:
                config.driver_data = reg;
                config.regmap = rc5t583->regmap;
 
-               rdev = regulator_register(&ri->desc, &config);
+               rdev = devm_regulator_register(&pdev->dev, &ri->desc, &config);
                if (IS_ERR(rdev)) {
                        dev_err(&pdev->dev, "Failed to register regulator %s\n",
                                                ri->desc.name);
-                       ret = PTR_ERR(rdev);
-                       goto clean_exit;
+                       return PTR_ERR(rdev);
                }
                reg->rdev = rdev;
        }
        platform_set_drvdata(pdev, regs);
        return 0;
-
-clean_exit:
-       while (--id >= 0)
-               regulator_unregister(regs[id].rdev);
-
-       return ret;
-}
-
-static int rc5t583_regulator_remove(struct platform_device *pdev)
-{
-       struct rc5t583_regulator *regs = platform_get_drvdata(pdev);
-       int id;
-
-       for (id = 0; id < RC5T583_REGULATOR_MAX; ++id)
-               regulator_unregister(regs[id].rdev);
-       return 0;
 }
 
 static struct platform_driver rc5t583_regulator_driver = {
@@ -208,7 +191,6 @@ static struct platform_driver rc5t583_regulator_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = rc5t583_regulator_probe,
-       .remove         = rc5t583_regulator_remove,
 };
 
 static int __init rc5t583_regulator_init(void)
index 5eba2ff8c0e86eff58bf5c48e77e4ad352f8b00a..333677d68d0ee31f784e76906bc930b592fc7257 100644 (file)
@@ -448,32 +448,16 @@ common_reg:
                        config.of_node = rdata[i].of_node;
                }
 
-               s2mps11->rdev[i] = regulator_register(&regulators[i], &config);
+               s2mps11->rdev[i] = devm_regulator_register(&pdev->dev,
+                                               &regulators[i], &config);
                if (IS_ERR(s2mps11->rdev[i])) {
                        ret = PTR_ERR(s2mps11->rdev[i]);
                        dev_err(&pdev->dev, "regulator init failed for %d\n",
                                i);
-                       s2mps11->rdev[i] = NULL;
-                       goto err;
+                       return ret;
                }
        }
 
-       return 0;
-err:
-       for (i = 0; i < S2MPS11_REGULATOR_MAX; i++)
-               regulator_unregister(s2mps11->rdev[i]);
-
-       return ret;
-}
-
-static int s2mps11_pmic_remove(struct platform_device *pdev)
-{
-       struct s2mps11_info *s2mps11 = platform_get_drvdata(pdev);
-       int i;
-
-       for (i = 0; i < S2MPS11_REGULATOR_MAX; i++)
-               regulator_unregister(s2mps11->rdev[i]);
-
        return 0;
 }
 
@@ -489,7 +473,6 @@ static struct platform_driver s2mps11_pmic_driver = {
                .owner = THIS_MODULE,
        },
        .probe = s2mps11_pmic_probe,
-       .remove = s2mps11_pmic_remove,
        .id_table = s2mps11_pmic_id,
 };
 
index c24448bc43cfb71658d88afea9779e2b47471495..2297fdf9ba7e6353fac764efe32c56c48c68ea8a 100644 (file)
@@ -910,33 +910,16 @@ static int s5m8767_pmic_probe(struct platform_device *pdev)
                config.regmap = iodev->regmap;
                config.of_node = pdata->regulators[i].reg_node;
 
-               rdev[i] = regulator_register(&regulators[id], &config);
+               rdev[i] = devm_regulator_register(&pdev->dev, &regulators[id],
+                                                 &config);
                if (IS_ERR(rdev[i])) {
                        ret = PTR_ERR(rdev[i]);
                        dev_err(s5m8767->dev, "regulator init failed for %d\n",
                                        id);
-                       rdev[i] = NULL;
-                       goto err;
+                       return ret;
                }
        }
 
-       return 0;
-err:
-       for (i = 0; i < s5m8767->num_regulators; i++)
-               regulator_unregister(rdev[i]);
-
-       return ret;
-}
-
-static int s5m8767_pmic_remove(struct platform_device *pdev)
-{
-       struct s5m8767_info *s5m8767 = platform_get_drvdata(pdev);
-       struct regulator_dev **rdev = s5m8767->rdev;
-       int i;
-
-       for (i = 0; i < s5m8767->num_regulators; i++)
-               regulator_unregister(rdev[i]);
-
        return 0;
 }
 
@@ -952,7 +935,6 @@ static struct platform_driver s5m8767_pmic_driver = {
                .owner = THIS_MODULE,
        },
        .probe = s5m8767_pmic_probe,
-       .remove = s5m8767_pmic_remove,
        .id_table = s5m8767_pmic_id,
 };
 
diff --git a/drivers/regulator/stw481x-vmmc.c b/drivers/regulator/stw481x-vmmc.c
new file mode 100644 (file)
index 0000000..f78857b
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Regulator driver for STw4810/STw4811 VMMC regulator.
+ *
+ * Copyright (C) 2013 ST-Ericsson SA
+ * Written on behalf of Linaro for ST-Ericsson
+ *
+ * Author: Linus Walleij <linus.walleij@linaro.org>
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/mfd/stw481x.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/of_regulator.h>
+
+static const unsigned int stw481x_vmmc_voltages[] = {
+       1800000,
+       1800000,
+       2850000,
+       3000000,
+       1850000,
+       2600000,
+       2700000,
+       3300000,
+};
+
+static struct regulator_ops stw481x_vmmc_ops = {
+       .list_voltage = regulator_list_voltage_table,
+       .enable      = regulator_enable_regmap,
+       .disable     = regulator_disable_regmap,
+       .is_enabled  = regulator_is_enabled_regmap,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+};
+
+static struct regulator_desc vmmc_regulator = {
+       .name = "VMMC",
+       .id   = 0,
+       .ops  = &stw481x_vmmc_ops,
+       .type = REGULATOR_VOLTAGE,
+       .owner = THIS_MODULE,
+       .n_voltages = ARRAY_SIZE(stw481x_vmmc_voltages),
+       .volt_table = stw481x_vmmc_voltages,
+       .enable_time = 200, /* FIXME: look this up */
+       .enable_reg = STW_CONF1,
+       .enable_mask = STW_CONF1_PDN_VMMC,
+       .vsel_reg = STW_CONF1,
+       .vsel_mask = STW_CONF1_VMMC_MASK,
+};
+
+static int stw481x_vmmc_regulator_probe(struct platform_device *pdev)
+{
+       struct stw481x *stw481x = dev_get_platdata(&pdev->dev);
+       struct regulator_config config = { };
+       int ret;
+
+       /* First disable the external VMMC if it's active */
+       ret = regmap_update_bits(stw481x->map, STW_CONF2,
+                                STW_CONF2_VMMC_EXT, 0);
+       if (ret) {
+               dev_err(&pdev->dev, "could not disable external VMMC\n");
+               return ret;
+       }
+
+       /* Register VMMC regulator */
+       config.dev = &pdev->dev;
+       config.driver_data = stw481x;
+       config.regmap = stw481x->map;
+       config.of_node = pdev->dev.of_node;
+       config.init_data = of_get_regulator_init_data(&pdev->dev,
+                                                     pdev->dev.of_node);
+
+       stw481x->vmmc_regulator = regulator_register(&vmmc_regulator, &config);
+       if (IS_ERR(stw481x->vmmc_regulator)) {
+               dev_err(&pdev->dev,
+                       "error initializing STw481x VMMC regulator\n");
+               return PTR_ERR(stw481x->vmmc_regulator);
+       }
+
+       dev_info(&pdev->dev, "initialized STw481x VMMC regulator\n");
+       return 0;
+}
+
+static int stw481x_vmmc_regulator_remove(struct platform_device *pdev)
+{
+       struct stw481x *stw481x = dev_get_platdata(&pdev->dev);
+
+       regulator_unregister(stw481x->vmmc_regulator);
+       return 0;
+}
+
+static const struct of_device_id stw481x_vmmc_match[] = {
+       { .compatible = "st,stw481x-vmmc", },
+       {},
+};
+
+static struct platform_driver stw481x_vmmc_regulator_driver = {
+       .driver = {
+               .name  = "stw481x-vmmc-regulator",
+               .owner = THIS_MODULE,
+               .of_match_table = stw481x_vmmc_match,
+       },
+       .probe = stw481x_vmmc_regulator_probe,
+       .remove = stw481x_vmmc_regulator_remove,
+};
+
+module_platform_driver(stw481x_vmmc_regulator_driver);
index 20c271d49dcbbd358e03d5140d05e9da4ca54952..b187b6bba7ad485a9a8d97ba248b0a70de89c5c8 100644 (file)
@@ -615,7 +615,7 @@ static int ti_abb_init_table(struct device *dev, struct ti_abb *abb,
                                        pname, *volt_table, vset_mask);
                        continue;
                }
-               info->vset = efuse_val & vset_mask >> __ffs(vset_mask);
+               info->vset = (efuse_val & vset_mask) >> __ffs(vset_mask);
                dev_dbg(dev, "[%d]v=%d vset=%x\n", i, *volt_table, info->vset);
 check_abb:
                switch (info->opp_sel) {
@@ -708,39 +708,31 @@ static int ti_abb_probe(struct platform_device *pdev)
        match = of_match_device(ti_abb_of_match, dev);
        if (!match) {
                /* We do not expect this to happen */
-               ret = -ENODEV;
                dev_err(dev, "%s: Unable to match device\n", __func__);
-               goto err;
+               return -ENODEV;
        }
        if (!match->data) {
-               ret = -EINVAL;
                dev_err(dev, "%s: Bad data in match\n", __func__);
-               goto err;
+               return -EINVAL;
        }
 
        abb = devm_kzalloc(dev, sizeof(struct ti_abb), GFP_KERNEL);
-       if (!abb) {
-               dev_err(dev, "%s: Unable to allocate ABB struct\n", __func__);
-               ret = -ENOMEM;
-               goto err;
-       }
+       if (!abb)
+               return -ENOMEM;
        abb->regs = match->data;
 
        /* Map ABB resources */
        pname = "base-address";
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, pname);
        abb->base = devm_ioremap_resource(dev, res);
-       if (IS_ERR(abb->base)) {
-               ret = PTR_ERR(abb->base);
-               goto err;
-       }
+       if (IS_ERR(abb->base))
+               return PTR_ERR(abb->base);
 
        pname = "int-address";
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, pname);
        if (!res) {
                dev_err(dev, "Missing '%s' IO resource\n", pname);
-               ret = -ENODEV;
-               goto err;
+               return -ENODEV;
        }
        /*
         * We may have shared interrupt register offsets which are
@@ -750,8 +742,7 @@ static int ti_abb_probe(struct platform_device *pdev)
                                             resource_size(res));
        if (!abb->int_base) {
                dev_err(dev, "Unable to map '%s'\n", pname);
-               ret = -ENOMEM;
-               goto err;
+               return -ENOMEM;
        }
 
        /* Map Optional resources */
@@ -771,17 +762,19 @@ static int ti_abb_probe(struct platform_device *pdev)
                                               resource_size(res));
        if (!abb->efuse_base) {
                dev_err(dev, "Unable to map '%s'\n", pname);
-               ret = -ENOMEM;
-               goto err;
+               return -ENOMEM;
        }
 
        pname = "ldo-address";
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, pname);
-       abb->ldo_base = devm_ioremap_resource(dev, res);
-       if (IS_ERR(abb->ldo_base)) {
-               ret = PTR_ERR(abb->ldo_base);
-               goto err;
+       if (!res) {
+               dev_dbg(dev, "Missing '%s' IO resource\n", pname);
+               ret = -ENODEV;
+               goto skip_opt;
        }
+       abb->ldo_base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(abb->ldo_base))
+               return PTR_ERR(abb->ldo_base);
 
        /* IF ldo_base is set, the following are mandatory */
        pname = "ti,ldovbb-override-mask";
@@ -790,12 +783,11 @@ static int ti_abb_probe(struct platform_device *pdev)
                                 &abb->ldovbb_override_mask);
        if (ret) {
                dev_err(dev, "Missing '%s' (%d)\n", pname, ret);
-               goto err;
+               return ret;
        }
        if (!abb->ldovbb_override_mask) {
                dev_err(dev, "Invalid property:'%s' set as 0!\n", pname);
-               ret = -EINVAL;
-               goto err;
+               return -EINVAL;
        }
 
        pname = "ti,ldovbb-vset-mask";
@@ -804,12 +796,11 @@ static int ti_abb_probe(struct platform_device *pdev)
                                 &abb->ldovbb_vset_mask);
        if (ret) {
                dev_err(dev, "Missing '%s' (%d)\n", pname, ret);
-               goto err;
+               return ret;
        }
        if (!abb->ldovbb_vset_mask) {
                dev_err(dev, "Invalid property:'%s' set as 0!\n", pname);
-               ret = -EINVAL;
-               goto err;
+               return -EINVAL;
        }
 
 skip_opt:
@@ -819,31 +810,29 @@ skip_opt:
                                 &abb->txdone_mask);
        if (ret) {
                dev_err(dev, "Missing '%s' (%d)\n", pname, ret);
-               goto err;
+               return ret;
        }
        if (!abb->txdone_mask) {
                dev_err(dev, "Invalid property:'%s' set as 0!\n", pname);
-               ret = -EINVAL;
-               goto err;
+               return -EINVAL;
        }
 
        initdata = of_get_regulator_init_data(dev, pdev->dev.of_node);
        if (!initdata) {
-               ret = -ENOMEM;
                dev_err(dev, "%s: Unable to alloc regulator init data\n",
                        __func__);
-               goto err;
+               return -ENOMEM;
        }
 
        /* init ABB opp_sel table */
        ret = ti_abb_init_table(dev, abb, initdata);
        if (ret)
-               goto err;
+               return ret;
 
        /* init ABB timing */
        ret = ti_abb_init_timings(dev, abb);
        if (ret)
-               goto err;
+               return ret;
 
        desc = &abb->rdesc;
        desc->name = dev_name(dev);
@@ -861,12 +850,12 @@ skip_opt:
        config.driver_data = abb;
        config.of_node = pdev->dev.of_node;
 
-       rdev = regulator_register(desc, &config);
+       rdev = devm_regulator_register(dev, desc, &config);
        if (IS_ERR(rdev)) {
                ret = PTR_ERR(rdev);
                dev_err(dev, "%s: failed to register regulator(%d)\n",
                        __func__, ret);
-               goto err;
+               return ret;
        }
        platform_set_drvdata(pdev, rdev);
 
@@ -874,31 +863,12 @@ skip_opt:
        ti_abb_rmw(abb->regs->sr2_en_mask, 1, abb->regs->setup_reg, abb->base);
 
        return 0;
-
-err:
-       dev_err(dev, "%s: Failed to initialize(%d)\n", __func__, ret);
-       return ret;
-}
-
-/**
- * ti_abb_remove() - cleanups
- * @pdev: ABB platform device
- *
- * Return: 0
- */
-static int ti_abb_remove(struct platform_device *pdev)
-{
-       struct regulator_dev *rdev = platform_get_drvdata(pdev);
-
-       regulator_unregister(rdev);
-       return 0;
 }
 
 MODULE_ALIAS("platform:ti_abb");
 
 static struct platform_driver ti_abb_driver = {
        .probe = ti_abb_probe,
-       .remove = ti_abb_remove,
        .driver = {
                   .name = "ti_abb",
                   .owner = THIS_MODULE,
index 9392a7ca3d2dc6df9152cb1aeb13c776b856e253..b0a3f0917a27ea841f3fffefdda7b67b163e8168 100644 (file)
@@ -343,7 +343,7 @@ static int tps51632_probe(struct i2c_client *client,
        config.regmap = tps->regmap;
        config.of_node = client->dev.of_node;
 
-       rdev = regulator_register(&tps->desc, &config);
+       rdev = devm_regulator_register(&client->dev, &tps->desc, &config);
        if (IS_ERR(rdev)) {
                dev_err(tps->dev, "regulator register failed\n");
                return PTR_ERR(rdev);
@@ -353,14 +353,6 @@ static int tps51632_probe(struct i2c_client *client,
        return 0;
 }
 
-static int tps51632_remove(struct i2c_client *client)
-{
-       struct tps51632_chip *tps = i2c_get_clientdata(client);
-
-       regulator_unregister(tps->rdev);
-       return 0;
-}
-
 static const struct i2c_device_id tps51632_id[] = {
        {.name = "tps51632",},
        {},
@@ -375,7 +367,6 @@ static struct i2c_driver tps51632_i2c_driver = {
                .of_match_table = of_match_ptr(tps51632_of_match),
        },
        .probe = tps51632_probe,
-       .remove = tps51632_remove,
        .id_table = tps51632_id,
 };
 
index ec9453ffb77fd561ec1c2d6c3591b7302bc16b5f..c1e33a3d397b6a62b88fc14e8e2fc0c1ae6a8ec2 100644 (file)
@@ -137,7 +137,7 @@ static int tps6105x_regulator_probe(struct platform_device *pdev)
        /* This instance is not set for regulator mode so bail out */
        if (pdata->mode != TPS6105X_MODE_VOLTAGE) {
                dev_info(&pdev->dev,
-                        "chip not in voltage mode mode, exit probe \n");
+                       "chip not in voltage mode mode, exit probe\n");
                return 0;
        }
 
@@ -146,8 +146,9 @@ static int tps6105x_regulator_probe(struct platform_device *pdev)
        config.driver_data = tps6105x;
 
        /* Register regulator with framework */
-       tps6105x->regulator = regulator_register(&tps6105x_regulator_desc,
-                                                &config);
+       tps6105x->regulator = devm_regulator_register(&pdev->dev,
+                                                     &tps6105x_regulator_desc,
+                                                     &config);
        if (IS_ERR(tps6105x->regulator)) {
                ret = PTR_ERR(tps6105x->regulator);
                dev_err(&tps6105x->client->dev,
@@ -159,20 +160,12 @@ static int tps6105x_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int tps6105x_regulator_remove(struct platform_device *pdev)
-{
-       struct tps6105x *tps6105x = dev_get_platdata(&pdev->dev);
-       regulator_unregister(tps6105x->regulator);
-       return 0;
-}
-
 static struct platform_driver tps6105x_regulator_driver = {
        .driver = {
                .name  = "tps6105x-regulator",
                .owner = THIS_MODULE,
        },
        .probe = tps6105x_regulator_probe,
-       .remove = tps6105x_regulator_remove,
 };
 
 static __init int tps6105x_regulator_init(void)
index 0b7ebb1ebf859bb5d409c19114b4a89f40a094b1..c2c0185a2dcd07b5521924ff1fee3eae344d75a1 100644 (file)
@@ -476,7 +476,7 @@ static int tps62360_probe(struct i2c_client *client,
        config.of_node = client->dev.of_node;
 
        /* Register the regulators */
-       rdev = regulator_register(&tps->desc, &config);
+       rdev = devm_regulator_register(&client->dev, &tps->desc, &config);
        if (IS_ERR(rdev)) {
                dev_err(tps->dev,
                        "%s(): regulator register failed with err %s\n",
@@ -488,20 +488,6 @@ static int tps62360_probe(struct i2c_client *client,
        return 0;
 }
 
-/**
- * tps62360_remove - tps62360 driver i2c remove handler
- * @client: i2c driver client device structure
- *
- * Unregister TPS driver as an i2c client device driver
- */
-static int tps62360_remove(struct i2c_client *client)
-{
-       struct tps62360_chip *tps = i2c_get_clientdata(client);
-
-       regulator_unregister(tps->rdev);
-       return 0;
-}
-
 static void tps62360_shutdown(struct i2c_client *client)
 {
        struct tps62360_chip *tps = i2c_get_clientdata(client);
@@ -535,7 +521,6 @@ static struct i2c_driver tps62360_i2c_driver = {
                .of_match_table = of_match_ptr(tps62360_of_match),
        },
        .probe = tps62360_probe,
-       .remove = tps62360_remove,
        .shutdown = tps62360_shutdown,
        .id_table = tps62360_id,
 };
index f6e398240686893dd833f8388596cd2870dfe2a9..3ef67a86115c9c09e0196915c17f745d0099bb31 100644 (file)
@@ -277,12 +277,12 @@ static int tps_65023_probe(struct i2c_client *client,
                config.regmap = tps->regmap;
 
                /* Register the regulators */
-               rdev = regulator_register(&tps->desc[i], &config);
+               rdev = devm_regulator_register(&client->dev, &tps->desc[i],
+                                              &config);
                if (IS_ERR(rdev)) {
                        dev_err(&client->dev, "failed to register %s\n",
                                id->name);
-                       error = PTR_ERR(rdev);
-                       goto fail;
+                       return PTR_ERR(rdev);
                }
 
                /* Save regulator for cleanup */
@@ -297,21 +297,6 @@ static int tps_65023_probe(struct i2c_client *client,
                                        TPS65023_REG_CTRL2_CORE_ADJ);
 
        return 0;
-
- fail:
-       while (--i >= 0)
-               regulator_unregister(tps->rdev[i]);
-       return error;
-}
-
-static int tps_65023_remove(struct i2c_client *client)
-{
-       struct tps_pmic *tps = i2c_get_clientdata(client);
-       int i;
-
-       for (i = 0; i < TPS65023_NUM_REGULATOR; i++)
-               regulator_unregister(tps->rdev[i]);
-       return 0;
 }
 
 static const struct tps_info tps65020_regs[] = {
@@ -431,7 +416,6 @@ static struct i2c_driver tps_65023_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe = tps_65023_probe,
-       .remove = tps_65023_remove,
        .id_table = tps_65023_id,
 };
 
index 4117ff52dba185909cc3db4e3df9329d4ecadaa8..162a0fae20b317bd0b4899e07520a45f496e43c6 100644 (file)
@@ -508,13 +508,13 @@ static int tps6507x_pmic_probe(struct platform_device *pdev)
                        config.of_node = tps6507x_reg_matches[i].of_node;
                }
 
-               rdev = regulator_register(&tps->desc[i], &config);
+               rdev = devm_regulator_register(&pdev->dev, &tps->desc[i],
+                                              &config);
                if (IS_ERR(rdev)) {
                        dev_err(tps6507x_dev->dev,
                                "failed to register %s regulator\n",
                                pdev->name);
-                       error = PTR_ERR(rdev);
-                       goto fail;
+                       return PTR_ERR(rdev);
                }
 
                /* Save regulator for cleanup */
@@ -525,22 +525,6 @@ static int tps6507x_pmic_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, tps6507x_dev);
 
        return 0;
-
-fail:
-       while (--i >= 0)
-               regulator_unregister(tps->rdev[i]);
-       return error;
-}
-
-static int tps6507x_pmic_remove(struct platform_device *pdev)
-{
-       struct tps6507x_dev *tps6507x_dev = platform_get_drvdata(pdev);
-       struct tps6507x_pmic *tps = tps6507x_dev->pmic;
-       int i;
-
-       for (i = 0; i < TPS6507X_NUM_REGULATOR; i++)
-               regulator_unregister(tps->rdev[i]);
-       return 0;
 }
 
 static struct platform_driver tps6507x_pmic_driver = {
@@ -549,7 +533,6 @@ static struct platform_driver tps6507x_pmic_driver = {
                .owner = THIS_MODULE,
        },
        .probe = tps6507x_pmic_probe,
-       .remove = tps6507x_pmic_remove,
 };
 
 static int __init tps6507x_pmic_init(void)
index c8e70451df38864ffbe2ffb3b9fb3d67817fedc4..bd611cdf6e1c595754ec5b09dccbf0be447cc9c3 100644 (file)
@@ -279,7 +279,7 @@ static int tps65090_regulator_probe(struct platform_device *pdev)
                                if (ret < 0) {
                                        dev_err(&pdev->dev,
                                                "failed disable ext control\n");
-                                       goto scrub;
+                                       return ret;
                                }
                        }
                }
@@ -296,12 +296,11 @@ static int tps65090_regulator_probe(struct platform_device *pdev)
                else
                        config.of_node = NULL;
 
-               rdev = regulator_register(ri->desc, &config);
+               rdev = devm_regulator_register(&pdev->dev, ri->desc, &config);
                if (IS_ERR(rdev)) {
                        dev_err(&pdev->dev, "failed to register regulator %s\n",
                                ri->desc->name);
-                       ret = PTR_ERR(rdev);
-                       goto scrub;
+                       return PTR_ERR(rdev);
                }
                ri->rdev = rdev;
 
@@ -309,36 +308,13 @@ static int tps65090_regulator_probe(struct platform_device *pdev)
                if (tps_pdata && is_dcdc(num) && tps_pdata->reg_init_data &&
                                tps_pdata->enable_ext_control) {
                        ret = tps65090_config_ext_control(ri, true);
-                       if (ret < 0) {
-                               /* Increment num to get unregister rdev */
-                               num++;
-                               goto scrub;
-                       }
+                       if (ret < 0)
+                               return ret;
                }
        }
 
        platform_set_drvdata(pdev, pmic);
        return 0;
-
-scrub:
-       while (--num >= 0) {
-               ri = &pmic[num];
-               regulator_unregister(ri->rdev);
-       }
-       return ret;
-}
-
-static int tps65090_regulator_remove(struct platform_device *pdev)
-{
-       struct tps65090_regulator *pmic = platform_get_drvdata(pdev);
-       struct tps65090_regulator *ri;
-       int num;
-
-       for (num = 0; num < TPS65090_REGULATOR_MAX; ++num) {
-               ri = &pmic[num];
-               regulator_unregister(ri->rdev);
-       }
-       return 0;
 }
 
 static struct platform_driver tps65090_regulator_driver = {
@@ -347,7 +323,6 @@ static struct platform_driver tps65090_regulator_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = tps65090_regulator_probe,
-       .remove         = tps65090_regulator_remove,
 };
 
 static int __init tps65090_regulator_init(void)
index 90861d68a0b002ee3f83b6529feed9884770ca9a..9ea1bf26bd137b4b4e33dcede0c6c1551ff6d79c 100644 (file)
@@ -52,25 +52,17 @@ static const unsigned int LDO1_VSEL_table[] = {
 };
 
 static const struct regulator_linear_range tps65217_uv1_ranges[] = {
-       { .min_uV = 900000, .max_uV = 1500000, .min_sel =  0, .max_sel = 24,
-         .uV_step = 25000 },
-       { .min_uV = 1550000, .max_uV = 1800000, .min_sel = 25, .max_sel = 30,
-         .uV_step = 50000 },
-       { .min_uV = 1850000, .max_uV = 2900000, .min_sel = 31, .max_sel = 52,
-         .uV_step = 50000 },
-       { .min_uV = 3000000, .max_uV = 3200000, .min_sel = 53, .max_sel = 55,
-         .uV_step = 100000 },
-       { .min_uV = 3300000, .max_uV = 3300000, .min_sel = 56, .max_sel = 62,
-         .uV_step = 0 },
+       REGULATOR_LINEAR_RANGE(900000, 0, 24, 25000),
+       REGULATOR_LINEAR_RANGE(1550000, 25, 30, 50000),
+       REGULATOR_LINEAR_RANGE(1850000, 31, 52, 50000),
+       REGULATOR_LINEAR_RANGE(3000000, 53, 55, 100000),
+       REGULATOR_LINEAR_RANGE(3300000, 56, 62, 0),
 };
 
 static const struct regulator_linear_range tps65217_uv2_ranges[] = {
-       { .min_uV = 1500000, .max_uV = 1900000, .min_sel =  0, .max_sel = 8,
-         .uV_step = 50000 },
-       { .min_uV = 2000000, .max_uV = 2400000, .min_sel = 9, .max_sel = 13,
-         .uV_step = 100000 },
-       { .min_uV = 2450000, .max_uV = 3300000, .min_sel = 14, .max_sel = 31,
-         .uV_step = 50000 },
+       REGULATOR_LINEAR_RANGE(1500000, 0, 8, 50000),
+       REGULATOR_LINEAR_RANGE(2000000, 9, 13, 100000),
+       REGULATOR_LINEAR_RANGE(2450000, 14, 31, 50000),
 };
 
 static int tps65217_pmic_enable(struct regulator_dev *dev)
@@ -233,7 +225,7 @@ static int tps65217_regulator_probe(struct platform_device *pdev)
        struct regulator_init_data *reg_data;
        struct regulator_dev *rdev;
        struct regulator_config config = { };
-       int i, ret;
+       int i;
 
        if (tps->dev->of_node)
                pdata = tps65217_parse_dt(pdev);
@@ -269,35 +261,18 @@ static int tps65217_regulator_probe(struct platform_device *pdev)
                if (tps->dev->of_node)
                        config.of_node = pdata->of_node[i];
 
-               rdev = regulator_register(&regulators[i], &config);
+               rdev = devm_regulator_register(&pdev->dev, &regulators[i],
+                                              &config);
                if (IS_ERR(rdev)) {
                        dev_err(tps->dev, "failed to register %s regulator\n",
                                pdev->name);
-                       ret = PTR_ERR(rdev);
-                       goto err_unregister_regulator;
+                       return PTR_ERR(rdev);
                }
 
                /* Save regulator for cleanup */
                tps->rdev[i] = rdev;
        }
        return 0;
-
-err_unregister_regulator:
-       while (--i >= 0)
-               regulator_unregister(tps->rdev[i]);
-
-       return ret;
-}
-
-static int tps65217_regulator_remove(struct platform_device *pdev)
-{
-       struct tps65217 *tps = platform_get_drvdata(pdev);
-       unsigned int i;
-
-       for (i = 0; i < TPS65217_NUM_REGULATOR; i++)
-               regulator_unregister(tps->rdev[i]);
-
-       return 0;
 }
 
 static struct platform_driver tps65217_regulator_driver = {
@@ -305,7 +280,6 @@ static struct platform_driver tps65217_regulator_driver = {
                .name = "tps65217-pmic",
        },
        .probe = tps65217_regulator_probe,
-       .remove = tps65217_regulator_remove,
 };
 
 static int __init tps65217_regulator_init(void)
index 62e8d28beabd7cc8ad51b2935e29b7d348e17438..9f6bfda711b73a6dae9cdc9b8be3b69b2f5e88cc 100644 (file)
@@ -577,21 +577,6 @@ static struct regulator_ops regulator_ops = {
        .get_current_limit      = get_current_limit,
 };
 
-static int pmic_remove(struct spi_device *spi)
-{
-       struct tps6524x *hw = spi_get_drvdata(spi);
-       int i;
-
-       if (!hw)
-               return 0;
-       for (i = 0; i < N_REGULATORS; i++) {
-               regulator_unregister(hw->rdev[i]);
-               hw->rdev[i] = NULL;
-       }
-       spi_set_drvdata(spi, NULL);
-       return 0;
-}
-
 static int pmic_probe(struct spi_device *spi)
 {
        struct tps6524x *hw;
@@ -599,7 +584,7 @@ static int pmic_probe(struct spi_device *spi)
        const struct supply_info *info = supply_info;
        struct regulator_init_data *init_data;
        struct regulator_config config = { };
-       int ret = 0, i;
+       int i;
 
        init_data = dev_get_platdata(dev);
        if (!init_data) {
@@ -632,24 +617,17 @@ static int pmic_probe(struct spi_device *spi)
                config.init_data = init_data;
                config.driver_data = hw;
 
-               hw->rdev[i] = regulator_register(&hw->desc[i], &config);
-               if (IS_ERR(hw->rdev[i])) {
-                       ret = PTR_ERR(hw->rdev[i]);
-                       hw->rdev[i] = NULL;
-                       goto fail;
-               }
+               hw->rdev[i] = devm_regulator_register(dev, &hw->desc[i],
+                                                     &config);
+               if (IS_ERR(hw->rdev[i]))
+                       return PTR_ERR(hw->rdev[i]);
        }
 
        return 0;
-
-fail:
-       pmic_remove(spi);
-       return ret;
 }
 
 static struct spi_driver pmic_driver = {
        .probe          = pmic_probe,
-       .remove         = pmic_remove,
        .driver         = {
                .name   = "tps6524x",
                .owner  = THIS_MODULE,
index 2c9155b66f09f914789c4afde4a8fd630ddd6eba..45e5d683d3f875e154f55c19480ca5ab2dd8f250 100644 (file)
@@ -379,15 +379,14 @@ static int tps6586x_regulator_probe(struct platform_device *pdev)
                ri = find_regulator_info(id);
                if (!ri) {
                        dev_err(&pdev->dev, "invalid regulator ID specified\n");
-                       err = -EINVAL;
-                       goto fail;
+                       return -EINVAL;
                }
 
                err = tps6586x_regulator_preinit(pdev->dev.parent, ri);
                if (err) {
                        dev_err(&pdev->dev,
                                "regulator %d preinit failed, e %d\n", id, err);
-                       goto fail;
+                       return err;
                }
 
                config.dev = pdev->dev.parent;
@@ -397,12 +396,12 @@ static int tps6586x_regulator_probe(struct platform_device *pdev)
                if (tps6586x_reg_matches)
                        config.of_node = tps6586x_reg_matches[id].of_node;
 
-               rdev[id] = regulator_register(&ri->desc, &config);
+               rdev[id] = devm_regulator_register(&pdev->dev, &ri->desc,
+                                                  &config);
                if (IS_ERR(rdev[id])) {
                        dev_err(&pdev->dev, "failed to register regulator %s\n",
                                        ri->desc.name);
-                       err = PTR_ERR(rdev[id]);
-                       goto fail;
+                       return PTR_ERR(rdev[id]);
                }
 
                if (reg_data) {
@@ -411,30 +410,13 @@ static int tps6586x_regulator_probe(struct platform_device *pdev)
                        if (err < 0) {
                                dev_err(&pdev->dev,
                                        "Slew rate config failed, e %d\n", err);
-                               regulator_unregister(rdev[id]);
-                               goto fail;
+                               return err;
                        }
                }
        }
 
        platform_set_drvdata(pdev, rdev);
        return 0;
-
-fail:
-       while (--id >= 0)
-               regulator_unregister(rdev[id]);
-       return err;
-}
-
-static int tps6586x_regulator_remove(struct platform_device *pdev)
-{
-       struct regulator_dev **rdev = platform_get_drvdata(pdev);
-       int id = TPS6586X_ID_MAX_REGULATOR;
-
-       while (--id >= 0)
-               regulator_unregister(rdev[id]);
-
-       return 0;
 }
 
 static struct platform_driver tps6586x_regulator_driver = {
@@ -443,7 +425,6 @@ static struct platform_driver tps6586x_regulator_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = tps6586x_regulator_probe,
-       .remove         = tps6586x_regulator_remove,
 };
 
 static int __init tps6586x_regulator_init(void)
index 45c16447744bb1bc303a4243a0aa281a3a6317b7..b8167df71170f174cab63a19704528f549253726 100644 (file)
@@ -1177,35 +1177,19 @@ static int tps65910_probe(struct platform_device *pdev)
                if (tps65910_reg_matches)
                        config.of_node = tps65910_reg_matches[i].of_node;
 
-               rdev = regulator_register(&pmic->desc[i], &config);
+               rdev = devm_regulator_register(&pdev->dev, &pmic->desc[i],
+                                              &config);
                if (IS_ERR(rdev)) {
                        dev_err(tps65910->dev,
                                "failed to register %s regulator\n",
                                pdev->name);
-                       err = PTR_ERR(rdev);
-                       goto err_unregister_regulator;
+                       return PTR_ERR(rdev);
                }
 
                /* Save regulator for cleanup */
                pmic->rdev[i] = rdev;
        }
        return 0;
-
-err_unregister_regulator:
-       while (--i >= 0)
-               regulator_unregister(pmic->rdev[i]);
-       return err;
-}
-
-static int tps65910_remove(struct platform_device *pdev)
-{
-       struct tps65910_reg *pmic = platform_get_drvdata(pdev);
-       int i;
-
-       for (i = 0; i < pmic->num_regulators; i++)
-               regulator_unregister(pmic->rdev[i]);
-
-       return 0;
 }
 
 static void tps65910_shutdown(struct platform_device *pdev)
@@ -1244,7 +1228,6 @@ static struct platform_driver tps65910_driver = {
                .owner = THIS_MODULE,
        },
        .probe = tps65910_probe,
-       .remove = tps65910_remove,
        .shutdown = tps65910_shutdown,
 };
 
index 281e52ac64ba0e3caf66c0322bd23ac91455a8a4..9cafaa0f94555a1e8fef93b4c0171be0aaea969f 100644 (file)
@@ -119,12 +119,9 @@ struct tps65912_reg {
 };
 
 static const struct regulator_linear_range tps65912_ldo_ranges[] = {
-       { .min_uV = 800000, .max_uV = 1600000, .min_sel =  0, .max_sel = 32,
-         .uV_step = 25000 },
-       { .min_uV = 1650000, .max_uV = 3000000, .min_sel = 33, .max_sel = 60,
-         .uV_step = 50000 },
-       { .min_uV = 3100000, .max_uV = 3300000, .min_sel = 61, .max_sel = 63,
-         .uV_step = 100000 },
+       REGULATOR_LINEAR_RANGE(800000, 0, 32, 25000),
+       REGULATOR_LINEAR_RANGE(1650000, 33, 60, 50000),
+       REGULATOR_LINEAR_RANGE(3100000, 61, 63, 100000),
 };
 
 static int tps65912_get_range(struct tps65912_reg *pmic, int id)
@@ -461,7 +458,7 @@ static int tps65912_probe(struct platform_device *pdev)
        struct regulator_dev *rdev;
        struct tps65912_reg *pmic;
        struct tps65912_board *pmic_plat_data;
-       int i, err;
+       int i;
 
        pmic_plat_data = dev_get_platdata(tps65912->dev);
        if (!pmic_plat_data)
@@ -504,34 +501,19 @@ static int tps65912_probe(struct platform_device *pdev)
                config.init_data = reg_data;
                config.driver_data = pmic;
 
-               rdev = regulator_register(&pmic->desc[i], &config);
+               rdev = devm_regulator_register(&pdev->dev, &pmic->desc[i],
+                                              &config);
                if (IS_ERR(rdev)) {
                        dev_err(tps65912->dev,
                                "failed to register %s regulator\n",
                                pdev->name);
-                       err = PTR_ERR(rdev);
-                       goto err;
+                       return PTR_ERR(rdev);
                }
 
                /* Save regulator for cleanup */
                pmic->rdev[i] = rdev;
        }
        return 0;
-
-err:
-       while (--i >= 0)
-               regulator_unregister(pmic->rdev[i]);
-       return err;
-}
-
-static int tps65912_remove(struct platform_device *pdev)
-{
-       struct tps65912_reg *tps65912_reg = platform_get_drvdata(pdev);
-       int i;
-
-       for (i = 0; i < TPS65912_NUM_REGULATOR; i++)
-               regulator_unregister(tps65912_reg->rdev[i]);
-       return 0;
 }
 
 static struct platform_driver tps65912_driver = {
@@ -540,7 +522,6 @@ static struct platform_driver tps65912_driver = {
                .owner = THIS_MODULE,
        },
        .probe = tps65912_probe,
-       .remove = tps65912_remove,
 };
 
 static int __init tps65912_init(void)
index 6511d0bfd8964ecba4861dfd30c91d727c39ef25..71f457a42623f602541ae5d69b90521d673c9e2b 100644 (file)
@@ -719,7 +719,7 @@ static int tps80031_regulator_probe(struct platform_device *pdev)
                        if (ret < 0) {
                                dev_err(&pdev->dev,
                                        "regulator config failed, e %d\n", ret);
-                               goto fail;
+                               return ret;
                        }
 
                        ret = tps80031_power_req_config(pdev->dev.parent,
@@ -727,41 +727,22 @@ static int tps80031_regulator_probe(struct platform_device *pdev)
                        if (ret < 0) {
                                dev_err(&pdev->dev,
                                        "pwr_req config failed, err %d\n", ret);
-                               goto fail;
+                               return ret;
                        }
                }
-               rdev = regulator_register(&ri->rinfo->desc, &config);
+               rdev = devm_regulator_register(&pdev->dev, &ri->rinfo->desc,
+                                              &config);
                if (IS_ERR(rdev)) {
                        dev_err(&pdev->dev,
                                "register regulator failed %s\n",
                                        ri->rinfo->desc.name);
-                       ret = PTR_ERR(rdev);
-                       goto fail;
+                       return PTR_ERR(rdev);
                }
                ri->rdev = rdev;
        }
 
        platform_set_drvdata(pdev, pmic);
        return 0;
-fail:
-       while (--num >= 0) {
-               ri = &pmic[num];
-               regulator_unregister(ri->rdev);
-       }
-       return ret;
-}
-
-static int tps80031_regulator_remove(struct platform_device *pdev)
-{
-       struct tps80031_regulator *pmic = platform_get_drvdata(pdev);
-       struct tps80031_regulator *ri = NULL;
-       int num;
-
-       for (num = 0; num < TPS80031_REGULATOR_MAX; ++num) {
-               ri = &pmic[num];
-               regulator_unregister(ri->rdev);
-       }
-       return 0;
 }
 
 static struct platform_driver tps80031_regulator_driver = {
@@ -770,7 +751,6 @@ static struct platform_driver tps80031_regulator_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = tps80031_regulator_probe,
-       .remove         = tps80031_regulator_remove,
 };
 
 static int __init tps80031_regulator_init(void)
index 78aae4cbb00424864fbad430fc55379a060065c5..8ebd785485c73ddceba4047facf3960192a2cdf2 100644 (file)
@@ -1188,7 +1188,7 @@ static int twlreg_probe(struct platform_device *pdev)
        config.driver_data = info;
        config.of_node = pdev->dev.of_node;
 
-       rdev = regulator_register(&info->desc, &config);
+       rdev = devm_regulator_register(&pdev->dev, &info->desc, &config);
        if (IS_ERR(rdev)) {
                dev_err(&pdev->dev, "can't register %s, %ld\n",
                                info->desc.name, PTR_ERR(rdev));
@@ -1217,7 +1217,6 @@ static int twlreg_remove(struct platform_device *pdev)
        struct regulator_dev *rdev = platform_get_drvdata(pdev);
        struct twlreg_info *info = rdev->reg_data;
 
-       regulator_unregister(rdev);
        kfree(info);
        return 0;
 }
index 4668c7f8133d7ecff17261d0af3640bbe5ba5cf4..f3ae28a7e66371143b6be01c9640712533faf541 100644 (file)
@@ -96,7 +96,7 @@ static int vexpress_regulator_probe(struct platform_device *pdev)
        config.driver_data = reg;
        config.of_node = pdev->dev.of_node;
 
-       reg->regdev = regulator_register(&reg->desc, &config);
+       reg->regdev = devm_regulator_register(&pdev->dev, &reg->desc, &config);
        if (IS_ERR(reg->regdev)) {
                err = PTR_ERR(reg->regdev);
                goto error_regulator_register;
@@ -119,7 +119,6 @@ static int vexpress_regulator_remove(struct platform_device *pdev)
        struct vexpress_regulator *reg = platform_get_drvdata(pdev);
 
        vexpress_config_func_put(reg->func);
-       regulator_unregister(reg->regdev);
 
        return 0;
 }
index 11861cb861df04394ff1de205eb7896c9ab98f89..6823e6f2b88aa13fde26a00e75b5d4ed8a2ce2ea 100644 (file)
@@ -387,8 +387,9 @@ static struct regulator_ops wm831x_buckv_ops = {
  * Set up DVS control.  We just log errors since we can still run
  * (with reduced performance) if we fail.
  */
-static void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc,
-                                           struct wm831x_buckv_pdata *pdata)
+static void wm831x_buckv_dvs_init(struct platform_device *pdev,
+                                 struct wm831x_dcdc *dcdc,
+                                 struct wm831x_buckv_pdata *pdata)
 {
        struct wm831x *wm831x = dcdc->wm831x;
        int ret;
@@ -402,9 +403,9 @@ static void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc,
         */
        dcdc->dvs_gpio_state = pdata->dvs_init_state;
 
-       ret = gpio_request_one(pdata->dvs_gpio,
-                              dcdc->dvs_gpio_state ? GPIOF_INIT_HIGH : 0,
-                              "DCDC DVS");
+       ret = devm_gpio_request_one(&pdev->dev, pdata->dvs_gpio,
+                                   dcdc->dvs_gpio_state ? GPIOF_INIT_HIGH : 0,
+                                   "DCDC DVS");
        if (ret < 0) {
                dev_err(wm831x->dev, "Failed to get %s DVS GPIO: %d\n",
                        dcdc->name, ret);
@@ -513,7 +514,8 @@ static int wm831x_buckv_probe(struct platform_device *pdev)
        dcdc->dvs_vsel = ret & WM831X_DC1_DVS_VSEL_MASK;
 
        if (pdata && pdata->dcdc[id])
-               wm831x_buckv_dvs_init(dcdc, pdata->dcdc[id]->driver_data);
+               wm831x_buckv_dvs_init(pdev, dcdc,
+                                     pdata->dcdc[id]->driver_data);
 
        config.dev = pdev->dev.parent;
        if (pdata)
@@ -521,7 +523,8 @@ static int wm831x_buckv_probe(struct platform_device *pdev)
        config.driver_data = dcdc;
        config.regmap = wm831x->regmap;
 
-       dcdc->regulator = regulator_register(&dcdc->desc, &config);
+       dcdc->regulator = devm_regulator_register(&pdev->dev, &dcdc->desc,
+                                                 &config);
        if (IS_ERR(dcdc->regulator)) {
                ret = PTR_ERR(dcdc->regulator);
                dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n",
@@ -530,57 +533,35 @@ static int wm831x_buckv_probe(struct platform_device *pdev)
        }
 
        irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));
-       ret = request_threaded_irq(irq, NULL, wm831x_dcdc_uv_irq,
-                                  IRQF_TRIGGER_RISING, dcdc->name, dcdc);
+       ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+                                       wm831x_dcdc_uv_irq,
+                                       IRQF_TRIGGER_RISING, dcdc->name, dcdc);
        if (ret != 0) {
                dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",
                        irq, ret);
-               goto err_regulator;
+               goto err;
        }
 
        irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "HC"));
-       ret = request_threaded_irq(irq, NULL, wm831x_dcdc_oc_irq,
-                                  IRQF_TRIGGER_RISING, dcdc->name, dcdc);
+       ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+                                       wm831x_dcdc_oc_irq,
+                                       IRQF_TRIGGER_RISING, dcdc->name, dcdc);
        if (ret != 0) {
                dev_err(&pdev->dev, "Failed to request HC IRQ %d: %d\n",
                        irq, ret);
-               goto err_uv;
+               goto err;
        }
 
        platform_set_drvdata(pdev, dcdc);
 
        return 0;
 
-err_uv:
-       free_irq(wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV")),
-                dcdc);
-err_regulator:
-       regulator_unregister(dcdc->regulator);
 err:
-       if (dcdc->dvs_gpio)
-               gpio_free(dcdc->dvs_gpio);
        return ret;
 }
 
-static int wm831x_buckv_remove(struct platform_device *pdev)
-{
-       struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
-       struct wm831x *wm831x = dcdc->wm831x;
-
-       free_irq(wm831x_irq(wm831x, platform_get_irq_byname(pdev, "HC")),
-                           dcdc);
-       free_irq(wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV")),
-                           dcdc);
-       regulator_unregister(dcdc->regulator);
-       if (dcdc->dvs_gpio)
-               gpio_free(dcdc->dvs_gpio);
-
-       return 0;
-}
-
 static struct platform_driver wm831x_buckv_driver = {
        .probe = wm831x_buckv_probe,
-       .remove = wm831x_buckv_remove,
        .driver         = {
                .name   = "wm831x-buckv",
                .owner  = THIS_MODULE,
@@ -681,7 +662,8 @@ static int wm831x_buckp_probe(struct platform_device *pdev)
        config.driver_data = dcdc;
        config.regmap = wm831x->regmap;
 
-       dcdc->regulator = regulator_register(&dcdc->desc, &config);
+       dcdc->regulator = devm_regulator_register(&pdev->dev, &dcdc->desc,
+                                                 &config);
        if (IS_ERR(dcdc->regulator)) {
                ret = PTR_ERR(dcdc->regulator);
                dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n",
@@ -690,38 +672,25 @@ static int wm831x_buckp_probe(struct platform_device *pdev)
        }
 
        irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));
-       ret = request_threaded_irq(irq, NULL, wm831x_dcdc_uv_irq,
-                                  IRQF_TRIGGER_RISING, dcdc->name, dcdc);
+       ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+                                       wm831x_dcdc_uv_irq,
+                                       IRQF_TRIGGER_RISING, dcdc->name, dcdc);
        if (ret != 0) {
                dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",
                        irq, ret);
-               goto err_regulator;
+               goto err;
        }
 
        platform_set_drvdata(pdev, dcdc);
 
        return 0;
 
-err_regulator:
-       regulator_unregister(dcdc->regulator);
 err:
        return ret;
 }
 
-static int wm831x_buckp_remove(struct platform_device *pdev)
-{
-       struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
-
-       free_irq(wm831x_irq(dcdc->wm831x, platform_get_irq_byname(pdev, "UV")),
-                           dcdc);
-       regulator_unregister(dcdc->regulator);
-
-       return 0;
-}
-
 static struct platform_driver wm831x_buckp_driver = {
        .probe = wm831x_buckp_probe,
-       .remove = wm831x_buckp_remove,
        .driver         = {
                .name   = "wm831x-buckp",
                .owner  = THIS_MODULE,
@@ -813,7 +782,8 @@ static int wm831x_boostp_probe(struct platform_device *pdev)
        config.driver_data = dcdc;
        config.regmap = wm831x->regmap;
 
-       dcdc->regulator = regulator_register(&dcdc->desc, &config);
+       dcdc->regulator = devm_regulator_register(&pdev->dev, &dcdc->desc,
+                                                 &config);
        if (IS_ERR(dcdc->regulator)) {
                ret = PTR_ERR(dcdc->regulator);
                dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n",
@@ -822,39 +792,26 @@ static int wm831x_boostp_probe(struct platform_device *pdev)
        }
 
        irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));
-       ret = request_threaded_irq(irq, NULL, wm831x_dcdc_uv_irq,
-                                  IRQF_TRIGGER_RISING, dcdc->name,
-                                  dcdc);
+       ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+                                       wm831x_dcdc_uv_irq,
+                                       IRQF_TRIGGER_RISING, dcdc->name,
+                                       dcdc);
        if (ret != 0) {
                dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",
                        irq, ret);
-               goto err_regulator;
+               goto err;
        }
 
        platform_set_drvdata(pdev, dcdc);
 
        return 0;
 
-err_regulator:
-       regulator_unregister(dcdc->regulator);
 err:
        return ret;
 }
 
-static int wm831x_boostp_remove(struct platform_device *pdev)
-{
-       struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
-
-       free_irq(wm831x_irq(dcdc->wm831x, platform_get_irq_byname(pdev, "UV")),
-                dcdc);
-       regulator_unregister(dcdc->regulator);
-
-       return 0;
-}
-
 static struct platform_driver wm831x_boostp_driver = {
        .probe = wm831x_boostp_probe,
-       .remove = wm831x_boostp_remove,
        .driver         = {
                .name   = "wm831x-boostp",
                .owner  = THIS_MODULE,
@@ -914,7 +871,8 @@ static int wm831x_epe_probe(struct platform_device *pdev)
        config.driver_data = dcdc;
        config.regmap = wm831x->regmap;
 
-       dcdc->regulator = regulator_register(&dcdc->desc, &config);
+       dcdc->regulator = devm_regulator_register(&pdev->dev, &dcdc->desc,
+                                                 &config);
        if (IS_ERR(dcdc->regulator)) {
                ret = PTR_ERR(dcdc->regulator);
                dev_err(wm831x->dev, "Failed to register EPE%d: %d\n",
@@ -930,18 +888,8 @@ err:
        return ret;
 }
 
-static int wm831x_epe_remove(struct platform_device *pdev)
-{
-       struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
-
-       regulator_unregister(dcdc->regulator);
-
-       return 0;
-}
-
 static struct platform_driver wm831x_epe_driver = {
        .probe = wm831x_epe_probe,
-       .remove = wm831x_epe_remove,
        .driver         = {
                .name   = "wm831x-epe",
                .owner  = THIS_MODULE,
index 4eb373de1facc63a4041ebc2c2804de358363287..0339b886df5dbf2a6bde26111a0a4c6a60f58732 100644 (file)
@@ -194,7 +194,8 @@ static int wm831x_isink_probe(struct platform_device *pdev)
        config.init_data = pdata->isink[id];
        config.driver_data = isink;
 
-       isink->regulator = regulator_register(&isink->desc, &config);
+       isink->regulator = devm_regulator_register(&pdev->dev, &isink->desc,
+                                                  &config);
        if (IS_ERR(isink->regulator)) {
                ret = PTR_ERR(isink->regulator);
                dev_err(wm831x->dev, "Failed to register ISINK%d: %d\n",
@@ -203,38 +204,26 @@ static int wm831x_isink_probe(struct platform_device *pdev)
        }
 
        irq = wm831x_irq(wm831x, platform_get_irq(pdev, 0));
-       ret = request_threaded_irq(irq, NULL, wm831x_isink_irq,
-                                  IRQF_TRIGGER_RISING, isink->name, isink);
+       ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+                                       wm831x_isink_irq,
+                                       IRQF_TRIGGER_RISING, isink->name,
+                                       isink);
        if (ret != 0) {
                dev_err(&pdev->dev, "Failed to request ISINK IRQ %d: %d\n",
                        irq, ret);
-               goto err_regulator;
+               goto err;
        }
 
        platform_set_drvdata(pdev, isink);
 
        return 0;
 
-err_regulator:
-       regulator_unregister(isink->regulator);
 err:
        return ret;
 }
 
-static int wm831x_isink_remove(struct platform_device *pdev)
-{
-       struct wm831x_isink *isink = platform_get_drvdata(pdev);
-
-       free_irq(wm831x_irq(isink->wm831x, platform_get_irq(pdev, 0)), isink);
-
-       regulator_unregister(isink->regulator);
-
-       return 0;
-}
-
 static struct platform_driver wm831x_isink_driver = {
        .probe = wm831x_isink_probe,
-       .remove = wm831x_isink_remove,
        .driver         = {
                .name   = "wm831x-isink",
                .owner  = THIS_MODULE,
index 2205fbc2c37b4cf9b917bafa5d1f583f7e767b49..46d6700467b57007fbb277283207cfbbc4456fc0 100644 (file)
@@ -63,10 +63,8 @@ static irqreturn_t wm831x_ldo_uv_irq(int irq, void *data)
  */
 
 static const struct regulator_linear_range wm831x_gp_ldo_ranges[] = {
-       { .min_uV =  900000, .max_uV = 1600000, .min_sel =  0, .max_sel = 14,
-         .uV_step =  50000 },
-       { .min_uV = 1700000, .max_uV = 3300000, .min_sel = 15, .max_sel = 31,
-         .uV_step = 100000 },
+       REGULATOR_LINEAR_RANGE(900000, 0, 14, 50000),
+       REGULATOR_LINEAR_RANGE(1700000, 15, 31, 100000),
 };
 
 static int wm831x_gp_ldo_set_suspend_voltage(struct regulator_dev *rdev,
@@ -279,7 +277,8 @@ static int wm831x_gp_ldo_probe(struct platform_device *pdev)
        config.driver_data = ldo;
        config.regmap = wm831x->regmap;
 
-       ldo->regulator = regulator_register(&ldo->desc, &config);
+       ldo->regulator = devm_regulator_register(&pdev->dev, &ldo->desc,
+                                                &config);
        if (IS_ERR(ldo->regulator)) {
                ret = PTR_ERR(ldo->regulator);
                dev_err(wm831x->dev, "Failed to register LDO%d: %d\n",
@@ -288,39 +287,26 @@ static int wm831x_gp_ldo_probe(struct platform_device *pdev)
        }
 
        irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));
-       ret = request_threaded_irq(irq, NULL, wm831x_ldo_uv_irq,
-                                  IRQF_TRIGGER_RISING, ldo->name,
-                                  ldo);
+       ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+                                       wm831x_ldo_uv_irq,
+                                       IRQF_TRIGGER_RISING, ldo->name,
+                                       ldo);
        if (ret != 0) {
                dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",
                        irq, ret);
-               goto err_regulator;
+               goto err;
        }
 
        platform_set_drvdata(pdev, ldo);
 
        return 0;
 
-err_regulator:
-       regulator_unregister(ldo->regulator);
 err:
        return ret;
 }
 
-static int wm831x_gp_ldo_remove(struct platform_device *pdev)
-{
-       struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
-
-       free_irq(wm831x_irq(ldo->wm831x,
-                           platform_get_irq_byname(pdev, "UV")), ldo);
-       regulator_unregister(ldo->regulator);
-
-       return 0;
-}
-
 static struct platform_driver wm831x_gp_ldo_driver = {
        .probe = wm831x_gp_ldo_probe,
-       .remove = wm831x_gp_ldo_remove,
        .driver         = {
                .name   = "wm831x-ldo",
                .owner  = THIS_MODULE,
@@ -332,10 +318,8 @@ static struct platform_driver wm831x_gp_ldo_driver = {
  */
 
 static const struct regulator_linear_range wm831x_aldo_ranges[] = {
-       { .min_uV = 1000000, .max_uV = 1600000, .min_sel =  0, .max_sel = 12,
-         .uV_step =  50000 },
-       { .min_uV = 1700000, .max_uV = 3500000, .min_sel = 13, .max_sel = 31,
-         .uV_step = 100000 },
+       REGULATOR_LINEAR_RANGE(1000000, 0, 12, 50000),
+       REGULATOR_LINEAR_RANGE(1700000, 13, 31, 100000),
 };
 
 static int wm831x_aldo_set_suspend_voltage(struct regulator_dev *rdev,
@@ -505,7 +489,8 @@ static int wm831x_aldo_probe(struct platform_device *pdev)
        config.driver_data = ldo;
        config.regmap = wm831x->regmap;
 
-       ldo->regulator = regulator_register(&ldo->desc, &config);
+       ldo->regulator = devm_regulator_register(&pdev->dev, &ldo->desc,
+                                                &config);
        if (IS_ERR(ldo->regulator)) {
                ret = PTR_ERR(ldo->regulator);
                dev_err(wm831x->dev, "Failed to register LDO%d: %d\n",
@@ -514,38 +499,25 @@ static int wm831x_aldo_probe(struct platform_device *pdev)
        }
 
        irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));
-       ret = request_threaded_irq(irq, NULL, wm831x_ldo_uv_irq,
-                                  IRQF_TRIGGER_RISING, ldo->name, ldo);
+       ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+                                       wm831x_ldo_uv_irq,
+                                       IRQF_TRIGGER_RISING, ldo->name, ldo);
        if (ret != 0) {
                dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",
                        irq, ret);
-               goto err_regulator;
+               goto err;
        }
 
        platform_set_drvdata(pdev, ldo);
 
        return 0;
 
-err_regulator:
-       regulator_unregister(ldo->regulator);
 err:
        return ret;
 }
 
-static int wm831x_aldo_remove(struct platform_device *pdev)
-{
-       struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
-
-       free_irq(wm831x_irq(ldo->wm831x, platform_get_irq_byname(pdev, "UV")),
-                ldo);
-       regulator_unregister(ldo->regulator);
-
-       return 0;
-}
-
 static struct platform_driver wm831x_aldo_driver = {
        .probe = wm831x_aldo_probe,
-       .remove = wm831x_aldo_remove,
        .driver         = {
                .name   = "wm831x-aldo",
                .owner  = THIS_MODULE,
@@ -663,7 +635,8 @@ static int wm831x_alive_ldo_probe(struct platform_device *pdev)
        config.driver_data = ldo;
        config.regmap = wm831x->regmap;
 
-       ldo->regulator = regulator_register(&ldo->desc, &config);
+       ldo->regulator = devm_regulator_register(&pdev->dev, &ldo->desc,
+                                                &config);
        if (IS_ERR(ldo->regulator)) {
                ret = PTR_ERR(ldo->regulator);
                dev_err(wm831x->dev, "Failed to register LDO%d: %d\n",
@@ -679,18 +652,8 @@ err:
        return ret;
 }
 
-static int wm831x_alive_ldo_remove(struct platform_device *pdev)
-{
-       struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
-
-       regulator_unregister(ldo->regulator);
-
-       return 0;
-}
-
 static struct platform_driver wm831x_alive_ldo_driver = {
        .probe = wm831x_alive_ldo_probe,
-       .remove = wm831x_alive_ldo_remove,
        .driver         = {
                .name   = "wm831x-alive-ldo",
                .owner  = THIS_MODULE,
index 61ca9292a42944229f9f52bc6f5b8943b6414b22..de7b9c73e3fa09f3b14db1c5d8949ca99a37c352 100644 (file)
@@ -543,10 +543,8 @@ static int wm8350_dcdc_set_suspend_mode(struct regulator_dev *rdev,
 }
 
 static const struct regulator_linear_range wm8350_ldo_ranges[] = {
-       { .min_uV =  900000, .max_uV = 1650000, .min_sel =  0, .max_sel = 15,
-         .uV_step =  50000 },
-       { .min_uV = 1800000, .max_uV = 3300000, .min_sel = 16, .max_sel = 31,
-         .uV_step = 100000 },
+       REGULATOR_LINEAR_RANGE(900000, 0, 15, 50000),
+       REGULATOR_LINEAR_RANGE(1800000, 16, 31, 100000),
 };
 
 static int wm8350_ldo_set_suspend_voltage(struct regulator_dev *rdev, int uV)
@@ -1206,7 +1204,8 @@ static int wm8350_regulator_probe(struct platform_device *pdev)
        config.regmap = wm8350->regmap;
 
        /* register regulator */
-       rdev = regulator_register(&wm8350_reg[pdev->id], &config);
+       rdev = devm_regulator_register(&pdev->dev, &wm8350_reg[pdev->id],
+                                      &config);
        if (IS_ERR(rdev)) {
                dev_err(&pdev->dev, "failed to register %s\n",
                        wm8350_reg[pdev->id].name);
@@ -1217,7 +1216,6 @@ static int wm8350_regulator_probe(struct platform_device *pdev)
        ret = wm8350_register_irq(wm8350, wm8350_reg[pdev->id].irq,
                                  pmic_uv_handler, 0, "UV", rdev);
        if (ret < 0) {
-               regulator_unregister(rdev);
                dev_err(&pdev->dev, "failed to register regulator %s IRQ\n",
                        wm8350_reg[pdev->id].name);
                return ret;
@@ -1233,8 +1231,6 @@ static int wm8350_regulator_remove(struct platform_device *pdev)
 
        wm8350_free_irq(wm8350, wm8350_reg[pdev->id].irq, rdev);
 
-       regulator_unregister(rdev);
-
        return 0;
 }
 
index 58f51bec13f25d2f47a488ca53fc1099bb683762..82d82900085199f738d1555059d396315da6520a 100644 (file)
 #include <linux/mfd/wm8400-private.h>
 
 static const struct regulator_linear_range wm8400_ldo_ranges[] = {
-       { .min_uV =  900000, .max_uV = 1600000, .min_sel = 0, .max_sel = 14,
-         .uV_step =  50000 },
-       { .min_uV = 1700000, .max_uV = 3300000, .min_sel = 15, .max_sel = 31,
-         .uV_step = 100000 },
+       REGULATOR_LINEAR_RANGE(900000, 0, 14, 50000),
+       REGULATOR_LINEAR_RANGE(1700000, 15, 31, 100000),
 };
 
 static struct regulator_ops wm8400_ldo_ops = {
@@ -219,7 +217,8 @@ static int wm8400_regulator_probe(struct platform_device *pdev)
        config.driver_data = wm8400;
        config.regmap = wm8400->regmap;
 
-       rdev = regulator_register(&regulators[pdev->id], &config);
+       rdev = devm_regulator_register(&pdev->dev, &regulators[pdev->id],
+                                      &config);
        if (IS_ERR(rdev))
                return PTR_ERR(rdev);
 
@@ -228,21 +227,11 @@ static int wm8400_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int wm8400_regulator_remove(struct platform_device *pdev)
-{
-       struct regulator_dev *rdev = platform_get_drvdata(pdev);
-
-       regulator_unregister(rdev);
-
-       return 0;
-}
-
 static struct platform_driver wm8400_regulator_driver = {
        .driver = {
                .name = "wm8400-regulator",
        },
        .probe = wm8400_regulator_probe,
-       .remove = wm8400_regulator_remove,
 };
 
 /**
index 5ee2a208457c2b58e46fb1f1d7a79e8b180c4a35..71c5911f2e7130b2114d19b7619a30e69672a94a 100644 (file)
@@ -165,7 +165,9 @@ static int wm8994_ldo_probe(struct platform_device *pdev)
                ldo->init_data = *pdata->ldo[id].init_data;
        }
 
-       ldo->regulator = regulator_register(&wm8994_ldo_desc[id], &config);
+       ldo->regulator = devm_regulator_register(&pdev->dev,
+                                                &wm8994_ldo_desc[id],
+                                                &config);
        if (IS_ERR(ldo->regulator)) {
                ret = PTR_ERR(ldo->regulator);
                dev_err(wm8994->dev, "Failed to register LDO%d: %d\n",
@@ -181,18 +183,8 @@ err:
        return ret;
 }
 
-static int wm8994_ldo_remove(struct platform_device *pdev)
-{
-       struct wm8994_ldo *ldo = platform_get_drvdata(pdev);
-
-       regulator_unregister(ldo->regulator);
-
-       return 0;
-}
-
 static struct platform_driver wm8994_ldo_driver = {
        .probe = wm8994_ldo_probe,
-       .remove = wm8994_ldo_remove,
        .driver         = {
                .name   = "wm8994-ldo",
                .owner  = THIS_MODULE,
index a0ebbc9ce5cdbacc69cc8c240f8d9fd76e43ec12..042aa077b5b3e166a8453ac0684da1dd024f6785 100644 (file)
@@ -1912,9 +1912,6 @@ static int serial_imx_probe_dt(struct imx_port *sport,
 
        sport->devdata = of_id->data;
 
-       if (of_device_is_stdout_path(np))
-               add_preferred_console(imx_reg.cons->name, sport->port.line, 0);
-
        return 0;
 }
 #else
index 93b697a0de658ddc6769fedbe822b1151fef4bab..15ad6fcda88b323b2f5711b753ee76126741ea04 100644 (file)
@@ -561,12 +561,13 @@ static int vt8500_serial_probe(struct platform_device *pdev)
        if (!mmres || !irqres)
                return -ENODEV;
 
-       if (np)
+       if (np) {
                port = of_alias_get_id(np, "serial");
                if (port >= VT8500_MAX_PORTS)
                        port = -1;
-       else
+       } else {
                port = -1;
+       }
 
        if (port < 0) {
                /* calculate the port id */
index 6f96795dd20cc3ff3d0c08490ae8d87b0b2ccccf..64d7a6d9a1adcbd679258661a6b5875bd8bf834a 100644 (file)
@@ -100,8 +100,10 @@ static void host_stop(struct ci_hdrc *ci)
 {
        struct usb_hcd *hcd = ci->hcd;
 
-       usb_remove_hcd(hcd);
-       usb_put_hcd(hcd);
+       if (hcd) {
+               usb_remove_hcd(hcd);
+               usb_put_hcd(hcd);
+       }
        if (ci->platdata->reg_vbus)
                regulator_disable(ci->platdata->reg_vbus);
 }
index 5b44cd47da5b28b30046bead355aa54eda3eec0f..01fe36273f3b144cb1c1fe3306ebdf16459c605f 100644 (file)
@@ -97,6 +97,9 @@ static const struct usb_device_id usb_quirk_list[] = {
        /* Alcor Micro Corp. Hub */
        { USB_DEVICE(0x058f, 0x9254), .driver_info = USB_QUIRK_RESET_RESUME },
 
+       /* MicroTouch Systems touchscreen */
+       { USB_DEVICE(0x0596, 0x051e), .driver_info = USB_QUIRK_RESET_RESUME },
+
        /* appletouch */
        { USB_DEVICE(0x05ac, 0x021a), .driver_info = USB_QUIRK_RESET_RESUME },
 
@@ -130,6 +133,9 @@ static const struct usb_device_id usb_quirk_list[] = {
        /* Broadcom BCM92035DGROM BT dongle */
        { USB_DEVICE(0x0a5c, 0x2021), .driver_info = USB_QUIRK_RESET_RESUME },
 
+       /* MAYA44USB sound device */
+       { USB_DEVICE(0x0a92, 0x0091), .driver_info = USB_QUIRK_RESET_RESUME },
+
        /* Action Semiconductor flash disk */
        { USB_DEVICE(0x10d6, 0x2200), .driver_info =
                        USB_QUIRK_STRING_FETCH_255 },
index 2c76ef1320eab679e1dd1aabd1c8466981392efc..08ef2829a7e2b1c06bbd0af51f308884c8ad9a26 100644 (file)
@@ -799,7 +799,7 @@ void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev)
         * switchable ports.
         */
        pci_write_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN,
-                       cpu_to_le32(ports_available));
+                       ports_available);
 
        pci_read_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN,
                        &ports_available);
@@ -821,7 +821,7 @@ void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev)
         * host.
         */
        pci_write_config_dword(xhci_pdev, USB_INTEL_XUSB2PR,
-                       cpu_to_le32(ports_available));
+                       ports_available);
 
        pci_read_config_dword(xhci_pdev, USB_INTEL_XUSB2PR,
                        &ports_available);
index 773a6b28c4f1657670547265e0d73caed6366907..e8b4c56dcf62adf1f5326e8609087cd387fedc2e 100644 (file)
@@ -1157,18 +1157,6 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
                t1 = xhci_port_state_to_neutral(t1);
                if (t1 != t2)
                        xhci_writel(xhci, t2, port_array[port_index]);
-
-               if (hcd->speed != HCD_USB3) {
-                       /* enable remote wake up for USB 2.0 */
-                       __le32 __iomem *addr;
-                       u32 tmp;
-
-                       /* Get the port power control register address. */
-                       addr = port_array[port_index] + PORTPMSC;
-                       tmp = xhci_readl(xhci, addr);
-                       tmp |= PORT_RWE;
-                       xhci_writel(xhci, tmp, addr);
-               }
        }
        hcd->state = HC_STATE_SUSPENDED;
        bus_state->next_statechange = jiffies + msecs_to_jiffies(10);
@@ -1247,20 +1235,6 @@ int xhci_bus_resume(struct usb_hcd *hcd)
                                xhci_ring_device(xhci, slot_id);
                } else
                        xhci_writel(xhci, temp, port_array[port_index]);
-
-               if (hcd->speed != HCD_USB3) {
-                       /* disable remote wake up for USB 2.0 */
-                       __le32 __iomem *addr;
-                       u32 tmp;
-
-                       /* Add one to the port status register address to get
-                        * the port power control register address.
-                        */
-                       addr = port_array[port_index] + PORTPMSC;
-                       tmp = xhci_readl(xhci, addr);
-                       tmp &= ~PORT_RWE;
-                       xhci_writel(xhci, tmp, addr);
-               }
        }
 
        (void) xhci_readl(xhci, &xhci->op_regs->command);
index 236c3aabe94083ab5c1829241a46a20d39829587..b8dffd59eb256e52786328e5e4f1919846a80d9c 100644 (file)
@@ -35,6 +35,9 @@
 #define PCI_VENDOR_ID_ETRON            0x1b6f
 #define PCI_DEVICE_ID_ASROCK_P67       0x7023
 
+#define PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI     0x8c31
+#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI  0x9c31
+
 static const char hcd_name[] = "xhci_hcd";
 
 /* called after powerup, by probe or system-pm "wakeup" */
@@ -69,6 +72,14 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
                                "QUIRK: Fresco Logic xHC needs configure"
                                " endpoint cmd after reset endpoint");
                }
+               if (pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK &&
+                               pdev->revision == 0x4) {
+                       xhci->quirks |= XHCI_SLOW_SUSPEND;
+                       xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
+                               "QUIRK: Fresco Logic xHC revision %u"
+                               "must be suspended extra slowly",
+                               pdev->revision);
+               }
                /* Fresco Logic confirms: all revisions of this chip do not
                 * support MSI, even though some of them claim to in their PCI
                 * capabilities.
@@ -110,6 +121,15 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
                xhci->quirks |= XHCI_SPURIOUS_REBOOT;
                xhci->quirks |= XHCI_AVOID_BEI;
        }
+       if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
+           (pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI ||
+            pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI)) {
+               /* Workaround for occasional spurious wakeups from S5 (or
+                * any other sleep) on Haswell machines with LPT and LPT-LP
+                * with the new Intel BIOS
+                */
+               xhci->quirks |= XHCI_SPURIOUS_WAKEUP;
+       }
        if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
                        pdev->device == PCI_DEVICE_ID_ASROCK_P67) {
                xhci->quirks |= XHCI_RESET_ON_RESUME;
@@ -217,6 +237,11 @@ static void xhci_pci_remove(struct pci_dev *dev)
                usb_put_hcd(xhci->shared_hcd);
        }
        usb_hcd_pci_remove(dev);
+
+       /* Workaround for spurious wakeups at shutdown with HSW */
+       if (xhci->quirks & XHCI_SPURIOUS_WAKEUP)
+               pci_set_power_state(dev, PCI_D3hot);
+
        kfree(xhci);
 }
 
index 1e36dbb4836693dbe5ac90b8231361f82645a7b1..6e0d886bcce52c19361d321cf68c0abacf5b054c 100644 (file)
@@ -730,6 +730,9 @@ void xhci_shutdown(struct usb_hcd *hcd)
 
        spin_lock_irq(&xhci->lock);
        xhci_halt(xhci);
+       /* Workaround for spurious wakeups at shutdown with HSW */
+       if (xhci->quirks & XHCI_SPURIOUS_WAKEUP)
+               xhci_reset(xhci);
        spin_unlock_irq(&xhci->lock);
 
        xhci_cleanup_msix(xhci);
@@ -737,6 +740,10 @@ void xhci_shutdown(struct usb_hcd *hcd)
        xhci_dbg_trace(xhci, trace_xhci_dbg_init,
                        "xhci_shutdown completed - status = %x",
                        xhci_readl(xhci, &xhci->op_regs->status));
+
+       /* Yet another workaround for spurious wakeups at shutdown with HSW */
+       if (xhci->quirks & XHCI_SPURIOUS_WAKEUP)
+               pci_set_power_state(to_pci_dev(hcd->self.controller), PCI_D3hot);
 }
 
 #ifdef CONFIG_PM
@@ -839,6 +846,7 @@ static void xhci_clear_command_ring(struct xhci_hcd *xhci)
 int xhci_suspend(struct xhci_hcd *xhci)
 {
        int                     rc = 0;
+       unsigned int            delay = XHCI_MAX_HALT_USEC;
        struct usb_hcd          *hcd = xhci_to_hcd(xhci);
        u32                     command;
 
@@ -861,8 +869,12 @@ int xhci_suspend(struct xhci_hcd *xhci)
        command = xhci_readl(xhci, &xhci->op_regs->command);
        command &= ~CMD_RUN;
        xhci_writel(xhci, command, &xhci->op_regs->command);
+
+       /* Some chips from Fresco Logic need an extraordinary delay */
+       delay *= (xhci->quirks & XHCI_SLOW_SUSPEND) ? 10 : 1;
+
        if (xhci_handshake(xhci, &xhci->op_regs->status,
-                     STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC)) {
+                     STS_HALT, STS_HALT, delay)) {
                xhci_warn(xhci, "WARN: xHC CMD_RUN timeout\n");
                spin_unlock_irq(&xhci->lock);
                return -ETIMEDOUT;
index 289fbfbae7463f429ef051602e08e7eccb3e06e8..941d5f59e4dcc254770bac770ba024e36a677bad 100644 (file)
@@ -1548,6 +1548,8 @@ struct xhci_hcd {
 #define XHCI_COMP_MODE_QUIRK   (1 << 14)
 #define XHCI_AVOID_BEI         (1 << 15)
 #define XHCI_PLAT              (1 << 16)
+#define XHCI_SLOW_SUSPEND      (1 << 17)
+#define XHCI_SPURIOUS_WAKEUP   (1 << 18)
        unsigned int            num_active_eps;
        unsigned int            limit_active_eps;
        /* There are two roothubs to keep track of bus suspend info for */
index e2b21c1d9c403088d704d12901c8049e329c360f..ba5f70f92888774c5ef900d44c6f8ad941e6b4e9 100644 (file)
@@ -246,6 +246,6 @@ config USB_EZUSB_FX2
 config USB_HSIC_USB3503
        tristate "USB3503 HSIC to USB20 Driver"
        depends on I2C
-       select REGMAP
+       select REGMAP_I2C
        help
          This option enables support for SMSC USB3503 HSIC to USB 2.0 Driver.
index 18e877ffe7b7d8c7393bdf43efdfd0d58e618011..cd70cc8861711015f5443e2b76e969209d9bdb3a 100644 (file)
@@ -921,6 +921,52 @@ static void musb_generic_disable(struct musb *musb)
 
 }
 
+/*
+ * Program the HDRC to start (enable interrupts, dma, etc.).
+ */
+void musb_start(struct musb *musb)
+{
+       void __iomem    *regs = musb->mregs;
+       u8              devctl = musb_readb(regs, MUSB_DEVCTL);
+
+       dev_dbg(musb->controller, "<== devctl %02x\n", devctl);
+
+       /*  Set INT enable registers, enable interrupts */
+       musb->intrtxe = musb->epmask;
+       musb_writew(regs, MUSB_INTRTXE, musb->intrtxe);
+       musb->intrrxe = musb->epmask & 0xfffe;
+       musb_writew(regs, MUSB_INTRRXE, musb->intrrxe);
+       musb_writeb(regs, MUSB_INTRUSBE, 0xf7);
+
+       musb_writeb(regs, MUSB_TESTMODE, 0);
+
+       /* put into basic highspeed mode and start session */
+       musb_writeb(regs, MUSB_POWER, MUSB_POWER_ISOUPDATE
+                       | MUSB_POWER_HSENAB
+                       /* ENSUSPEND wedges tusb */
+                       /* | MUSB_POWER_ENSUSPEND */
+                  );
+
+       musb->is_active = 0;
+       devctl = musb_readb(regs, MUSB_DEVCTL);
+       devctl &= ~MUSB_DEVCTL_SESSION;
+
+       /* session started after:
+        * (a) ID-grounded irq, host mode;
+        * (b) vbus present/connect IRQ, peripheral mode;
+        * (c) peripheral initiates, using SRP
+        */
+       if (musb->port_mode != MUSB_PORT_MODE_HOST &&
+                       (devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) {
+               musb->is_active = 1;
+       } else {
+               devctl |= MUSB_DEVCTL_SESSION;
+       }
+
+       musb_platform_enable(musb);
+       musb_writeb(regs, MUSB_DEVCTL, devctl);
+}
+
 /*
  * Make the HDRC stop (disable interrupts, etc.);
  * reversible by musb_start
index 65f3917b4fc5fb55c95bf4157d70a1d7194a110d..1c5bf75ee8ff8a45a3da1fca7cb1d31920f0eeff 100644 (file)
@@ -503,6 +503,7 @@ static inline void musb_configure_ep0(struct musb *musb)
 extern const char musb_driver_name[];
 
 extern void musb_stop(struct musb *musb);
+extern void musb_start(struct musb *musb);
 
 extern void musb_write_fifo(struct musb_hw_ep *ep, u16 len, const u8 *src);
 extern void musb_read_fifo(struct musb_hw_ep *ep, u16 len, u8 *dst);
index b19ed213ab8580c5456cbddaca4f217db31733c4..3671898a4535b3cf2de3c0e188f4947485d2760d 100644 (file)
@@ -1853,11 +1853,14 @@ static int musb_gadget_start(struct usb_gadget *g,
        musb->gadget_driver = driver;
 
        spin_lock_irqsave(&musb->lock, flags);
+       musb->is_active = 1;
 
        otg_set_peripheral(otg, &musb->g);
        musb->xceiv->state = OTG_STATE_B_IDLE;
        spin_unlock_irqrestore(&musb->lock, flags);
 
+       musb_start(musb);
+
        /* REVISIT:  funcall to other code, which also
         * handles power budgeting ... this way also
         * ensures HdrcStart is indirectly called.
index a523950c2b32e66e07f7c8bd78daa181f691f25c..d1d6b83aabca61df43dffccf57ccbe7687cbe399 100644 (file)
 
 #include "musb_core.h"
 
-/*
-* Program the HDRC to start (enable interrupts, dma, etc.).
-*/
-static void musb_start(struct musb *musb)
-{
-       void __iomem    *regs = musb->mregs;
-       u8              devctl = musb_readb(regs, MUSB_DEVCTL);
-
-       dev_dbg(musb->controller, "<== devctl %02x\n", devctl);
-
-       /*  Set INT enable registers, enable interrupts */
-       musb->intrtxe = musb->epmask;
-       musb_writew(regs, MUSB_INTRTXE, musb->intrtxe);
-       musb->intrrxe = musb->epmask & 0xfffe;
-       musb_writew(regs, MUSB_INTRRXE, musb->intrrxe);
-       musb_writeb(regs, MUSB_INTRUSBE, 0xf7);
-
-       musb_writeb(regs, MUSB_TESTMODE, 0);
-
-       /* put into basic highspeed mode and start session */
-       musb_writeb(regs, MUSB_POWER, MUSB_POWER_ISOUPDATE
-                                               | MUSB_POWER_HSENAB
-                                               /* ENSUSPEND wedges tusb */
-                                               /* | MUSB_POWER_ENSUSPEND */
-                                               );
-
-       musb->is_active = 0;
-       devctl = musb_readb(regs, MUSB_DEVCTL);
-       devctl &= ~MUSB_DEVCTL_SESSION;
-
-       /* session started after:
-        * (a) ID-grounded irq, host mode;
-        * (b) vbus present/connect IRQ, peripheral mode;
-        * (c) peripheral initiates, using SRP
-        */
-       if (musb->port_mode != MUSB_PORT_MODE_HOST &&
-           (devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) {
-               musb->is_active = 1;
-       } else {
-               devctl |= MUSB_DEVCTL_SESSION;
-       }
-
-       musb_platform_enable(musb);
-       musb_writeb(regs, MUSB_DEVCTL, devctl);
-}
-
 static void musb_port_suspend(struct musb *musb, bool do_suspend)
 {
        struct usb_otg  *otg = musb->xceiv->otg;
index 80a7104d5ddb3e6d81fa125bb13d9a4d0af05dcf..acaee066b99aa10e5ecf2a8e75cffd31899b6507 100644 (file)
@@ -451,6 +451,10 @@ static void option_instat_callback(struct urb *urb);
 #define CHANGHONG_VENDOR_ID                    0x2077
 #define CHANGHONG_PRODUCT_CH690                        0x7001
 
+/* Inovia */
+#define INOVIA_VENDOR_ID                       0x20a6
+#define INOVIA_SEW858                          0x1105
+
 /* some devices interfaces need special handling due to a number of reasons */
 enum option_blacklist_reason {
                OPTION_BLACKLIST_NONE = 0,
@@ -689,6 +693,222 @@ static const struct usb_device_id option_ids[] = {
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7A) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7B) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7C) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x01) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x02) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x03) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x04) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x05) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x06) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x0A) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x0B) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x0D) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x0E) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x0F) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x10) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x12) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x13) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x14) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x15) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x17) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x18) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x19) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x1A) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x1B) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x1C) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x31) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x32) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x33) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x34) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x35) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x36) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x3A) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x3B) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x3D) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x3E) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x3F) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x48) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x49) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x4A) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x4B) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x4C) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x61) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x62) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x63) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x64) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x65) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x66) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6A) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6B) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6D) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6E) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6F) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x78) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x79) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x7A) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x7B) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x7C) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x01) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x02) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x03) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x04) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x05) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x06) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x0A) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x0B) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x0D) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x0E) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x0F) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x10) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x12) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x13) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x14) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x15) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x17) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x18) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x19) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x1A) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x1B) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x1C) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x31) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x32) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x33) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x34) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x35) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x36) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x3A) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x3B) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x3D) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x3E) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x3F) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x48) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x49) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x4A) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x4B) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x4C) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x61) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x62) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x63) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x64) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x65) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x66) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6A) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6B) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6D) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6E) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6F) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x78) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x79) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x7A) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x7B) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x7C) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x01) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x02) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x03) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x04) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x05) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x06) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x0A) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x0B) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x0D) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x0E) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x0F) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x10) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x12) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x13) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x14) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x15) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x17) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x18) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x19) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x1A) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x1B) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x1C) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x31) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x32) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x33) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x34) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x35) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x36) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x3A) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x3B) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x3D) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x3E) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x3F) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x48) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x49) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x4A) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x4B) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x4C) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x61) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x62) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x63) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x64) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x65) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x66) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6A) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6B) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6D) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6E) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6F) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x78) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x79) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x7A) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x7B) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x7C) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x01) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x02) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x03) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x04) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x05) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x06) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x0A) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x0B) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x0D) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x0E) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x0F) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x10) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x12) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x13) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x14) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x15) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x17) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x18) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x19) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x1A) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x1B) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x1C) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x31) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x32) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x33) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x34) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x35) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x36) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x3A) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x3B) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x3D) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x3E) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x3F) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x48) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x49) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x4A) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x4B) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x4C) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x61) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x62) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x63) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x64) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x65) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x66) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6A) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6B) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6D) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6E) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6F) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x78) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x79) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x7A) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x7B) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x7C) },
 
 
        { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) },
@@ -1257,7 +1477,9 @@ static const struct usb_device_id option_ids[] = {
 
        { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100) },
        { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD145) },
-       { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD200) },
+       { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD200),
+               .driver_info = (kernel_ulong_t)&net_intf6_blacklist
+       },
        { USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */
        { USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_GT_B3730, USB_CLASS_CDC_DATA, 0x00, 0x00) }, /* Samsung GT-B3730 LTE USB modem.*/
        { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM600) },
@@ -1345,6 +1567,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x00, 0x00) },
        { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e01, 0xff, 0xff, 0xff) }, /* D-Link DWM-152/C1 */
        { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e02, 0xff, 0xff, 0xff) }, /* D-Link DWM-156/C1 */
+       { USB_DEVICE(INOVIA_VENDOR_ID, INOVIA_SEW858) },
        { } /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
index 760b78560f67fd7e7d905d53dff2cb7a46f2919f..c9a35697ebe9a6e131d5a9c145e5f3f3415dd5bf 100644 (file)
@@ -190,6 +190,7 @@ static struct usb_device_id ti_id_table_combined[] = {
        { USB_DEVICE(IBM_VENDOR_ID, IBM_454B_PRODUCT_ID) },
        { USB_DEVICE(IBM_VENDOR_ID, IBM_454C_PRODUCT_ID) },
        { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_PRODUCT_ID) },
+       { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_STRIP_PORT_ID) },
        { USB_DEVICE(TI_VENDOR_ID, FRI2_PRODUCT_ID) },
        { }     /* terminator */
 };
index 94d75edef77fdf34e4f5e341e5952e532f03f09e..18509e6c21ab84e7d3133f7a0e428ba462d2a24b 100644 (file)
@@ -211,8 +211,11 @@ static int slave_configure(struct scsi_device *sdev)
                /*
                 * Many devices do not respond properly to READ_CAPACITY_16.
                 * Tell the SCSI layer to try READ_CAPACITY_10 first.
+                * However some USB 3.0 drive enclosures return capacity
+                * modulo 2TB. Those must use READ_CAPACITY_16
                 */
-               sdev->try_rc_10_first = 1;
+               if (!(us->fflags & US_FL_NEEDS_CAP16))
+                       sdev->try_rc_10_first = 1;
 
                /* assume SPC3 or latter devices support sense size > 18 */
                if (sdev->scsi_level > SCSI_SPC_2)
index c015f2c16729c5b4030fc829fae9a3cfb90acde6..de32cfa5bfa6ca0772d0955ea83b9b98dd698ea5 100644 (file)
@@ -1925,6 +1925,13 @@ UNUSUAL_DEV(  0x1652, 0x6600, 0x0201, 0x0201,
                USB_SC_DEVICE, USB_PR_DEVICE, NULL,
                US_FL_IGNORE_RESIDUE ),
 
+/* Reported by Oliver Neukum <oneukum@suse.com> */
+UNUSUAL_DEV(  0x174c, 0x55aa, 0x0100, 0x0100,
+               "ASMedia",
+               "AS2105",
+               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+               US_FL_NEEDS_CAP16),
+
 /* Reported by Jesse Feddema <jdfeddema@gmail.com> */
 UNUSUAL_DEV(  0x177f, 0x0400, 0x0000, 0x0000,
                "Yarvik",
index a9807dea3887af0afe44e545784f70d46efa40dd..4fb7a8f83c8a99ff8d3412a5328b2407c98409a8 100644 (file)
@@ -545,6 +545,8 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
        long npage;
        int ret = 0, prot = 0;
        uint64_t mask;
+       struct vfio_dma *dma = NULL;
+       unsigned long pfn;
 
        end = map->iova + map->size;
 
@@ -587,8 +589,6 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
        }
 
        for (iova = map->iova; iova < end; iova += size, vaddr += size) {
-               struct vfio_dma *dma = NULL;
-               unsigned long pfn;
                long i;
 
                /* Pin a contiguous chunk of memory */
@@ -597,16 +597,15 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
                if (npage <= 0) {
                        WARN_ON(!npage);
                        ret = (int)npage;
-                       break;
+                       goto out;
                }
 
                /* Verify pages are not already mapped */
                for (i = 0; i < npage; i++) {
                        if (iommu_iova_to_phys(iommu->domain,
                                               iova + (i << PAGE_SHIFT))) {
-                               vfio_unpin_pages(pfn, npage, prot, true);
                                ret = -EBUSY;
-                               break;
+                               goto out_unpin;
                        }
                }
 
@@ -616,8 +615,7 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
                if (ret) {
                        if (ret != -EBUSY ||
                            map_try_harder(iommu, iova, pfn, npage, prot)) {
-                               vfio_unpin_pages(pfn, npage, prot, true);
-                               break;
+                               goto out_unpin;
                        }
                }
 
@@ -672,9 +670,8 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
                        dma = kzalloc(sizeof(*dma), GFP_KERNEL);
                        if (!dma) {
                                iommu_unmap(iommu->domain, iova, size);
-                               vfio_unpin_pages(pfn, npage, prot, true);
                                ret = -ENOMEM;
-                               break;
+                               goto out_unpin;
                        }
 
                        dma->size = size;
@@ -685,16 +682,21 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
                }
        }
 
-       if (ret) {
-               struct vfio_dma *tmp;
-               iova = map->iova;
-               size = map->size;
-               while ((tmp = vfio_find_dma(iommu, iova, size))) {
-                       int r = vfio_remove_dma_overlap(iommu, iova,
-                                                       &size, tmp);
-                       if (WARN_ON(r || !size))
-                               break;
-               }
+       WARN_ON(ret);
+       mutex_unlock(&iommu->lock);
+       return ret;
+
+out_unpin:
+       vfio_unpin_pages(pfn, npage, prot, true);
+
+out:
+       iova = map->iova;
+       size = map->size;
+       while ((dma = vfio_find_dma(iommu, iova, size))) {
+               int r = vfio_remove_dma_overlap(iommu, iova,
+                                               &size, dma);
+               if (WARN_ON(r || !size))
+                       break;
        }
 
        mutex_unlock(&iommu->lock);
index c7c64f18773d87d5f23e81ec90ba7d8bfaee504a..fa932c2f7d97276b66199eda06b6edb6565208bb 100644 (file)
@@ -613,6 +613,9 @@ static int w1_bus_notify(struct notifier_block *nb, unsigned long action,
        sl = dev_to_w1_slave(dev);
        fops = sl->family->fops;
 
+       if (!fops)
+               return 0;
+
        switch (action) {
        case BUS_NOTIFY_ADD_DEVICE:
                /* if the family driver needs to initialize something... */
@@ -713,7 +716,10 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn)
        atomic_set(&sl->refcnt, 0);
        init_completion(&sl->released);
 
+       /* slave modules need to be loaded in a context with unlocked mutex */
+       mutex_unlock(&dev->mutex);
        request_module("w1-family-0x%0x", rn->family);
+       mutex_lock(&dev->mutex);
 
        spin_lock(&w1_flock);
        f = w1_family_registered(rn->family);
index b0ef7b07b1b3be510e85dd1bab6711e7d27cebee..51e3afa7835479e00fa346241cfccd10b6e60a80 100644 (file)
@@ -6437,6 +6437,7 @@ noinline int can_nocow_extent(struct inode *inode, u64 offset, u64 *len,
 
        if (btrfs_extent_readonly(root, disk_bytenr))
                goto out;
+       btrfs_release_path(path);
 
        /*
         * look for other files referencing this extent, if we
index 4d7433534f5cd77b7f9b240fba57ac7923df07e6..6024877335caf2a9dfa6af1018c5da19b0e8a2ae 100644 (file)
@@ -1005,9 +1005,19 @@ grow_dev_page(struct block_device *bdev, sector_t block,
        struct buffer_head *bh;
        sector_t end_block;
        int ret = 0;            /* Will call free_more_memory() */
+       gfp_t gfp_mask;
 
-       page = find_or_create_page(inode->i_mapping, index,
-               (mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS)|__GFP_MOVABLE);
+       gfp_mask = mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS;
+       gfp_mask |= __GFP_MOVABLE;
+       /*
+        * XXX: __getblk_slow() can not really deal with failure and
+        * will endlessly loop on improvised global reclaim.  Prefer
+        * looping in the allocator rather than here, at least that
+        * code knows what it's doing.
+        */
+       gfp_mask |= __GFP_NOFAIL;
+
+       page = find_or_create_page(inode->i_mapping, index, gfp_mask);
        if (!page)
                return ret;
 
index a16b4e58bcc62ee88f9772f75120ef250d0112bd..77fc5e181077b1f897cf27d40c140133b6cf6d0f 100644 (file)
@@ -120,14 +120,16 @@ cifs_read_super(struct super_block *sb)
 {
        struct inode *inode;
        struct cifs_sb_info *cifs_sb;
+       struct cifs_tcon *tcon;
        int rc = 0;
 
        cifs_sb = CIFS_SB(sb);
+       tcon = cifs_sb_master_tcon(cifs_sb);
 
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIXACL)
                sb->s_flags |= MS_POSIXACL;
 
-       if (cifs_sb_master_tcon(cifs_sb)->ses->capabilities & CAP_LARGE_FILES)
+       if (tcon->ses->capabilities & tcon->ses->server->vals->cap_large_files)
                sb->s_maxbytes = MAX_LFS_FILESIZE;
        else
                sb->s_maxbytes = MAX_NON_LFS;
@@ -147,7 +149,7 @@ cifs_read_super(struct super_block *sb)
                goto out_no_root;
        }
 
-       if (cifs_sb_master_tcon(cifs_sb)->nocase)
+       if (tcon->nocase)
                sb->s_d_op = &cifs_ci_dentry_ops;
        else
                sb->s_d_op = &cifs_dentry_ops;
index a630475e421c421ef38f6633ddb31c8351827752..08f9dfb1a894402eec24579717f6c48d4d92f695 100644 (file)
@@ -1491,15 +1491,30 @@ struct file_notify_information {
        __u8  FileName[0];
 } __attribute__((packed));
 
-struct reparse_data {
-       __u32   ReparseTag;
-       __u16   ReparseDataLength;
+/* For IO_REPARSE_TAG_SYMLINK */
+struct reparse_symlink_data {
+       __le32  ReparseTag;
+       __le16  ReparseDataLength;
        __u16   Reserved;
-       __u16   SubstituteNameOffset;
-       __u16   SubstituteNameLength;
-       __u16   PrintNameOffset;
-       __u16   PrintNameLength;
-       __u32   Flags;
+       __le16  SubstituteNameOffset;
+       __le16  SubstituteNameLength;
+       __le16  PrintNameOffset;
+       __le16  PrintNameLength;
+       __le32  Flags;
+       char    PathBuffer[0];
+} __attribute__((packed));
+
+/* For IO_REPARSE_TAG_NFS */
+#define NFS_SPECFILE_LNK       0x00000000014B4E4C
+#define NFS_SPECFILE_CHR       0x0000000000524843
+#define NFS_SPECFILE_BLK       0x00000000004B4C42
+#define NFS_SPECFILE_FIFO      0x000000004F464946
+#define NFS_SPECFILE_SOCK      0x000000004B434F53
+struct reparse_posix_data {
+       __le32  ReparseTag;
+       __le16  ReparseDataLength;
+       __u16   Reserved;
+       __le64  InodeType; /* LNK, FIFO, CHR etc. */
        char    PathBuffer[0];
 } __attribute__((packed));
 
index 4baf35949b51a16a395a698f40b66dd312a14246..ccd31ab815d4b2404d58a0e42f3ad606d35b87f5 100644 (file)
@@ -3088,7 +3088,8 @@ CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
        bool is_unicode;
        unsigned int sub_len;
        char *sub_start;
-       struct reparse_data *reparse_buf;
+       struct reparse_symlink_data *reparse_buf;
+       struct reparse_posix_data *posix_buf;
        __u32 data_offset, data_count;
        char *end_of_smb;
 
@@ -3137,20 +3138,47 @@ CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
                goto qreparse_out;
        }
        end_of_smb = 2 + get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
-       reparse_buf = (struct reparse_data *)
+       reparse_buf = (struct reparse_symlink_data *)
                                ((char *)&pSMBr->hdr.Protocol + data_offset);
        if ((char *)reparse_buf >= end_of_smb) {
                rc = -EIO;
                goto qreparse_out;
        }
-       if ((reparse_buf->PathBuffer + reparse_buf->PrintNameOffset +
-                               reparse_buf->PrintNameLength) > end_of_smb) {
+       if (reparse_buf->ReparseTag == cpu_to_le32(IO_REPARSE_TAG_NFS)) {
+               cifs_dbg(FYI, "NFS style reparse tag\n");
+               posix_buf =  (struct reparse_posix_data *)reparse_buf;
+
+               if (posix_buf->InodeType != cpu_to_le64(NFS_SPECFILE_LNK)) {
+                       cifs_dbg(FYI, "unsupported file type 0x%llx\n",
+                                le64_to_cpu(posix_buf->InodeType));
+                       rc = -EOPNOTSUPP;
+                       goto qreparse_out;
+               }
+               is_unicode = true;
+               sub_len = le16_to_cpu(reparse_buf->ReparseDataLength);
+               if (posix_buf->PathBuffer + sub_len > end_of_smb) {
+                       cifs_dbg(FYI, "reparse buf beyond SMB\n");
+                       rc = -EIO;
+                       goto qreparse_out;
+               }
+               *symlinkinfo = cifs_strndup_from_utf16(posix_buf->PathBuffer,
+                               sub_len, is_unicode, nls_codepage);
+               goto qreparse_out;
+       } else if (reparse_buf->ReparseTag !=
+                       cpu_to_le32(IO_REPARSE_TAG_SYMLINK)) {
+               rc = -EOPNOTSUPP;
+               goto qreparse_out;
+       }
+
+       /* Reparse tag is NTFS symlink */
+       sub_start = le16_to_cpu(reparse_buf->SubstituteNameOffset) +
+                               reparse_buf->PathBuffer;
+       sub_len = le16_to_cpu(reparse_buf->SubstituteNameLength);
+       if (sub_start + sub_len > end_of_smb) {
                cifs_dbg(FYI, "reparse buf beyond SMB\n");
                rc = -EIO;
                goto qreparse_out;
        }
-       sub_start = reparse_buf->SubstituteNameOffset + reparse_buf->PathBuffer;
-       sub_len = reparse_buf->SubstituteNameLength;
        if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
                is_unicode = true;
        else
index af847e1cf1c1985f5ddadd07e10dbc0e38a162a2..651a5279607b968a255a528e5411e4f4b39ca438 100644 (file)
@@ -780,7 +780,9 @@ static const struct {
        ERRDOS, ERRnoaccess, 0xc0000290}, {
        ERRDOS, ERRbadfunc, 0xc000029c}, {
        ERRDOS, ERRsymlink, NT_STATUS_STOPPED_ON_SYMLINK}, {
-       ERRDOS, ERRinvlevel, 0x007c0001}, };
+       ERRDOS, ERRinvlevel, 0x007c0001}, {
+       0, 0, 0 }
+};
 
 /*****************************************************************************
  Print an error message from the status code
index 352358de1d7e37a8126d61d76898112393f64d08..e87387dbf39fa1d24b19f245e86da4c907b0fdaf 100644 (file)
@@ -500,9 +500,9 @@ select_sectype(struct TCP_Server_Info *server, enum securityEnum requested)
                                return NTLMv2;
                        if (global_secflags & CIFSSEC_MAY_NTLM)
                                return NTLM;
-                       /* Fallthrough */
                default:
-                       return Unspecified;
+                       /* Fallthrough to attempt LANMAN authentication next */
+                       break;
                }
        case CIFS_NEGFLAVOR_LANMAN:
                switch (requested) {
index eba0efde66d70ae15974eef74b10ff6d83ca44d8..edccb5252462b6b465d3d71cb7d3de20e8d2be9a 100644 (file)
@@ -687,6 +687,10 @@ SMB2_logoff(const unsigned int xid, struct cifs_ses *ses)
        else
                return -EIO;
 
+       /* no need to send SMB logoff if uid already closed due to reconnect */
+       if (ses->need_reconnect)
+               goto smb2_session_already_dead;
+
        rc = small_smb2_init(SMB2_LOGOFF, NULL, (void **) &req);
        if (rc)
                return rc;
@@ -701,6 +705,8 @@ SMB2_logoff(const unsigned int xid, struct cifs_ses *ses)
         * No tcon so can't do
         * cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]);
         */
+
+smb2_session_already_dead:
        return rc;
 }
 
index d952ee48f4dcc629a5d1e91c3470cbd2bd6d1aec..a4b2391fe66e4e11cea93e7396b987c335d43823 100644 (file)
 #define FSCTL_QUERY_NETWORK_INTERFACE_INFO 0x001401FC /* BB add struct */
 #define FSCTL_SRV_READ_HASH          0x001441BB /* BB add struct */
 
+/* See FSCC 2.1.2.5 */
 #define IO_REPARSE_TAG_MOUNT_POINT   0xA0000003
 #define IO_REPARSE_TAG_HSM           0xC0000004
 #define IO_REPARSE_TAG_SIS           0x80000007
+#define IO_REPARSE_TAG_HSM2          0x80000006
+#define IO_REPARSE_TAG_DRIVER_EXTENDER 0x80000005
+/* Used by the DFS filter. See MS-DFSC */
+#define IO_REPARSE_TAG_DFS           0x8000000A
+/* Used by the DFS filter See MS-DFSC */
+#define IO_REPARSE_TAG_DFSR          0x80000012
+#define IO_REPARSE_TAG_FILTER_MANAGER 0x8000000B
+/* See section MS-FSCC 2.1.2.4 */
+#define IO_REPARSE_TAG_SYMLINK       0xA000000C
+#define IO_REPARSE_TAG_DEDUP         0x80000013
+#define IO_REPARSE_APPXSTREAM       0xC0000014
+/* NFS symlinks, Win 8/SMB3 and later */
+#define IO_REPARSE_TAG_NFS           0x80000014
 
 /* fsctl flags */
 /* If Flags is set to this value, the request is an FSCTL not ioctl request */
index 6fdcb1b4a106747779ae77ed365116256e79edec..800b938e4061768f5f55ee414b45afa56e6d6aa2 100644 (file)
@@ -410,8 +410,13 @@ static int
 wait_for_free_request(struct TCP_Server_Info *server, const int timeout,
                      const int optype)
 {
-       return wait_for_free_credits(server, timeout,
-                               server->ops->get_credits_field(server, optype));
+       int *val;
+
+       val = server->ops->get_credits_field(server, optype);
+       /* Since an echo is already inflight, no need to wait to send another */
+       if (*val <= 0 && optype == CIFS_ECHO_OP)
+               return -EAGAIN;
+       return wait_for_free_credits(server, timeout, val);
 }
 
 static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf,
index 1194b1f0f8396c934ab6a382deadab6c0a6c4c2f..f8cde46de9cd77c3047182e94164bdfdac4a317d 100644 (file)
@@ -1783,7 +1783,7 @@ retry:
                d_tmpfile(dentry, inode);
                err = ext3_orphan_add(handle, inode);
                if (err)
-                       goto err_drop_inode;
+                       goto err_unlock_inode;
                mark_inode_dirty(inode);
                unlock_new_inode(inode);
        }
@@ -1791,10 +1791,9 @@ retry:
        if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries))
                goto retry;
        return err;
-err_drop_inode:
+err_unlock_inode:
        ext3_journal_stop(handle);
        unlock_new_inode(inode);
-       iput(inode);
        return err;
 }
 
index 1bec5a5c1e45a29e9ead318987ec03d803104c5a..5a0408d7b1147094c3e82b6d11750b33396b7732 100644 (file)
@@ -2319,7 +2319,7 @@ retry:
                d_tmpfile(dentry, inode);
                err = ext4_orphan_add(handle, inode);
                if (err)
-                       goto err_drop_inode;
+                       goto err_unlock_inode;
                mark_inode_dirty(inode);
                unlock_new_inode(inode);
        }
@@ -2328,10 +2328,9 @@ retry:
        if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries))
                goto retry;
        return err;
-err_drop_inode:
+err_unlock_inode:
        ext4_journal_stop(handle);
        unlock_new_inode(inode);
-       iput(inode);
        return err;
 }
 
index 9f8ef9b7674db1ca1004b682b40a6e5500dcfc24..8eaa1ba793fc188879d405e768a81aedbaa4bf76 100644 (file)
@@ -288,10 +288,14 @@ static int proc_reg_mmap(struct file *file, struct vm_area_struct *vma)
 static unsigned long proc_reg_get_unmapped_area(struct file *file, unsigned long orig_addr, unsigned long len, unsigned long pgoff, unsigned long flags)
 {
        struct proc_dir_entry *pde = PDE(file_inode(file));
-       int rv = -EIO;
-       unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
+       unsigned long rv = -EIO;
+       unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long) = NULL;
        if (use_pde(pde)) {
-               get_unmapped_area = pde->proc_fops->get_unmapped_area;
+#ifdef CONFIG_MMU
+               get_unmapped_area = current->mm->get_unmapped_area;
+#endif
+               if (pde->proc_fops->get_unmapped_area)
+                       get_unmapped_area = pde->proc_fops->get_unmapped_area;
                if (get_unmapped_area)
                        rv = get_unmapped_area(file, orig_addr, len, pgoff, flags);
                unuse_pde(pde);
index 7366e9d63cee7d8658e9fed949a2fe7b22519c6f..390bdab01c3c782cc14b55c6d1ef35ebddcc4197 100644 (file)
@@ -941,6 +941,8 @@ static void pte_to_pagemap_entry(pagemap_entry_t *pme, struct pagemapread *pm,
                frame = pte_pfn(pte);
                flags = PM_PRESENT;
                page = vm_normal_page(vma, addr, pte);
+               if (pte_soft_dirty(pte))
+                       flags2 |= __PM_SOFT_DIRTY;
        } else if (is_swap_pte(pte)) {
                swp_entry_t entry;
                if (pte_swp_soft_dirty(pte))
@@ -960,7 +962,7 @@ static void pte_to_pagemap_entry(pagemap_entry_t *pme, struct pagemapread *pm,
 
        if (page && !PageAnon(page))
                flags |= PM_FILE;
-       if ((vma->vm_flags & VM_SOFTDIRTY) || pte_soft_dirty(pte))
+       if ((vma->vm_flags & VM_SOFTDIRTY))
                flags2 |= __PM_SOFT_DIRTY;
 
        *pme = make_pme(PM_PFRAME(frame) | PM_STATUS2(pm->v2, flags2) | flags);
index 02e113bb8b7d5c777fdc435a5285208238ce66e9..d9019821aa6020e1c6d974856edfb404cb81d8c8 100644 (file)
@@ -311,7 +311,6 @@ struct acpi_device {
        unsigned int physical_node_count;
        struct list_head physical_node_list;
        struct mutex physical_node_lock;
-       struct list_head power_dependent;
        void (*remove)(struct acpi_device *);
 };
 
@@ -456,8 +455,6 @@ acpi_status acpi_add_pm_notifier(struct acpi_device *adev,
 acpi_status acpi_remove_pm_notifier(struct acpi_device *adev,
                                    acpi_notify_handler handler);
 int acpi_pm_device_sleep_state(struct device *, int *, int);
-void acpi_dev_pm_add_dependent(acpi_handle handle, struct device *depdev);
-void acpi_dev_pm_remove_dependent(acpi_handle handle, struct device *depdev);
 #else
 static inline acpi_status acpi_add_pm_notifier(struct acpi_device *adev,
                                               acpi_notify_handler handler,
@@ -478,10 +475,6 @@ static inline int acpi_pm_device_sleep_state(struct device *d, int *p, int m)
        return (m >= ACPI_STATE_D0 && m <= ACPI_STATE_D3_COLD) ?
                m : ACPI_STATE_D0;
 }
-static inline void acpi_dev_pm_add_dependent(acpi_handle handle,
-                                            struct device *depdev) {}
-static inline void acpi_dev_pm_remove_dependent(acpi_handle handle,
-                                               struct device *depdev) {}
 #endif
 
 #ifdef CONFIG_PM_RUNTIME
index ecc82b37c4ccf00fb863ecf6981de19bbccec52a..b3e7a667e03c24ca5c3d1c54c0db5c7b0bdde052 100644 (file)
@@ -137,47 +137,24 @@ extern void mem_cgroup_print_oom_info(struct mem_cgroup *memcg,
 extern void mem_cgroup_replace_page_cache(struct page *oldpage,
                                        struct page *newpage);
 
-/**
- * mem_cgroup_toggle_oom - toggle the memcg OOM killer for the current task
- * @new: true to enable, false to disable
- *
- * Toggle whether a failed memcg charge should invoke the OOM killer
- * or just return -ENOMEM.  Returns the previous toggle state.
- *
- * NOTE: Any path that enables the OOM killer before charging must
- *       call mem_cgroup_oom_synchronize() afterward to finalize the
- *       OOM handling and clean up.
- */
-static inline bool mem_cgroup_toggle_oom(bool new)
+static inline void mem_cgroup_oom_enable(void)
 {
-       bool old;
-
-       old = current->memcg_oom.may_oom;
-       current->memcg_oom.may_oom = new;
-
-       return old;
+       WARN_ON(current->memcg_oom.may_oom);
+       current->memcg_oom.may_oom = 1;
 }
 
-static inline void mem_cgroup_enable_oom(void)
+static inline void mem_cgroup_oom_disable(void)
 {
-       bool old = mem_cgroup_toggle_oom(true);
-
-       WARN_ON(old == true);
-}
-
-static inline void mem_cgroup_disable_oom(void)
-{
-       bool old = mem_cgroup_toggle_oom(false);
-
-       WARN_ON(old == false);
+       WARN_ON(!current->memcg_oom.may_oom);
+       current->memcg_oom.may_oom = 0;
 }
 
 static inline bool task_in_memcg_oom(struct task_struct *p)
 {
-       return p->memcg_oom.in_memcg_oom;
+       return p->memcg_oom.memcg;
 }
 
-bool mem_cgroup_oom_synchronize(void);
+bool mem_cgroup_oom_synchronize(bool wait);
 
 #ifdef CONFIG_MEMCG_SWAP
 extern int do_swap_account;
@@ -402,16 +379,11 @@ static inline void mem_cgroup_end_update_page_stat(struct page *page,
 {
 }
 
-static inline bool mem_cgroup_toggle_oom(bool new)
-{
-       return false;
-}
-
-static inline void mem_cgroup_enable_oom(void)
+static inline void mem_cgroup_oom_enable(void)
 {
 }
 
-static inline void mem_cgroup_disable_oom(void)
+static inline void mem_cgroup_oom_disable(void)
 {
 }
 
@@ -420,7 +392,7 @@ static inline bool task_in_memcg_oom(struct task_struct *p)
        return false;
 }
 
-static inline bool mem_cgroup_oom_synchronize(void)
+static inline bool mem_cgroup_oom_synchronize(bool wait)
 {
        return false;
 }
index cebe97ee98b86e1d6f6ef478ddf84693d8486d6b..7314fc4e6d2503b0e5e885c7ceccf0a873207ec0 100644 (file)
@@ -59,6 +59,12 @@ struct mfd_cell {
         * pm_runtime_no_callbacks().
         */
        bool                    pm_runtime_no_callbacks;
+
+       /* A list of regulator supplies that should be mapped to the MFD
+        * device rather than the child device when requested
+        */
+       const char              **parent_supplies;
+       int                     num_parent_supplies;
 };
 
 /*
index 68029b30c3dc89e2d2620fd41101b2ab05069344..5eb4e31af22b8e05356dfef793c1b96497af8cb3 100644 (file)
@@ -181,7 +181,7 @@ enum {
        MLX5_DEV_CAP_FLAG_TLP_HINTS     = 1LL << 39,
        MLX5_DEV_CAP_FLAG_SIG_HAND_OVER = 1LL << 40,
        MLX5_DEV_CAP_FLAG_DCT           = 1LL << 41,
-       MLX5_DEV_CAP_FLAG_CMDIF_CSUM    = 1LL << 46,
+       MLX5_DEV_CAP_FLAG_CMDIF_CSUM    = 3LL << 46,
 };
 
 enum {
@@ -417,7 +417,7 @@ struct mlx5_init_seg {
        struct health_buffer    health;
        __be32                  rsvd2[884];
        __be32                  health_counter;
-       __be32                  rsvd3[1023];
+       __be32                  rsvd3[1019];
        __be64                  ieee1588_clk;
        __be32                  ieee1588_clk_type;
        __be32                  clr_intx;
index 8888381fc150b8f3f852077407ee8187a54cb7aa..6b8c496572c841d8ec8be70740557f1caf50b79a 100644 (file)
@@ -82,7 +82,7 @@ enum {
 };
 
 enum {
-       MLX5_MAX_EQ_NAME        = 20
+       MLX5_MAX_EQ_NAME        = 32
 };
 
 enum {
@@ -747,8 +747,7 @@ static inline u32 mlx5_idx_to_mkey(u32 mkey_idx)
 
 enum {
        MLX5_PROF_MASK_QP_SIZE          = (u64)1 << 0,
-       MLX5_PROF_MASK_CMDIF_CSUM       = (u64)1 << 1,
-       MLX5_PROF_MASK_MR_CACHE         = (u64)1 << 2,
+       MLX5_PROF_MASK_MR_CACHE         = (u64)1 << 1,
 };
 
 enum {
@@ -758,7 +757,6 @@ enum {
 struct mlx5_profile {
        u64     mask;
        u32     log_max_qp;
-       int     cmdif_csum;
        struct {
                int     size;
                int     limit;
diff --git a/include/linux/of_reserved_mem.h b/include/linux/of_reserved_mem.h
deleted file mode 100644 (file)
index c841282..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef __OF_RESERVED_MEM_H
-#define __OF_RESERVED_MEM_H
-
-#ifdef CONFIG_OF_RESERVED_MEM
-void of_reserved_mem_device_init(struct device *dev);
-void of_reserved_mem_device_release(struct device *dev);
-void early_init_dt_scan_reserved_mem(void);
-#else
-static inline void of_reserved_mem_device_init(struct device *dev) { }
-static inline void of_reserved_mem_device_release(struct device *dev) { }
-static inline void early_init_dt_scan_reserved_mem(void) { }
-#endif
-
-#endif /* __OF_RESERVED_MEM_H */
index 27be915caa96465ebfe7068a3af499e976a0ddc1..e530681bea7049cfa818e66acea0bf863952d281 100644 (file)
@@ -146,6 +146,32 @@ struct regulator *__must_check devm_regulator_get_optional(struct device *dev,
 void regulator_put(struct regulator *regulator);
 void devm_regulator_put(struct regulator *regulator);
 
+int regulator_register_supply_alias(struct device *dev, const char *id,
+                                   struct device *alias_dev,
+                                   const char *alias_id);
+void regulator_unregister_supply_alias(struct device *dev, const char *id);
+
+int regulator_bulk_register_supply_alias(struct device *dev, const char **id,
+                                        struct device *alias_dev,
+                                        const char **alias_id, int num_id);
+void regulator_bulk_unregister_supply_alias(struct device *dev,
+                                           const char **id, int num_id);
+
+int devm_regulator_register_supply_alias(struct device *dev, const char *id,
+                                        struct device *alias_dev,
+                                        const char *alias_id);
+void devm_regulator_unregister_supply_alias(struct device *dev,
+                                           const char *id);
+
+int devm_regulator_bulk_register_supply_alias(struct device *dev,
+                                             const char **id,
+                                             struct device *alias_dev,
+                                             const char **alias_id,
+                                             int num_id);
+void devm_regulator_bulk_unregister_supply_alias(struct device *dev,
+                                                const char **id,
+                                                int num_id);
+
 /* regulator output control and status */
 int __must_check regulator_enable(struct regulator *regulator);
 int regulator_disable(struct regulator *regulator);
@@ -250,6 +276,59 @@ static inline void devm_regulator_put(struct regulator *regulator)
 {
 }
 
+static inline int regulator_register_supply_alias(struct device *dev,
+                                                 const char *id,
+                                                 struct device *alias_dev,
+                                                 const char *alias_id)
+{
+       return 0;
+}
+
+static inline void regulator_unregister_supply_alias(struct device *dev,
+                                                   const char *id)
+{
+}
+
+static inline int regulator_bulk_register_supply_alias(struct device *dev,
+                                                      const char **id,
+                                                      struct device *alias_dev,
+                                                      const char **alias_id,
+                                                      int num_id)
+{
+       return 0;
+}
+
+static inline void regulator_bulk_unregister_supply_alias(struct device *dev,
+                                                         const char **id,
+                                                         int num_id)
+{
+}
+
+static inline int devm_regulator_register_supply_alias(struct device *dev,
+                                                      const char *id,
+                                                      struct device *alias_dev,
+                                                      const char *alias_id)
+{
+       return 0;
+}
+
+static inline void devm_regulator_unregister_supply_alias(struct device *dev,
+                                                         const char *id)
+{
+}
+
+static inline int devm_regulator_bulk_register_supply_alias(
+               struct device *dev, const char **id, struct device *alias_dev,
+               const char **alias_id, int num_id)
+{
+       return 0;
+}
+
+static inline void devm_regulator_bulk_unregister_supply_alias(
+               struct device *dev, const char **id, int num_id)
+{
+}
+
 static inline int regulator_enable(struct regulator *regulator)
 {
        return 0;
index 9bdad43ad228a5501c2dc8b0e6cc77a6da8c7b30..9370e65348a40ba5a92620fbfe4cfed4305a3963 100644 (file)
@@ -46,19 +46,26 @@ enum regulator_status {
  * regulator_list_linear_range().
  *
  * @min_uV:  Lowest voltage in range
- * @max_uV:  Highest voltage in range
  * @min_sel: Lowest selector for range
  * @max_sel: Highest selector for range
  * @uV_step: Step size
  */
 struct regulator_linear_range {
        unsigned int min_uV;
-       unsigned int max_uV;
        unsigned int min_sel;
        unsigned int max_sel;
        unsigned int uV_step;
 };
 
+/* Initialize struct regulator_linear_range */
+#define REGULATOR_LINEAR_RANGE(_min_uV, _min_sel, _max_sel, _step_uV)  \
+{                                                                      \
+       .min_uV         = _min_uV,                                      \
+       .min_sel        = _min_sel,                                     \
+       .max_sel        = _max_sel,                                     \
+       .uV_step        = _step_uV,                                     \
+}
+
 /**
  * struct regulator_ops - regulator operations.
  *
@@ -209,6 +216,7 @@ enum regulator_type {
  * @min_uV: Voltage given by the lowest selector (if linear mapping)
  * @uV_step: Voltage increase with each selector (if linear mapping)
  * @linear_min_sel: Minimal selector for starting linear mapping
+ * @fixed_uV: Fixed voltage of rails.
  * @ramp_delay: Time to settle down after voltage change (unit: uV/us)
  * @volt_table: Voltage mapping table (if table based mapping)
  *
@@ -241,6 +249,7 @@ struct regulator_desc {
        unsigned int min_uV;
        unsigned int uV_step;
        unsigned int linear_min_sel;
+       int fixed_uV;
        unsigned int ramp_delay;
 
        const struct regulator_linear_range *linear_ranges;
@@ -336,7 +345,12 @@ struct regulator_dev {
 struct regulator_dev *
 regulator_register(const struct regulator_desc *regulator_desc,
                   const struct regulator_config *config);
+struct regulator_dev *
+devm_regulator_register(struct device *dev,
+                       const struct regulator_desc *regulator_desc,
+                       const struct regulator_config *config);
 void regulator_unregister(struct regulator_dev *rdev);
+void devm_regulator_unregister(struct device *dev, struct regulator_dev *rdev);
 
 int regulator_notifier_call_chain(struct regulator_dev *rdev,
                                  unsigned long event, void *data);
index 999b20ce06cf349185f008388e12e64c70518196..730e638c55899ba9bfff37a045386af5ee0f5cfe 100644 (file)
@@ -95,6 +95,7 @@ struct regulator_state {
  * @initial_state: Suspend state to set by default.
  * @initial_mode: Mode to set at startup.
  * @ramp_delay: Time to settle down after voltage change (unit: uV/us)
+ * @enable_time: Turn-on time of the rails (unit: microseconds)
  */
 struct regulation_constraints {
 
@@ -129,6 +130,7 @@ struct regulation_constraints {
        unsigned int initial_mode;
 
        unsigned int ramp_delay;
+       unsigned int enable_time;
 
        /* constraint flags */
        unsigned always_on:1;   /* regulator never off when system is on */
@@ -193,15 +195,10 @@ int regulator_suspend_finish(void);
 
 #ifdef CONFIG_REGULATOR
 void regulator_has_full_constraints(void);
-void regulator_use_dummy_regulator(void);
 #else
 static inline void regulator_has_full_constraints(void)
 {
 }
-
-static inline void regulator_use_dummy_regulator(void)
-{
-}
 #endif
 
 #endif
index 6682da36b293cfad598a0c5803e9e32038f72aa3..e27baeeda3f470ed99ae899d8de22da062856bf8 100644 (file)
@@ -1394,11 +1394,10 @@ struct task_struct {
        } memcg_batch;
        unsigned int memcg_kmem_skip_account;
        struct memcg_oom_info {
+               struct mem_cgroup *memcg;
+               gfp_t gfp_mask;
+               int order;
                unsigned int may_oom:1;
-               unsigned int in_memcg_oom:1;
-               unsigned int oom_locked:1;
-               int wakeups;
-               struct mem_cgroup *wait_on_memcg;
        } memcg_oom;
 #endif
 #ifdef CONFIG_UPROBES
index f9a7e7bc925be61322a24304076503bd918a520a..11d85b9c1b081af6a9f4f30ac3c1458766ed4238 100644 (file)
@@ -12,7 +12,7 @@ struct usb_phy_gen_xceiv_platform_data {
        unsigned int needs_reset:1;
 };
 
-#if IS_ENABLED(CONFIG_NOP_USB_XCEIV)
+#if defined(CONFIG_NOP_USB_XCEIV) || (defined(CONFIG_NOP_USB_XCEIV_MODULE) && defined(MODULE))
 /* sometimes transceivers are accessed only through e.g. ULPI */
 extern void usb_nop_xceiv_register(void);
 extern void usb_nop_xceiv_unregister(void);
index bf99cd01be206ebeb170d826e176c3ac22e1493e..630356866030d88a355390a932105ff9c86b98bb 100644 (file)
@@ -66,7 +66,9 @@
        US_FLAG(INITIAL_READ10, 0x00100000)                     \
                /* Initial READ(10) (and others) must be retried */     \
        US_FLAG(WRITE_CACHE,    0x00200000)                     \
-               /* Write Cache status is not available */
+               /* Write Cache status is not available */       \
+       US_FLAG(NEEDS_CAP16,    0x00400000)
+               /* cannot handle READ_CAPACITY_10 */
 
 #define US_FLAG(name, value)   US_FL_##name = value ,
 enum { US_DO_ALL_FLAGS };
index 8c4f59b0204a2821811a4b28fd48e0ce6163d987..db9d241af133d770cb0a95a22cacf257f79b1215 100644 (file)
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -1282,6 +1282,12 @@ static int semctl_setval(struct ipc_namespace *ns, int semid, int semnum,
 
        sem_lock(sma, NULL, -1);
 
+       if (sma->sem_perm.deleted) {
+               sem_unlock(sma, -1);
+               rcu_read_unlock();
+               return -EIDRM;
+       }
+
        curr = &sma->sem_base[semnum];
 
        ipc_assert_locked_object(&sma->sem_perm);
@@ -1336,12 +1342,14 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
                int i;
 
                sem_lock(sma, NULL, -1);
+               if (sma->sem_perm.deleted) {
+                       err = -EIDRM;
+                       goto out_unlock;
+               }
                if(nsems > SEMMSL_FAST) {
                        if (!ipc_rcu_getref(sma)) {
-                               sem_unlock(sma, -1);
-                               rcu_read_unlock();
                                err = -EIDRM;
-                               goto out_free;
+                               goto out_unlock;
                        }
                        sem_unlock(sma, -1);
                        rcu_read_unlock();
@@ -1354,10 +1362,8 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
                        rcu_read_lock();
                        sem_lock_and_putref(sma);
                        if (sma->sem_perm.deleted) {
-                               sem_unlock(sma, -1);
-                               rcu_read_unlock();
                                err = -EIDRM;
-                               goto out_free;
+                               goto out_unlock;
                        }
                }
                for (i = 0; i < sma->sem_nsems; i++)
@@ -1375,8 +1381,8 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
                struct sem_undo *un;
 
                if (!ipc_rcu_getref(sma)) {
-                       rcu_read_unlock();
-                       return -EIDRM;
+                       err = -EIDRM;
+                       goto out_rcu_wakeup;
                }
                rcu_read_unlock();
 
@@ -1404,10 +1410,8 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
                rcu_read_lock();
                sem_lock_and_putref(sma);
                if (sma->sem_perm.deleted) {
-                       sem_unlock(sma, -1);
-                       rcu_read_unlock();
                        err = -EIDRM;
-                       goto out_free;
+                       goto out_unlock;
                }
 
                for (i = 0; i < nsems; i++)
@@ -1431,6 +1435,10 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
                goto out_rcu_wakeup;
 
        sem_lock(sma, NULL, -1);
+       if (sma->sem_perm.deleted) {
+               err = -EIDRM;
+               goto out_unlock;
+       }
        curr = &sma->sem_base[semnum];
 
        switch (cmd) {
@@ -1836,6 +1844,10 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
        if (error)
                goto out_rcu_wakeup;
 
+       error = -EIDRM;
+       locknum = sem_lock(sma, sops, nsops);
+       if (sma->sem_perm.deleted)
+               goto out_unlock_free;
        /*
         * semid identifiers are not unique - find_alloc_undo may have
         * allocated an undo structure, it was invalidated by an RMID
@@ -1843,8 +1855,6 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
         * This case can be detected checking un->semid. The existence of
         * "un" itself is guaranteed by rcu.
         */
-       error = -EIDRM;
-       locknum = sem_lock(sma, sops, nsops);
        if (un && un->semid == -1)
                goto out_unlock_free;
 
@@ -2057,6 +2067,12 @@ void exit_sem(struct task_struct *tsk)
                }
 
                sem_lock(sma, NULL, -1);
+               /* exit_sem raced with IPC_RMID, nothing to do */
+               if (sma->sem_perm.deleted) {
+                       sem_unlock(sma, -1);
+                       rcu_read_unlock();
+                       continue;
+               }
                un = __lookup_undo(ulp, semid);
                if (un == NULL) {
                        /* exit_sem raced with IPC_RMID+semget() that created
index fdb8ae7407755f9b1c3725e2a7fd38a8a31c7f54..7684f41bce76a9b430f04b7e4e77810b48798a42 100644 (file)
  *            Pavel Emelianov <xemul@openvz.org>
  *
  * General sysv ipc locking scheme:
- *  when doing ipc id lookups, take the ids->rwsem
- *      rcu_read_lock()
- *          obtain the ipc object (kern_ipc_perm)
- *          perform security, capabilities, auditing and permission checks, etc.
- *          acquire the ipc lock (kern_ipc_perm.lock) throught ipc_lock_object()
- *             perform data updates (ie: SET, RMID, LOCK/UNLOCK commands)
+ *     rcu_read_lock()
+ *          obtain the ipc object (kern_ipc_perm) by looking up the id in an idr
+ *         tree.
+ *         - perform initial checks (capabilities, auditing and permission,
+ *           etc).
+ *         - perform read-only operations, such as STAT, INFO commands.
+ *           acquire the ipc lock (kern_ipc_perm.lock) through
+ *           ipc_lock_object()
+ *             - perform data updates, such as SET, RMID commands and
+ *               mechanism-specific operations (semop/semtimedop,
+ *               msgsnd/msgrcv, shmat/shmdt).
+ *         drop the ipc lock, through ipc_unlock_object().
+ *     rcu_read_unlock()
+ *
+ *  The ids->rwsem must be taken when:
+ *     - creating, removing and iterating the existing entries in ipc
+ *       identifier sets.
+ *     - iterating through files under /proc/sysvipc/
+ *
+ *  Note that sems have a special fast path that avoids kern_ipc_perm.lock -
+ *  see sem_lock().
  */
 
 #include <linux/mm.h>
index 7deeb6297a483d7272acb30c4f3b0c0d6b0e76b3..1a53d497a8c53ae460686af6107531c4161eae53 100644 (file)
@@ -53,6 +53,7 @@ int percpu_ref_init(struct percpu_ref *ref, percpu_ref_func_t *release)
        ref->release = release;
        return 0;
 }
+EXPORT_SYMBOL_GPL(percpu_ref_init);
 
 /**
  * percpu_ref_cancel_init - cancel percpu_ref_init()
@@ -84,6 +85,7 @@ void percpu_ref_cancel_init(struct percpu_ref *ref)
                free_percpu(ref->pcpu_count);
        }
 }
+EXPORT_SYMBOL_GPL(percpu_ref_cancel_init);
 
 static void percpu_ref_kill_rcu(struct rcu_head *rcu)
 {
@@ -156,3 +158,4 @@ void percpu_ref_kill_and_confirm(struct percpu_ref *ref,
 
        call_rcu_sched(&ref->rcu, percpu_ref_kill_rcu);
 }
+EXPORT_SYMBOL_GPL(percpu_ref_kill_and_confirm);
index 1e6aec4a2d2ebae29c0fea0405a7e81f422beeb4..ae4846ff48494e9ac5e733a5d5339b61763a49f5 100644 (file)
@@ -1616,7 +1616,6 @@ int filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
        struct inode *inode = mapping->host;
        pgoff_t offset = vmf->pgoff;
        struct page *page;
-       bool memcg_oom;
        pgoff_t size;
        int ret = 0;
 
@@ -1625,11 +1624,7 @@ int filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
                return VM_FAULT_SIGBUS;
 
        /*
-        * Do we have something in the page cache already?  Either
-        * way, try readahead, but disable the memcg OOM killer for it
-        * as readahead is optional and no errors are propagated up
-        * the fault stack.  The OOM killer is enabled while trying to
-        * instantiate the faulting page individually below.
+        * Do we have something in the page cache already?
         */
        page = find_get_page(mapping, offset);
        if (likely(page) && !(vmf->flags & FAULT_FLAG_TRIED)) {
@@ -1637,14 +1632,10 @@ int filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
                 * We found the page, so try async readahead before
                 * waiting for the lock.
                 */
-               memcg_oom = mem_cgroup_toggle_oom(false);
                do_async_mmap_readahead(vma, ra, file, page, offset);
-               mem_cgroup_toggle_oom(memcg_oom);
        } else if (!page) {
                /* No page in the page cache at all */
-               memcg_oom = mem_cgroup_toggle_oom(false);
                do_sync_mmap_readahead(vma, ra, file, offset);
-               mem_cgroup_toggle_oom(memcg_oom);
                count_vm_event(PGMAJFAULT);
                mem_cgroup_count_vm_event(vma->vm_mm, PGMAJFAULT);
                ret = VM_FAULT_MAJOR;
index 7489884682d84a6b5840fef19e90234076fd374e..610e3df2768a6a5b2ec1e293da4c96dafbbe2d30 100644 (file)
@@ -2697,6 +2697,7 @@ void __split_huge_page_pmd(struct vm_area_struct *vma, unsigned long address,
 
        mmun_start = haddr;
        mmun_end   = haddr + HPAGE_PMD_SIZE;
+again:
        mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end);
        spin_lock(&mm->page_table_lock);
        if (unlikely(!pmd_trans_huge(*pmd))) {
@@ -2719,7 +2720,14 @@ void __split_huge_page_pmd(struct vm_area_struct *vma, unsigned long address,
        split_huge_page(page);
 
        put_page(page);
-       BUG_ON(pmd_trans_huge(*pmd));
+
+       /*
+        * We don't always have down_write of mmap_sem here: a racing
+        * do_huge_pmd_wp_page() might have copied-on-write to another
+        * huge page before our split_huge_page() got the anon_vma lock.
+        */
+       if (unlikely(pmd_trans_huge(*pmd)))
+               goto again;
 }
 
 void split_huge_page_pmd_mm(struct mm_struct *mm, unsigned long address,
index b49579c7f2a550462c334f97907f2fc131a65e00..0b7656e804d126cf0fcfa04a8b427396af86deb1 100644 (file)
@@ -653,6 +653,7 @@ static void free_huge_page(struct page *page)
        BUG_ON(page_count(page));
        BUG_ON(page_mapcount(page));
        restore_reserve = PagePrivate(page);
+       ClearPagePrivate(page);
 
        spin_lock(&hugetlb_lock);
        hugetlb_cgroup_uncharge_page(hstate_index(h),
@@ -695,8 +696,22 @@ static void prep_compound_gigantic_page(struct page *page, unsigned long order)
        /* we rely on prep_new_huge_page to set the destructor */
        set_compound_order(page, order);
        __SetPageHead(page);
+       __ClearPageReserved(page);
        for (i = 1; i < nr_pages; i++, p = mem_map_next(p, page, i)) {
                __SetPageTail(p);
+               /*
+                * For gigantic hugepages allocated through bootmem at
+                * boot, it's safer to be consistent with the not-gigantic
+                * hugepages and clear the PG_reserved bit from all tail pages
+                * too.  Otherwse drivers using get_user_pages() to access tail
+                * pages may get the reference counting wrong if they see
+                * PG_reserved set on a tail page (despite the head page not
+                * having PG_reserved set).  Enforcing this consistency between
+                * head and tail pages allows drivers to optimize away a check
+                * on the head page when they need know if put_page() is needed
+                * after get_user_pages().
+                */
+               __ClearPageReserved(p);
                set_page_count(p, 0);
                p->first_page = page;
        }
@@ -1329,9 +1344,9 @@ static void __init gather_bootmem_prealloc(void)
 #else
                page = virt_to_page(m);
 #endif
-               __ClearPageReserved(page);
                WARN_ON(page_count(page) != 1);
                prep_compound_huge_page(page, h->order);
+               WARN_ON(PageReserved(page));
                prep_new_huge_page(h, page, page_to_nid(page));
                /*
                 * If we had gigantic hugepages allocated at boot time, we need
index 1c52ddbc839ba1f8f42e940c51bc321ba6b2abfe..34d3ca9572d6baed85499d099a0050af3b9bdf66 100644 (file)
@@ -866,6 +866,7 @@ static unsigned long mem_cgroup_read_events(struct mem_cgroup *memcg,
        unsigned long val = 0;
        int cpu;
 
+       get_online_cpus();
        for_each_online_cpu(cpu)
                val += per_cpu(memcg->stat->events[idx], cpu);
 #ifdef CONFIG_HOTPLUG_CPU
@@ -873,6 +874,7 @@ static unsigned long mem_cgroup_read_events(struct mem_cgroup *memcg,
        val += memcg->nocpu_base.events[idx];
        spin_unlock(&memcg->pcp_counter_lock);
 #endif
+       put_online_cpus();
        return val;
 }
 
@@ -2159,110 +2161,59 @@ static void memcg_oom_recover(struct mem_cgroup *memcg)
                memcg_wakeup_oom(memcg);
 }
 
-/*
- * try to call OOM killer
- */
 static void mem_cgroup_oom(struct mem_cgroup *memcg, gfp_t mask, int order)
 {
-       bool locked;
-       int wakeups;
-
        if (!current->memcg_oom.may_oom)
                return;
-
-       current->memcg_oom.in_memcg_oom = 1;
-
        /*
-        * As with any blocking lock, a contender needs to start
-        * listening for wakeups before attempting the trylock,
-        * otherwise it can miss the wakeup from the unlock and sleep
-        * indefinitely.  This is just open-coded because our locking
-        * is so particular to memcg hierarchies.
+        * We are in the middle of the charge context here, so we
+        * don't want to block when potentially sitting on a callstack
+        * that holds all kinds of filesystem and mm locks.
+        *
+        * Also, the caller may handle a failed allocation gracefully
+        * (like optional page cache readahead) and so an OOM killer
+        * invocation might not even be necessary.
+        *
+        * That's why we don't do anything here except remember the
+        * OOM context and then deal with it at the end of the page
+        * fault when the stack is unwound, the locks are released,
+        * and when we know whether the fault was overall successful.
         */
-       wakeups = atomic_read(&memcg->oom_wakeups);
-       mem_cgroup_mark_under_oom(memcg);
-
-       locked = mem_cgroup_oom_trylock(memcg);
-
-       if (locked)
-               mem_cgroup_oom_notify(memcg);
-
-       if (locked && !memcg->oom_kill_disable) {
-               mem_cgroup_unmark_under_oom(memcg);
-               mem_cgroup_out_of_memory(memcg, mask, order);
-               mem_cgroup_oom_unlock(memcg);
-               /*
-                * There is no guarantee that an OOM-lock contender
-                * sees the wakeups triggered by the OOM kill
-                * uncharges.  Wake any sleepers explicitely.
-                */
-               memcg_oom_recover(memcg);
-       } else {
-               /*
-                * A system call can just return -ENOMEM, but if this
-                * is a page fault and somebody else is handling the
-                * OOM already, we need to sleep on the OOM waitqueue
-                * for this memcg until the situation is resolved.
-                * Which can take some time because it might be
-                * handled by a userspace task.
-                *
-                * However, this is the charge context, which means
-                * that we may sit on a large call stack and hold
-                * various filesystem locks, the mmap_sem etc. and we
-                * don't want the OOM handler to deadlock on them
-                * while we sit here and wait.  Store the current OOM
-                * context in the task_struct, then return -ENOMEM.
-                * At the end of the page fault handler, with the
-                * stack unwound, pagefault_out_of_memory() will check
-                * back with us by calling
-                * mem_cgroup_oom_synchronize(), possibly putting the
-                * task to sleep.
-                */
-               current->memcg_oom.oom_locked = locked;
-               current->memcg_oom.wakeups = wakeups;
-               css_get(&memcg->css);
-               current->memcg_oom.wait_on_memcg = memcg;
-       }
+       css_get(&memcg->css);
+       current->memcg_oom.memcg = memcg;
+       current->memcg_oom.gfp_mask = mask;
+       current->memcg_oom.order = order;
 }
 
 /**
  * mem_cgroup_oom_synchronize - complete memcg OOM handling
+ * @handle: actually kill/wait or just clean up the OOM state
  *
- * This has to be called at the end of a page fault if the the memcg
- * OOM handler was enabled and the fault is returning %VM_FAULT_OOM.
+ * This has to be called at the end of a page fault if the memcg OOM
+ * handler was enabled.
  *
- * Memcg supports userspace OOM handling, so failed allocations must
+ * Memcg supports userspace OOM handling where failed allocations must
  * sleep on a waitqueue until the userspace task resolves the
  * situation.  Sleeping directly in the charge context with all kinds
  * of locks held is not a good idea, instead we remember an OOM state
  * in the task and mem_cgroup_oom_synchronize() has to be called at
- * the end of the page fault to put the task to sleep and clean up the
- * OOM state.
+ * the end of the page fault to complete the OOM handling.
  *
  * Returns %true if an ongoing memcg OOM situation was detected and
- * finalized, %false otherwise.
+ * completed, %false otherwise.
  */
-bool mem_cgroup_oom_synchronize(void)
+bool mem_cgroup_oom_synchronize(bool handle)
 {
+       struct mem_cgroup *memcg = current->memcg_oom.memcg;
        struct oom_wait_info owait;
-       struct mem_cgroup *memcg;
+       bool locked;
 
        /* OOM is global, do not handle */
-       if (!current->memcg_oom.in_memcg_oom)
-               return false;
-
-       /*
-        * We invoked the OOM killer but there is a chance that a kill
-        * did not free up any charges.  Everybody else might already
-        * be sleeping, so restart the fault and keep the rampage
-        * going until some charges are released.
-        */
-       memcg = current->memcg_oom.wait_on_memcg;
        if (!memcg)
-               goto out;
+               return false;
 
-       if (test_thread_flag(TIF_MEMDIE) || fatal_signal_pending(current))
-               goto out_memcg;
+       if (!handle)
+               goto cleanup;
 
        owait.memcg = memcg;
        owait.wait.flags = 0;
@@ -2271,13 +2222,25 @@ bool mem_cgroup_oom_synchronize(void)
        INIT_LIST_HEAD(&owait.wait.task_list);
 
        prepare_to_wait(&memcg_oom_waitq, &owait.wait, TASK_KILLABLE);
-       /* Only sleep if we didn't miss any wakeups since OOM */
-       if (atomic_read(&memcg->oom_wakeups) == current->memcg_oom.wakeups)
+       mem_cgroup_mark_under_oom(memcg);
+
+       locked = mem_cgroup_oom_trylock(memcg);
+
+       if (locked)
+               mem_cgroup_oom_notify(memcg);
+
+       if (locked && !memcg->oom_kill_disable) {
+               mem_cgroup_unmark_under_oom(memcg);
+               finish_wait(&memcg_oom_waitq, &owait.wait);
+               mem_cgroup_out_of_memory(memcg, current->memcg_oom.gfp_mask,
+                                        current->memcg_oom.order);
+       } else {
                schedule();
-       finish_wait(&memcg_oom_waitq, &owait.wait);
-out_memcg:
-       mem_cgroup_unmark_under_oom(memcg);
-       if (current->memcg_oom.oom_locked) {
+               mem_cgroup_unmark_under_oom(memcg);
+               finish_wait(&memcg_oom_waitq, &owait.wait);
+       }
+
+       if (locked) {
                mem_cgroup_oom_unlock(memcg);
                /*
                 * There is no guarantee that an OOM-lock contender
@@ -2286,10 +2249,9 @@ out_memcg:
                 */
                memcg_oom_recover(memcg);
        }
+cleanup:
+       current->memcg_oom.memcg = NULL;
        css_put(&memcg->css);
-       current->memcg_oom.wait_on_memcg = NULL;
-out:
-       current->memcg_oom.in_memcg_oom = 0;
        return true;
 }
 
@@ -2703,6 +2665,9 @@ static int __mem_cgroup_try_charge(struct mm_struct *mm,
                     || fatal_signal_pending(current)))
                goto bypass;
 
+       if (unlikely(task_in_memcg_oom(current)))
+               goto bypass;
+
        /*
         * We always charge the cgroup the mm_struct belongs to.
         * The mm_struct's mem_cgroup changes on task migration if the
@@ -2801,6 +2766,8 @@ done:
        return 0;
 nomem:
        *ptr = NULL;
+       if (gfp_mask & __GFP_NOFAIL)
+               return 0;
        return -ENOMEM;
 bypass:
        *ptr = root_mem_cgroup;
index ca00039471152eae75bb8321a129a4edfc6f580e..1311f26497e6a0f776682ed8a7e23b8620a5b9ad 100644 (file)
@@ -837,6 +837,8 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm,
                                         */
                                        make_migration_entry_read(&entry);
                                        pte = swp_entry_to_pte(entry);
+                                       if (pte_swp_soft_dirty(*src_pte))
+                                               pte = pte_swp_mksoft_dirty(pte);
                                        set_pte_at(src_mm, addr, src_pte, pte);
                                }
                        }
@@ -3863,15 +3865,21 @@ int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma,
         * space.  Kernel faults are handled more gracefully.
         */
        if (flags & FAULT_FLAG_USER)
-               mem_cgroup_enable_oom();
+               mem_cgroup_oom_enable();
 
        ret = __handle_mm_fault(mm, vma, address, flags);
 
-       if (flags & FAULT_FLAG_USER)
-               mem_cgroup_disable_oom();
-
-       if (WARN_ON(task_in_memcg_oom(current) && !(ret & VM_FAULT_OOM)))
-               mem_cgroup_oom_synchronize();
+       if (flags & FAULT_FLAG_USER) {
+               mem_cgroup_oom_disable();
+                /*
+                 * The task may have entered a memcg OOM situation but
+                 * if the allocation error was handled gracefully (no
+                 * VM_FAULT_OOM), there is no need to kill anything.
+                 * Just clean up the OOM state peacefully.
+                 */
+                if (task_in_memcg_oom(current) && !(ret & VM_FAULT_OOM))
+                        mem_cgroup_oom_synchronize(false);
+       }
 
        return ret;
 }
index a26bccd44ccb0a907662c08135399462bd816b9c..7a7325ee1d089696a8073a84d2f748f326124805 100644 (file)
@@ -161,6 +161,8 @@ static int remove_migration_pte(struct page *new, struct vm_area_struct *vma,
 
        get_page(new);
        pte = pte_mkold(mk_pte(new, vma->vm_page_prot));
+       if (pte_swp_soft_dirty(*ptep))
+               pte = pte_mksoft_dirty(pte);
        if (is_write_migration_entry(entry))
                pte = pte_mkwrite(pte);
 #ifdef CONFIG_HUGETLB_PAGE
index 94722a4d6b438311de1d1690d81a0d598a907339..a3af058f68e4d9f434337d0dcd6127d5d8c6d039 100644 (file)
@@ -94,13 +94,16 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
                        swp_entry_t entry = pte_to_swp_entry(oldpte);
 
                        if (is_write_migration_entry(entry)) {
+                               pte_t newpte;
                                /*
                                 * A protection check is difficult so
                                 * just be safe and disable write
                                 */
                                make_migration_entry_read(&entry);
-                               set_pte_at(mm, addr, pte,
-                                       swp_entry_to_pte(entry));
+                               newpte = swp_entry_to_pte(entry);
+                               if (pte_swp_soft_dirty(oldpte))
+                                       newpte = pte_swp_mksoft_dirty(newpte);
+                               set_pte_at(mm, addr, pte, newpte);
                        }
                        pages++;
                }
index 91b13d6a16d453b50894e6028800b92399bf8f14..0843feb66f3d0236abd4386b5bfd0170c24ae0ef 100644 (file)
@@ -25,7 +25,6 @@
 #include <asm/uaccess.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
-#include <asm/pgalloc.h>
 
 #include "internal.h"
 
@@ -63,10 +62,8 @@ static pmd_t *alloc_new_pmd(struct mm_struct *mm, struct vm_area_struct *vma,
                return NULL;
 
        pmd = pmd_alloc(mm, pud, addr);
-       if (!pmd) {
-               pud_free(mm, pud);
+       if (!pmd)
                return NULL;
-       }
 
        VM_BUG_ON(pmd_trans_huge(*pmd));
 
index 314e9d2743813ea5e52c08929b8a4cbb4621dfa9..6738c47f1f7280edc5f3fe610b2658195a0a77e0 100644 (file)
@@ -680,7 +680,7 @@ void pagefault_out_of_memory(void)
 {
        struct zonelist *zonelist;
 
-       if (mem_cgroup_oom_synchronize())
+       if (mem_cgroup_oom_synchronize(true))
                return;
 
        zonelist = node_zonelist(first_online_node, GFP_KERNEL);
index f5236f804aa6cdf9800f445c31950a52cdd6b88f..63807583d8e89f1c96f8b05bcf5fe422ed200c26 100644 (file)
@@ -1210,11 +1210,11 @@ static unsigned long dirty_poll_interval(unsigned long dirty,
        return 1;
 }
 
-static long bdi_max_pause(struct backing_dev_info *bdi,
-                         unsigned long bdi_dirty)
+static unsigned long bdi_max_pause(struct backing_dev_info *bdi,
+                                  unsigned long bdi_dirty)
 {
-       long bw = bdi->avg_write_bandwidth;
-       long t;
+       unsigned long bw = bdi->avg_write_bandwidth;
+       unsigned long t;
 
        /*
         * Limit pause time for small memory systems. If sleeping for too long
@@ -1226,7 +1226,7 @@ static long bdi_max_pause(struct backing_dev_info *bdi,
        t = bdi_dirty / (1 + bw / roundup_pow_of_two(1 + HZ / 8));
        t++;
 
-       return min_t(long, t, MAX_PAUSE);
+       return min_t(unsigned long, t, MAX_PAUSE);
 }
 
 static long bdi_min_pause(struct backing_dev_info *bdi,
index a3443278ce3a693b4c2625df3752a59e975abca3..e2e98af703ea9fdcbab4bcd034bc82a1482c9ca6 100644 (file)
@@ -56,6 +56,7 @@ static int kmem_cache_sanity_check(struct mem_cgroup *memcg, const char *name,
                        continue;
                }
 
+#if !defined(CONFIG_SLUB) || !defined(CONFIG_SLUB_DEBUG_ON)
                /*
                 * For simplicity, we won't check this in the list of memcg
                 * caches. We have control over memcg naming, and if there
@@ -69,6 +70,7 @@ static int kmem_cache_sanity_check(struct mem_cgroup *memcg, const char *name,
                        s = NULL;
                        return -EINVAL;
                }
+#endif
        }
 
        WARN_ON(strchr(name, ' '));     /* It confuses parsers */
index 3963fc24fcc1b6f8c4d365de4d99bda8993311b7..de7c904e52e507079f5bae7a2b7854a9d7cf80b0 100644 (file)
@@ -1824,6 +1824,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
        struct filename *pathname;
        int i, type, prev;
        int err;
+       unsigned int old_block_size;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
@@ -1914,6 +1915,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
        }
 
        swap_file = p->swap_file;
+       old_block_size = p->old_block_size;
        p->swap_file = NULL;
        p->max = 0;
        swap_map = p->swap_map;
@@ -1938,7 +1940,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
        inode = mapping->host;
        if (S_ISBLK(inode->i_mode)) {
                struct block_device *bdev = I_BDEV(inode);
-               set_blocksize(bdev, p->old_block_size);
+               set_blocksize(bdev, old_block_size);
                blkdev_put(bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
        } else {
                mutex_lock(&inode->i_mutex);
index 53f2f82f83ae0d16bf19646cdb5b3bce5fc4e4cf..eea668d9cff6c578ada0cf6c02eca5e22de5598d 100644 (file)
@@ -211,6 +211,7 @@ void unregister_shrinker(struct shrinker *shrinker)
        down_write(&shrinker_rwsem);
        list_del(&shrinker->list);
        up_write(&shrinker_rwsem);
+       kfree(shrinker->nr_deferred);
 }
 EXPORT_SYMBOL(unregister_shrinker);
 
index 841e35f1db22caff3afd03c104403f0c744776cb..d93510c6aa2da860d779570cbf0a4c7cee278ad5 100644 (file)
@@ -804,6 +804,10 @@ static void zswap_frontswap_invalidate_area(unsigned type)
        }
        tree->rbroot = RB_ROOT;
        spin_unlock(&tree->lock);
+
+       zbud_destroy_pool(tree->pool);
+       kfree(tree);
+       zswap_trees[type] = NULL;
 }
 
 static struct zbud_ops zswap_zbud_ops = {
index 95c2b2689a03aa521bc923323f521a8c191d107d..7db9954f1af2c56c42400746f367f5f4d9906ca8 100644 (file)
@@ -580,15 +580,13 @@ static struct aa_namespace *__next_namespace(struct aa_namespace *root,
 
        /* check if the next ns is a sibling, parent, gp, .. */
        parent = ns->parent;
-       while (parent) {
+       while (ns != root) {
                mutex_unlock(&ns->lock);
                next = list_entry_next(ns, base.list);
                if (!list_entry_is_head(next, &parent->sub_ns, base.list)) {
                        mutex_lock(&next->lock);
                        return next;
                }
-               if (parent == root)
-                       return NULL;
                ns = parent;
                parent = parent->parent;
        }
index 345bec07a27d9292dbfc1306d1f5e12563eaa891..705c2879d3a94a79e10d1190468483c2f9d7192a 100644 (file)
@@ -610,6 +610,7 @@ void aa_free_profile(struct aa_profile *profile)
        aa_put_dfa(profile->policy.dfa);
        aa_put_replacedby(profile->replacedby);
 
+       kzfree(profile->hash);
        kzfree(profile);
 }
 
index ac41e9cdc976a1c190c51684519abb9c475c2c59..26ad4f0aade3fcf2c26940c008fae9a55c63244c 100644 (file)
@@ -3531,7 +3531,7 @@ static int create_capture_mixers(struct hda_codec *codec)
                if (!multi)
                        err = create_single_cap_vol_ctl(codec, n, vol, sw,
                                                        inv_dmic);
-               else if (!multi_cap_vol)
+               else if (!multi_cap_vol && !inv_dmic)
                        err = create_bind_cap_vol_ctl(codec, n, vol, sw);
                else
                        err = create_multi_cap_vol_ctl(codec);
index 4f255dfee4504454702bfdec305b1b72820a26ac..f59a321a6d6af04d6dce32751410e4eb3f9d9df0 100644 (file)
@@ -4845,6 +4845,7 @@ static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigne
                        if ((err = hdsp_get_iobox_version(hdsp)) < 0)
                                return err;
                }
+               memset(&hdsp_version, 0, sizeof(hdsp_version));
                hdsp_version.io_type = hdsp->io_type;
                hdsp_version.firmware_rev = hdsp->firmware_rev;
                if ((err = copy_to_user(argp, &hdsp_version, sizeof(hdsp_version))))
index d0323a693ba20f4719731369f85324e9ba582096..999550bbad40e66f259d9ed2b044ed478e377d72 100644 (file)
@@ -262,7 +262,9 @@ static int usb_stream_hwdep_mmap(struct snd_hwdep *hw,
        }
 
        area->vm_ops = &usb_stream_hwdep_vm_ops;
-       area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
+       area->vm_flags |= VM_DONTDUMP;
+       if (!read)
+               area->vm_flags |= VM_DONTEXPAND;
        area->vm_private_data = us122l;
        atomic_inc(&us122l->mmap_count);
 out:
index 4fa655d68a81c8a1b8dd8b60f885721edc7cfea1..41bd85559d4b01aa8ee0e89615ece47c4115b0d0 100644 (file)
@@ -151,7 +151,7 @@ static int check_timer_create(int which)
        fflush(stdout);
 
        done = 0;
-       timer_create(which, NULL, &id);
+       err = timer_create(which, NULL, &id);
        if (err < 0) {
                perror("Can't create timer\n");
                return -1;