Merge tag 'pm+acpi-4.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 15 Apr 2015 03:21:54 +0000 (20:21 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 15 Apr 2015 03:21:54 +0000 (20:21 -0700)
Pull power management and ACPI updates from Rafael Wysocki:
 "These are mostly fixes and cleanups all over, although there are a few
  items that sort of fall into the new feature category.

  First off, we have new callbacks for PM domains that should help us to
  handle some issues related to device initialization in a better way.

  There also is some consolidation in the unified device properties API
  area allowing us to use that inferface for accessing data coming from
  platform initialization code in addition to firmware-provided data.

  We have some new device/CPU IDs in a few drivers, support for new
  chips and a new cpufreq driver too.

  Specifics:

   - Generic PM domains support update including new PM domain callbacks
     to handle device initialization better (Russell King, Rafael J
     Wysocki, Kevin Hilman)

   - Unified device properties API update including a new mechanism for
     accessing data provided by platform initialization code (Rafael J
     Wysocki, Adrian Hunter)

   - ARM cpuidle update including ARM32/ARM64 handling consolidation
     (Daniel Lezcano)

   - intel_idle update including support for the Silvermont Core in the
     Baytrail SOC and for the Airmont Core in the Cherrytrail and
     Braswell SOCs (Len Brown, Mathias Krause)

   - New cpufreq driver for Hisilicon ACPU (Leo Yan)

   - intel_pstate update including support for the Knights Landing chip
     (Dasaratharaman Chandramouli, Kristen Carlson Accardi)

   - QorIQ cpufreq driver update (Tang Yuantian, Arnd Bergmann)

   - powernv cpufreq driver update (Shilpasri G Bhat)

   - devfreq update including Tegra support changes (Tomeu Vizoso,
     MyungJoo Ham, Chanwoo Choi)

   - powercap RAPL (Running-Average Power Limit) driver update including
     support for Intel Broadwell server chips (Jacob Pan, Mathias Krause)

   - ACPI device enumeration update related to the handling of the
     special PRP0001 device ID allowing DT-style 'compatible' property
     to be used for ACPI device identification (Rafael J Wysocki)

   - ACPI EC driver update including limited _DEP support (Lan Tianyu,
     Lv Zheng)

   - ACPI backlight driver update including a new mechanism to allow
     native backlight handling to be forced on non-Windows 8 systems and
     a new quirk for Lenovo Ideapad Z570 (Aaron Lu, Hans de Goede)

   - New Windows Vista compatibility quirk for Sony VGN-SR19XN (Chen Yu)

   - Assorted ACPI fixes and cleanups (Aaron Lu, Martin Kepplinger,
     Masanari Iida, Mika Westerberg, Nan Li, Rafael J Wysocki)

   - Fixes related to suspend-to-idle for the iTCO watchdog driver and
     the ACPI core system suspend/resume code (Rafael J Wysocki, Chen Yu)

   - PM tracing support for the suspend phase of system suspend/resume
     transitions (Zhonghui Fu)

   - Configurable delay for the system suspend/resume testing facility
     (Brian Norris)

   - PNP subsystem cleanups (Peter Huewe, Rafael J Wysocki)"

* tag 'pm+acpi-4.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (74 commits)
  ACPI / scan: Fix NULL pointer dereference in acpi_companion_match()
  ACPI / scan: Rework modalias creation when "compatible" is present
  intel_idle: mark cpu id array as __initconst
  powercap / RAPL: mark rapl_ids array as __initconst
  powercap / RAPL: add ID for Broadwell server
  intel_pstate: Knights Landing support
  intel_pstate: remove MSR test
  cpufreq: fix qoriq uniprocessor build
  ACPI / scan: Take the PRP0001 position in the list of IDs into account
  ACPI / scan: Simplify acpi_match_device()
  ACPI / scan: Generalize of_compatible matching
  device property: Introduce firmware node type for platform data
  device property: Make it possible to use secondary firmware nodes
  PM / watchdog: iTCO: stop watchdog during system suspend
  cpufreq: hisilicon: add acpu driver
  ACPI / EC: Call acpi_walk_dep_device_list() after installing EC opregion handler
  cpufreq: powernv: Report cpu frequency throttling
  intel_idle: Add support for the Airmont Core in the Cherrytrail and Braswell SOCs
  intel_idle: Update support for Silvermont Core in Baytrail SOC
  PM / devfreq: tegra: Register governor on module init
  ...

16 files changed:
1  2 
Documentation/kernel-parameters.txt
MAINTAINERS
arch/arm/mach-omap2/cpuidle44xx.c
arch/arm/mach-tegra/cpuidle-tegra20.c
arch/arm/mach-tegra/cpuidle-tegra30.c
drivers/acpi/battery.c
drivers/base/core.c
drivers/base/dd.c
drivers/base/platform.c
drivers/base/property.c
drivers/i2c/busses/i2c-designware-platdrv.c
drivers/i2c/i2c-core.c
drivers/idle/intel_idle.c
include/asm-generic/vmlinux.lds.h
include/linux/device.h
include/linux/i2c.h

@@@ -1036,7 -1036,7 +1036,7 @@@ bytes respectively. Such letter suffixe
                        Format: {"off" | "on" | "skip[mbr]"}
  
        efi=            [EFI]
 -                      Format: { "old_map", "nochunk", "noruntime" }
 +                      Format: { "old_map", "nochunk", "noruntime", "debug" }
                        old_map [X86-64]: switch to the old ioremap-based EFI
                        runtime services mapping. 32-bit still uses this one by
                        default.
                        boot stub, as chunking can cause problems with some
                        firmware implementations.
                        noruntime : disable EFI runtime services support
 +                      debug: enable misc debug output
  
        efi_no_storage_paranoia [EFI; X86]
                        Using this parameter you can use more than 50% of
                        seconds.  Use this parameter to check at some
                        other rate.  0 disables periodic checking.
  
 -      memtest=        [KNL,X86] Enable memtest
 +      memtest=        [KNL,X86,ARM] Enable memtest
                        Format: <integer>
                        default : 0 <disable>
                        Specifies the number of memtest passes to be
  
        nmi_watchdog=   [KNL,BUGS=X86] Debugging features for SMP kernels
                        Format: [panic,][nopanic,][num]
 -                      Valid num: 0
 +                      Valid num: 0 or 1
                        0 - turn nmi_watchdog off
 +                      1 - turn nmi_watchdog on
                        When panic is specified, panic when an NMI watchdog
                        timeout occurs (or 'nopanic' to override the opposite
                        default).
                        register save and restore. The kernel will only save
                        legacy floating-point registers on task switch.
  
 +      nohugeiomap     [KNL,x86] Disable kernel huge I/O mappings.
 +
        noxsave         [BUGS=X86] Disables x86 extended register state save
                        and restore using xsave. The kernel will fallback to
                        enabling legacy floating-point and sse state.
  
        nousb           [USB] Disable the USB subsystem
  
 -      nowatchdog      [KNL] Disable the lockup detector (NMI watchdog).
 +      nowatchdog      [KNL] Disable both lockup detectors, i.e.
 +                        soft-lockup and NMI watchdog (hard-lockup).
  
        nowb            [ARM]
  
                        Set maximum number of finished RCU callbacks to
                        process in one batch.
  
 +      rcutree.gp_init_delay=  [KNL]
 +                      Set the number of jiffies to delay each step of
 +                      RCU grace-period initialization.  This only has
 +                      effect when CONFIG_RCU_TORTURE_TEST_SLOW_INIT is
 +                      set.
 +
        rcutree.rcu_fanout_leaf= [KNL]
                        Increase the number of CPUs assigned to each
                        leaf rcu_node structure.  Useful for very large
                        value is one, and maximum value is HZ.
  
        rcutree.kthread_prio=    [KNL,BOOT]
 -                      Set the SCHED_FIFO priority of the RCU
 -                      per-CPU kthreads (rcuc/N). This value is also
 -                      used for the priority of the RCU boost threads
 -                      (rcub/N). Valid values are 1-99 and the default
 -                      is 1 (the least-favored priority).
 +                      Set the SCHED_FIFO priority of the RCU per-CPU
 +                      kthreads (rcuc/N). This value is also used for
 +                      the priority of the RCU boost threads (rcub/N)
 +                      and for the RCU grace-period kthreads (rcu_bh,
 +                      rcu_preempt, and rcu_sched). If RCU_BOOST is
 +                      set, valid values are 1-99 and the default is 1
 +                      (the least-favored priority).  Otherwise, when
 +                      RCU_BOOST is not set, valid values are 0-99 and
 +                      the default is zero (non-realtime operation).
  
        rcutree.rcu_nocb_leader_stride= [KNL]
                        Set the number of NOCB kthread groups, which
                        improve throughput, but will also increase the
                        amount of memory reserved for use by the client.
  
+       suspend.pm_test_delay=
+                       [SUSPEND]
+                       Sets the number of seconds to remain in a suspend test
+                       mode before resuming the system (see
+                       /sys/power/pm_test). Only available when CONFIG_PM_DEBUG
+                       is set. Default value is 5.
        swapaccount=[0|1]
                        [KNL] Enable accounting of swap in memory resource
                        controller if no parameter or 1 is given or disable
diff --combined MAINTAINERS
@@@ -724,7 -724,7 +724,7 @@@ F: staging/iio/trigger/iio-trig-bfin-ti
  
  ANDROID DRIVERS
  M:    Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 -M:    Arve HjønnevÃ¥g <arve@android.com>
 +M:    Arve HjønnevÃ¥g <arve@android.com>
  M:    Riley Andrews <riandrews@android.com>
  T:    git git://git.kernel.org/pub/scm/linux/kernel/gregkh/staging.git
  L:    devel@driverdev.osuosl.org
@@@ -1468,8 -1468,6 +1468,8 @@@ F:      drivers/clocksource/arm_global_timer
  F:    drivers/i2c/busses/i2c-st.c
  F:    drivers/media/rc/st_rc.c
  F:    drivers/mmc/host/sdhci-st.c
 +F:    drivers/phy/phy-miphy28lp.c
 +F:    drivers/phy/phy-miphy365x.c
  F:    drivers/phy/phy-stih407-usb.c
  F:    drivers/phy/phy-stih41x-usb.c
  F:    drivers/pinctrl/pinctrl-st.c
@@@ -2520,18 -2518,11 +2520,18 @@@ F:   Documentation/zh_CN
  
  CHIPIDEA USB HIGH SPEED DUAL ROLE CONTROLLER
  M:    Peter Chen <Peter.Chen@freescale.com>
 -T:    git git://github.com/hzpeterchen/linux-usb.git
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb.git
  L:    linux-usb@vger.kernel.org
  S:    Maintained
  F:    drivers/usb/chipidea/
  
 +CHIPONE ICN8318 I2C TOUCHSCREEN DRIVER
 +M:    Hans de Goede <hdegoede@redhat.com>
 +L:    linux-input@vger.kernel.org
 +S:    Maintained
 +F:    Documentation/devicetree/bindings/input/touchscreen/chipone_icn8318.txt
 +F:    drivers/input/touchscreen/chipone_icn8318.c
 +
  CHROME HARDWARE PLATFORM SUPPORT
  M:    Olof Johansson <olof@lixom.net>
  S:    Maintained
@@@ -3146,15 -3137,12 +3146,15 @@@ S:   Supporte
  F:    Documentation/hwmon/da90??
  F:    drivers/gpio/gpio-da90??.c
  F:    drivers/hwmon/da90??-hwmon.c
 +F:    drivers/iio/adc/da91??-*.c
  F:    drivers/input/misc/da90??_onkey.c
  F:    drivers/input/touchscreen/da9052_tsi.c
  F:    drivers/leds/leds-da90??.c
  F:    drivers/mfd/da903x.c
  F:    drivers/mfd/da90??-*.c
 +F:    drivers/mfd/da91??-*.c
  F:    drivers/power/da9052-battery.c
 +F:    drivers/power/da91??-*.c
  F:    drivers/regulator/da903x.c
  F:    drivers/regulator/da9???-regulator.[ch]
  F:    drivers/rtc/rtc-da90??.c
@@@ -3164,7 -3152,6 +3164,7 @@@ F:      include/linux/mfd/da903x.
  F:    include/linux/mfd/da9052/
  F:    include/linux/mfd/da9055/
  F:    include/linux/mfd/da9063/
 +F:    include/linux/mfd/da9150/
  F:    include/sound/da[79]*.h
  F:    sound/soc/codecs/da[79]*.[ch]
  
@@@ -4176,12 -4163,6 +4176,12 @@@ F:    sound/soc/fsl/fsl
  F:    sound/soc/fsl/imx*
  F:    sound/soc/fsl/mpc8610_hpcd.c
  
 +FREESCALE QORIQ MANAGEMENT COMPLEX DRIVER
 +M:    J. German Rivera <German.Rivera@freescale.com>
 +L:    linux-kernel@vger.kernel.org
 +S:    Maintained
 +F:    drivers/staging/fsl-mc/
 +
  FREEVXFS FILESYSTEM
  M:    Christoph Hellwig <hch@infradead.org>
  W:    ftp://ftp.openlinux.org/pub/people/hch/vxfs
@@@ -4331,6 -4312,15 +4331,15 @@@ S:    Supporte
  F:    drivers/phy/
  F:    include/linux/phy/
  
+ GENERIC PM DOMAINS
+ M:    "Rafael J. Wysocki" <rjw@rjwysocki.net>
+ M:    Kevin Hilman <khilman@kernel.org>
+ M:    Ulf Hansson <ulf.hansson@linaro.org>
+ L:    linux-pm@vger.kernel.org
+ S:    Supported
+ F:    drivers/base/power/domain*.c
+ F:    include/linux/pm_domain.h
  GENERIC UIO DRIVER FOR PCI DEVICES
  M:    "Michael S. Tsirkin" <mst@redhat.com>
  L:    kvm@vger.kernel.org
@@@ -4344,10 -4334,10 +4353,10 @@@ F:   scripts/get_maintainer.p
  
  GFS2 FILE SYSTEM
  M:    Steven Whitehouse <swhiteho@redhat.com>
 +M:    Bob Peterson <rpeterso@redhat.com>
  L:    cluster-devel@redhat.com
  W:    http://sources.redhat.com/cluster/
 -T:    git git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-fixes.git
 -T:    git git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-nmw.git
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2.git
  S:    Supported
  F:    Documentation/filesystems/gfs2*.txt
  F:    fs/gfs2/
@@@ -4967,7 -4957,6 +4976,7 @@@ S:      Maintaine
  F:    drivers/iio/
  F:    drivers/staging/iio/
  F:    include/linux/iio/
 +F:    tools/iio/
  
  IKANOS/ADI EAGLE ADSL USB DRIVER
  M:    Matthieu Castet <castet.matthieu@free.fr>
@@@ -5611,8 -5600,6 +5620,8 @@@ S:      Supporte
  F:    Documentation/*/kvm*.txt
  F:    Documentation/virtual/kvm/
  F:    arch/*/kvm/
 +F:    arch/x86/kernel/kvm.c
 +F:    arch/x86/kernel/kvmclock.c
  F:    arch/*/include/asm/kvm*
  F:    include/linux/kvm*
  F:    include/uapi/linux/kvm*
@@@ -6586,8 -6573,10 +6595,8 @@@ F:     drivers/mfd
  F:    include/linux/mfd/
  
  MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM
 -M:    Chris Ball <chris@printf.net>
  M:    Ulf Hansson <ulf.hansson@linaro.org>
  L:    linux-mmc@vger.kernel.org
 -T:    git git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc.git
  T:    git git://git.linaro.org/people/ulf.hansson/mmc.git
  S:    Maintained
  F:    drivers/mmc/
@@@ -8579,7 -8568,6 +8588,7 @@@ F:      include/uapi/linux/timex.
  F:    kernel/time/clocksource.c
  F:    kernel/time/time*.c
  F:    kernel/time/ntp.c
 +F:    tools/testing/selftests/timers/
  
  SC1200 WDT DRIVER
  M:    Zwane Mwaikambo <zwanem@gmail.com>
@@@ -8688,8 -8676,10 +8697,8 @@@ S:     Maintaine
  F:    drivers/mmc/host/sdricoh_cs.c
  
  SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) DRIVER
 -M:    Chris Ball <chris@printf.net>
  L:    linux-mmc@vger.kernel.org
 -T:    git git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc.git
 -S:    Maintained
 +S:    Orphan
  F:    drivers/mmc/host/sdhci.*
  F:    drivers/mmc/host/sdhci-pltfm.[ch]
  
@@@ -8705,12 -8695,18 +8714,12 @@@ F:   include/linux/seccomp.
  K:    \bsecure_computing
  K:    \bTIF_SECCOMP\b
  
 -SECURE DIGITAL HOST CONTROLLER INTERFACE, OPEN FIRMWARE BINDINGS (SDHCI-OF)
 -M:    Anton Vorontsov <anton@enomsg.org>
 -L:    linuxppc-dev@lists.ozlabs.org
 -L:    linux-mmc@vger.kernel.org
 -S:    Maintained
 -F:    drivers/mmc/host/sdhci-pltfm.[ch]
 -
  SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) SAMSUNG DRIVER
  M:    Ben Dooks <ben-linux@fluff.org>
 +M:    Jaehoon Chung <jh80.chung@samsung.com>
  L:    linux-mmc@vger.kernel.org
  S:    Maintained
 -F:    drivers/mmc/host/sdhci-s3c.c
 +F:    drivers/mmc/host/sdhci-s3c*
  
  SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) ST SPEAR DRIVER
  M:    Viresh Kumar <viresh.linux@gmail.com>
@@@ -9377,14 -9373,6 +9386,14 @@@ L:    linux-fbdev@vger.kernel.or
  S:    Maintained
  F:    drivers/staging/sm7xxfb/
  
 +STAGING - SILICON MOTION SM750 FRAME BUFFER DRIVER
 +M:    Sudip Mukherjee <sudipm.mukherjee@gmail.com>
 +M:    Teddy Wang <teddy.wang@siliconmotion.com>
 +M:    Sudip Mukherjee <sudip@vectorindia.org>
 +L:    linux-fbdev@vger.kernel.org
 +S:    Maintained
 +F:    drivers/staging/sm750fb/
 +
  STAGING - SLICOSS
  M:    Lior Dotan <liodot@gmail.com>
  M:    Christopher Harrer <charrer@alacritech.com>
@@@ -10156,12 -10144,6 +10165,12 @@@ S: Maintaine
  F:    drivers/net/usb/cdc_*.c
  F:    include/uapi/linux/usb/cdc.h
  
 +USB CHAOSKEY DRIVER
 +M:    Keith Packard <keithp@keithp.com>
 +L:    linux-usb@vger.kernel.org
 +S:    Maintained
 +F:    drivers/usb/misc/chaoskey.c
 +
  USB CYPRESS C67X00 DRIVER
  M:    Peter Korsgaard <jacmet@sunsite.dk>
  L:    linux-usb@vger.kernel.org
@@@ -10242,7 -10224,7 +10251,7 @@@ F:   drivers/usb/host/ohci
  
  USB OTG FSM (Finite State Machine)
  M:    Peter Chen <Peter.Chen@freescale.com>
 -T:    git git://github.com/hzpeterchen/linux-usb.git
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb.git
  L:    linux-usb@vger.kernel.org
  S:    Maintained
  F:    drivers/usb/common/usb-otg-fsm.c
  #include <linux/cpuidle.h>
  #include <linux/cpu_pm.h>
  #include <linux/export.h>
 -#include <linux/clockchips.h>
 +#include <linux/tick.h>
  
  #include <asm/cpuidle.h>
- #include <asm/proc-fns.h>
  
  #include "common.h"
  #include "pm.h"
@@@ -84,6 -83,7 +83,6 @@@ static int omap_enter_idle_coupled(stru
  {
        struct idle_statedata *cx = state_ptr + index;
        u32 mpuss_can_lose_context = 0;
 -      int cpu_id = smp_processor_id();
  
        /*
         * CPU0 has to wait and stay ON until CPU1 is OFF state.
        mpuss_can_lose_context = (cx->mpu_state == PWRDM_POWER_RET) &&
                                 (cx->mpu_logic_state == PWRDM_POWER_OFF);
  
 -      clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu_id);
 +      tick_broadcast_enter();
  
        /*
         * Call idle CPU PM enter notifier chain so that
        if (dev->cpu == 0 && mpuss_can_lose_context)
                cpu_cluster_pm_exit();
  
 -      clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu_id);
 +      tick_broadcast_exit();
  
  fail:
        cpuidle_coupled_parallel_barrier(dev, &abort_barrier);
   */
  static void omap_setup_broadcast_timer(void *arg)
  {
 -      int cpu = smp_processor_id();
 -      clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &cpu);
 +      tick_broadcast_enable();
  }
  
  static struct cpuidle_driver omap4_idle_driver = {
   */
  
  #include <linux/clk/tegra.h>
 -#include <linux/clockchips.h>
 +#include <linux/tick.h>
  #include <linux/cpuidle.h>
  #include <linux/cpu_pm.h>
  #include <linux/kernel.h>
  #include <linux/module.h>
  
  #include <asm/cpuidle.h>
- #include <asm/proc-fns.h>
  #include <asm/smp_plat.h>
  #include <asm/suspend.h>
  
@@@ -136,11 -135,11 +135,11 @@@ static bool tegra20_cpu_cluster_power_d
        if (tegra20_reset_cpu_1() || !tegra_cpu_rail_off_ready())
                return false;
  
 -      clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
 +      tick_broadcast_enter();
  
        tegra_idle_lp2_last();
  
 -      clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
 +      tick_broadcast_exit();
  
        if (cpu_online(1))
                tegra20_wake_cpu1_from_reset();
@@@ -153,13 -152,13 +152,13 @@@ static bool tegra20_idle_enter_lp2_cpu_
                                         struct cpuidle_driver *drv,
                                         int index)
  {
 -      clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
 +      tick_broadcast_enter();
  
        cpu_suspend(0, tegra20_sleep_cpu_secondary_finish);
  
        tegra20_cpu_clear_resettable();
  
 -      clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
 +      tick_broadcast_exit();
  
        return true;
  }
   */
  
  #include <linux/clk/tegra.h>
 -#include <linux/clockchips.h>
 +#include <linux/tick.h>
  #include <linux/cpuidle.h>
  #include <linux/cpu_pm.h>
  #include <linux/kernel.h>
  #include <linux/module.h>
  
  #include <asm/cpuidle.h>
- #include <asm/proc-fns.h>
  #include <asm/smp_plat.h>
  #include <asm/suspend.h>
  
@@@ -76,11 -75,11 +75,11 @@@ static bool tegra30_cpu_cluster_power_d
                return false;
        }
  
 -      clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
 +      tick_broadcast_enter();
  
        tegra_idle_lp2_last();
  
 -      clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
 +      tick_broadcast_exit();
  
        return true;
  }
@@@ -90,13 -89,13 +89,13 @@@ static bool tegra30_cpu_core_power_down
                                        struct cpuidle_driver *drv,
                                        int index)
  {
 -      clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
 +      tick_broadcast_enter();
  
        smp_wmb();
  
        cpu_suspend(0, tegra30_sleep_cpu_secondary_finish);
  
 -      clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
 +      tick_broadcast_exit();
  
        return true;
  }
diff --combined drivers/acpi/battery.c
@@@ -117,8 -117,7 +117,8 @@@ enum 
  struct acpi_battery {
        struct mutex lock;
        struct mutex sysfs_lock;
 -      struct power_supply bat;
 +      struct power_supply *bat;
 +      struct power_supply_desc bat_desc;
        struct acpi_device *device;
        struct notifier_block pm_nb;
        unsigned long update_time;
        unsigned long flags;
  };
  
 -#define to_acpi_battery(x) container_of(x, struct acpi_battery, bat)
 +#define to_acpi_battery(x) power_supply_get_drvdata(x)
  
  static inline int acpi_battery_present(struct acpi_battery *battery)
  {
@@@ -531,8 -530,8 +531,8 @@@ static int acpi_battery_get_state(struc
                battery->rate_now != ACPI_BATTERY_VALUE_UNKNOWN &&
                (s16)(battery->rate_now) < 0) {
                battery->rate_now = abs((s16)battery->rate_now);
-               printk_once(KERN_WARNING FW_BUG "battery: (dis)charge rate"
-                       " invalid.\n");
+               printk_once(KERN_WARNING FW_BUG
+                           "battery: (dis)charge rate invalid.\n");
        }
  
        if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)
@@@ -609,45 -608,40 +609,45 @@@ static struct device_attribute alarm_at
  
  static int sysfs_add_battery(struct acpi_battery *battery)
  {
 -      int result;
 +      struct power_supply_config psy_cfg = { .drv_data = battery, };
  
        if (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) {
 -              battery->bat.properties = charge_battery_props;
 -              battery->bat.num_properties =
 +              battery->bat_desc.properties = charge_battery_props;
 +              battery->bat_desc.num_properties =
                        ARRAY_SIZE(charge_battery_props);
        } else {
 -              battery->bat.properties = energy_battery_props;
 -              battery->bat.num_properties =
 +              battery->bat_desc.properties = energy_battery_props;
 +              battery->bat_desc.num_properties =
                        ARRAY_SIZE(energy_battery_props);
        }
  
 -      battery->bat.name = acpi_device_bid(battery->device);
 -      battery->bat.type = POWER_SUPPLY_TYPE_BATTERY;
 -      battery->bat.get_property = acpi_battery_get_property;
 +      battery->bat_desc.name = acpi_device_bid(battery->device);
 +      battery->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY;
 +      battery->bat_desc.get_property = acpi_battery_get_property;
  
 -      result = power_supply_register_no_ws(&battery->device->dev, &battery->bat);
 +      battery->bat = power_supply_register_no_ws(&battery->device->dev,
 +                              &battery->bat_desc, &psy_cfg);
  
 -      if (result)
 +      if (IS_ERR(battery->bat)) {
 +              int result = PTR_ERR(battery->bat);
 +
 +              battery->bat = NULL;
                return result;
 -      return device_create_file(battery->bat.dev, &alarm_attr);
 +      }
 +      return device_create_file(&battery->bat->dev, &alarm_attr);
  }
  
  static void sysfs_remove_battery(struct acpi_battery *battery)
  {
        mutex_lock(&battery->sysfs_lock);
 -      if (!battery->bat.dev) {
 +      if (!battery->bat) {
                mutex_unlock(&battery->sysfs_lock);
                return;
        }
  
 -      device_remove_file(battery->bat.dev, &alarm_attr);
 -      power_supply_unregister(&battery->bat);
 -      battery->bat.dev = NULL;
 +      device_remove_file(&battery->bat->dev, &alarm_attr);
 +      power_supply_unregister(battery->bat);
 +      battery->bat = NULL;
        mutex_unlock(&battery->sysfs_lock);
  }
  
@@@ -744,7 -738,7 +744,7 @@@ static int acpi_battery_update(struct a
                        return result;
                acpi_battery_init_alarm(battery);
        }
 -      if (!battery->bat.dev) {
 +      if (!battery->bat) {
                result = sysfs_add_battery(battery);
                if (result)
                        return result;
@@@ -770,7 -764,7 +770,7 @@@ static void acpi_battery_refresh(struc
  {
        int power_unit;
  
 -      if (!battery->bat.dev)
 +      if (!battery->bat)
                return;
  
        power_unit = battery->power_unit;
@@@ -1068,11 -1062,11 +1068,11 @@@ static void acpi_battery_remove_fs(stru
  static void acpi_battery_notify(struct acpi_device *device, u32 event)
  {
        struct acpi_battery *battery = acpi_driver_data(device);
 -      struct device *old;
 +      struct power_supply *old;
  
        if (!battery)
                return;
 -      old = battery->bat.dev;
 +      old = battery->bat;
        /*
        * On Acer Aspire V5-573G notifications are sometimes triggered too
        * early. For example, when AC is unplugged and notification is
                                        acpi_battery_present(battery));
        acpi_notifier_call_chain(device, event, acpi_battery_present(battery));
        /* acpi_battery_update could remove power_supply object */
 -      if (old && battery->bat.dev)
 -              power_supply_changed(&battery->bat);
 +      if (old && battery->bat)
 +              power_supply_changed(battery->bat);
  }
  
  static int battery_notify(struct notifier_block *nb,
                if (!acpi_battery_present(battery))
                        return 0;
  
 -              if (!battery->bat.dev) {
 +              if (!battery->bat) {
                        result = acpi_battery_get_info(battery);
                        if (result)
                                return result;
diff --combined drivers/base/core.c
@@@ -12,6 -12,7 +12,7 @@@
  
  #include <linux/device.h>
  #include <linux/err.h>
+ #include <linux/fwnode.h>
  #include <linux/init.h>
  #include <linux/module.h>
  #include <linux/slab.h>
@@@ -805,16 -806,8 +806,16 @@@ static void cleanup_device_parent(struc
  
  static int device_add_class_symlinks(struct device *dev)
  {
 +      struct device_node *of_node = dev_of_node(dev);
        int error;
  
 +      if (of_node) {
 +              error = sysfs_create_link(&dev->kobj, &of_node->kobj,"of_node");
 +              if (error)
 +                      dev_warn(dev, "Error %d creating of_node link\n",error);
 +              /* An error here doesn't warrant bringing down the device */
 +      }
 +
        if (!dev->class)
                return 0;
  
                                  &dev->class->p->subsys.kobj,
                                  "subsystem");
        if (error)
 -              goto out;
 +              goto out_devnode;
  
        if (dev->parent && device_is_not_partition(dev)) {
                error = sysfs_create_link(&dev->kobj, &dev->parent->kobj,
@@@ -850,16 -843,12 +851,16 @@@ out_device
  
  out_subsys:
        sysfs_remove_link(&dev->kobj, "subsystem");
 -out:
 +out_devnode:
 +      sysfs_remove_link(&dev->kobj, "of_node");
        return error;
  }
  
  static void device_remove_class_symlinks(struct device *dev)
  {
 +      if (dev_of_node(dev))
 +              sysfs_remove_link(&dev->kobj, "of_node");
 +
        if (!dev->class)
                return;
  
@@@ -1107,7 -1096,8 +1108,7 @@@ done
        kobject_del(&dev->kobj);
   Error:
        cleanup_device_parent(dev);
 -      if (parent)
 -              put_device(parent);
 +      put_device(parent);
  name_error:
        kfree(dev->p);
        dev->p = NULL;
@@@ -2144,3 -2134,53 +2145,53 @@@ define_dev_printk_level(dev_notice, KER
  define_dev_printk_level(_dev_info, KERN_INFO);
  
  #endif
+ static inline bool fwnode_is_primary(struct fwnode_handle *fwnode)
+ {
+       return fwnode && !IS_ERR(fwnode->secondary);
+ }
+ /**
+  * set_primary_fwnode - Change the primary firmware node of a given device.
+  * @dev: Device to handle.
+  * @fwnode: New primary firmware node of the device.
+  *
+  * Set the device's firmware node pointer to @fwnode, but if a secondary
+  * firmware node of the device is present, preserve it.
+  */
+ void set_primary_fwnode(struct device *dev, struct fwnode_handle *fwnode)
+ {
+       if (fwnode) {
+               struct fwnode_handle *fn = dev->fwnode;
+               if (fwnode_is_primary(fn))
+                       fn = fn->secondary;
+               fwnode->secondary = fn;
+               dev->fwnode = fwnode;
+       } else {
+               dev->fwnode = fwnode_is_primary(dev->fwnode) ?
+                       dev->fwnode->secondary : NULL;
+       }
+ }
+ EXPORT_SYMBOL_GPL(set_primary_fwnode);
+ /**
+  * set_secondary_fwnode - Change the secondary firmware node of a given device.
+  * @dev: Device to handle.
+  * @fwnode: New secondary firmware node of the device.
+  *
+  * If a primary firmware node of the device is present, set its secondary
+  * pointer to @fwnode.  Otherwise, set the device's firmware node pointer to
+  * @fwnode.
+  */
+ void set_secondary_fwnode(struct device *dev, struct fwnode_handle *fwnode)
+ {
+       if (fwnode)
+               fwnode->secondary = ERR_PTR(-ENODEV);
+       if (fwnode_is_primary(dev->fwnode))
+               dev->fwnode->secondary = fwnode;
+       else
+               dev->fwnode = fwnode;
+ }
diff --combined drivers/base/dd.c
@@@ -298,6 -298,12 +298,12 @@@ static int really_probe(struct device *
                goto probe_failed;
        }
  
+       if (dev->pm_domain && dev->pm_domain->activate) {
+               ret = dev->pm_domain->activate(dev);
+               if (ret)
+                       goto probe_failed;
+       }
        if (dev->bus->probe) {
                ret = dev->bus->probe(dev);
                if (ret)
                        goto probe_failed;
        }
  
+       if (dev->pm_domain && dev->pm_domain->sync)
+               dev->pm_domain->sync(dev);
        driver_bound(dev);
        ret = 1;
        pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
@@@ -319,26 -328,24 +328,28 @@@ probe_failed
        driver_sysfs_remove(dev);
        dev->driver = NULL;
        dev_set_drvdata(dev, NULL);
+       if (dev->pm_domain && dev->pm_domain->dismiss)
+               dev->pm_domain->dismiss(dev);
  
 -      if (ret == -EPROBE_DEFER) {
 +      switch (ret) {
 +      case -EPROBE_DEFER:
                /* Driver requested deferred probing */
 -              dev_info(dev, "Driver %s requests probe deferral\n", drv->name);
 +              dev_dbg(dev, "Driver %s requests probe deferral\n", drv->name);
                driver_deferred_probe_add(dev);
                /* Did a trigger occur while probing? Need to re-trigger if yes */
                if (local_trigger_count != atomic_read(&deferred_trigger_count))
                        driver_deferred_probe_trigger();
 -      } else if (ret != -ENODEV && ret != -ENXIO) {
 +              break;
 +      case -ENODEV:
 +      case -ENXIO:
 +              pr_debug("%s: probe of %s rejects match %d\n",
 +                       drv->name, dev_name(dev), ret);
 +              break;
 +      default:
                /* driver matched but the probe failed */
                printk(KERN_WARNING
                       "%s: probe of %s failed with error %d\n",
                       drv->name, dev_name(dev), ret);
 -      } else {
 -              pr_debug("%s: probe of %s rejects match %d\n",
 -                     drv->name, dev_name(dev), ret);
        }
        /*
         * Ignore errors returned by ->probe so that the next driver can try
@@@ -529,6 -536,9 +540,9 @@@ static void __device_release_driver(str
                devres_release_all(dev);
                dev->driver = NULL;
                dev_set_drvdata(dev, NULL);
+               if (dev->pm_domain && dev->pm_domain->dismiss)
+                       dev->pm_domain->dismiss(dev);
                klist_remove(&dev->p->knode_driver);
                if (dev->bus)
                        blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
diff --combined drivers/base/platform.c
@@@ -101,15 -101,6 +101,15 @@@ int platform_get_irq(struct platform_de
        }
  
        r = platform_get_resource(dev, IORESOURCE_IRQ, num);
 +      /*
 +       * The resources may pass trigger flags to the irqs that need
 +       * to be set up. It so happens that the trigger flags for
 +       * IORESOURCE_BITS correspond 1-to-1 to the IRQF_TRIGGER*
 +       * settings.
 +       */
 +      if (r && r->flags & IORESOURCE_BITS)
 +              irqd_set_trigger_type(irq_get_irq_data(r->start),
 +                                    r->flags & IORESOURCE_BITS);
  
        return r ? r->start : -ENXIO;
  #endif
@@@ -463,7 -454,7 +463,7 @@@ struct platform_device *platform_device
                goto err_alloc;
  
        pdev->dev.parent = pdevinfo->parent;
-       ACPI_COMPANION_SET(&pdev->dev, pdevinfo->acpi_node.companion);
+       pdev->dev.fwnode = pdevinfo->fwnode;
  
        if (pdevinfo->dma_mask) {
                /*
diff --combined drivers/base/property.c
   * published by the Free Software Foundation.
   */
  
- #include <linux/property.h>
- #include <linux/export.h>
  #include <linux/acpi.h>
+ #include <linux/export.h>
+ #include <linux/kernel.h>
  #include <linux/of.h>
+ #include <linux/property.h>
+ /**
+  * device_add_property_set - Add a collection of properties to a device object.
+  * @dev: Device to add properties to.
+  * @pset: Collection of properties to add.
+  *
+  * Associate a collection of device properties represented by @pset with @dev
+  * as its secondary firmware node.
+  */
+ void device_add_property_set(struct device *dev, struct property_set *pset)
+ {
+       if (pset)
+               pset->fwnode.type = FWNODE_PDATA;
+       set_secondary_fwnode(dev, &pset->fwnode);
+ }
+ EXPORT_SYMBOL_GPL(device_add_property_set);
+ static inline bool is_pset(struct fwnode_handle *fwnode)
+ {
+       return fwnode && fwnode->type == FWNODE_PDATA;
+ }
+ static inline struct property_set *to_pset(struct fwnode_handle *fwnode)
+ {
+       return is_pset(fwnode) ?
+               container_of(fwnode, struct property_set, fwnode) : NULL;
+ }
+ static struct property_entry *pset_prop_get(struct property_set *pset,
+                                           const char *name)
+ {
+       struct property_entry *prop;
+       if (!pset || !pset->properties)
+               return NULL;
+       for (prop = pset->properties; prop->name; prop++)
+               if (!strcmp(name, prop->name))
+                       return prop;
+       return NULL;
+ }
+ static int pset_prop_read_array(struct property_set *pset, const char *name,
+                               enum dev_prop_type type, void *val, size_t nval)
+ {
+       struct property_entry *prop;
+       unsigned int item_size;
+       prop = pset_prop_get(pset, name);
+       if (!prop)
+               return -ENODATA;
+       if (prop->type != type)
+               return -EPROTO;
+       if (!val)
+               return prop->nval;
+       if (prop->nval < nval)
+               return -EOVERFLOW;
+       switch (type) {
+       case DEV_PROP_U8:
+               item_size = sizeof(u8);
+               break;
+       case DEV_PROP_U16:
+               item_size = sizeof(u16);
+               break;
+       case DEV_PROP_U32:
+               item_size = sizeof(u32);
+               break;
+       case DEV_PROP_U64:
+               item_size = sizeof(u64);
+               break;
+       case DEV_PROP_STRING:
+               item_size = sizeof(const char *);
+               break;
+       default:
+               return -EINVAL;
+       }
+       memcpy(val, prop->value.raw_data, nval * item_size);
+       return 0;
+ }
+ static inline struct fwnode_handle *dev_fwnode(struct device *dev)
+ {
+       return IS_ENABLED(CONFIG_OF) && dev->of_node ?
+               &dev->of_node->fwnode : dev->fwnode;
+ }
  
  /**
   * device_property_present - check if a property of a device is present
   */
  bool device_property_present(struct device *dev, const char *propname)
  {
-       if (IS_ENABLED(CONFIG_OF) && dev->of_node)
-               return of_property_read_bool(dev->of_node, propname);
-       return !acpi_dev_prop_get(ACPI_COMPANION(dev), propname, NULL);
+       return fwnode_property_present(dev_fwnode(dev), propname);
  }
  EXPORT_SYMBOL_GPL(device_property_present);
  
@@@ -43,32 -132,22 +132,22 @@@ bool fwnode_property_present(struct fwn
        else if (is_acpi_node(fwnode))
                return !acpi_dev_prop_get(acpi_node(fwnode), propname, NULL);
  
-       return false;
+       return !!pset_prop_get(to_pset(fwnode), propname);
  }
  EXPORT_SYMBOL_GPL(fwnode_property_present);
  
- #define OF_DEV_PROP_READ_ARRAY(node, propname, type, val, nval) \
-       (val) ? of_property_read_##type##_array((node), (propname), (val), (nval)) \
-             : of_property_count_elems_of_size((node), (propname), sizeof(type))
- #define DEV_PROP_READ_ARRAY(_dev_, _propname_, _type_, _proptype_, _val_, _nval_) \
-       IS_ENABLED(CONFIG_OF) && _dev_->of_node ? \
-               (OF_DEV_PROP_READ_ARRAY(_dev_->of_node, _propname_, _type_, \
-                                       _val_, _nval_)) : \
-               acpi_dev_prop_read(ACPI_COMPANION(_dev_), _propname_, \
-                                  _proptype_, _val_, _nval_)
  /**
   * device_property_read_u8_array - return a u8 array property of a device
   * @dev: Device to get the property of
   * @propname: Name of the property
-  * @val: The values are stored here
+  * @val: The values are stored here or %NULL to return the number of values
   * @nval: Size of the @val array
   *
   * Function reads an array of u8 properties with @propname from the device
   * firmware description and stores them to @val if found.
   *
-  * Return: %0 if the property was found (success),
+  * Return: number of values if @val was %NULL,
+  *         %0 if the property was found (success),
   *       %-EINVAL if given arguments are not valid,
   *       %-ENODATA if the property does not have a value,
   *       %-EPROTO if the property is not an array of numbers,
  int device_property_read_u8_array(struct device *dev, const char *propname,
                                  u8 *val, size_t nval)
  {
-       return DEV_PROP_READ_ARRAY(dev, propname, u8, DEV_PROP_U8, val, nval);
+       return fwnode_property_read_u8_array(dev_fwnode(dev), propname, val, nval);
  }
  EXPORT_SYMBOL_GPL(device_property_read_u8_array);
  
   * device_property_read_u16_array - return a u16 array property of a device
   * @dev: Device to get the property of
   * @propname: Name of the property
-  * @val: The values are stored here
+  * @val: The values are stored here or %NULL to return the number of values
   * @nval: Size of the @val array
   *
   * Function reads an array of u16 properties with @propname from the device
   * firmware description and stores them to @val if found.
   *
-  * Return: %0 if the property was found (success),
+  * Return: number of values if @val was %NULL,
+  *         %0 if the property was found (success),
   *       %-EINVAL if given arguments are not valid,
   *       %-ENODATA if the property does not have a value,
   *       %-EPROTO if the property is not an array of numbers,
  int device_property_read_u16_array(struct device *dev, const char *propname,
                                   u16 *val, size_t nval)
  {
-       return DEV_PROP_READ_ARRAY(dev, propname, u16, DEV_PROP_U16, val, nval);
+       return fwnode_property_read_u16_array(dev_fwnode(dev), propname, val, nval);
  }
  EXPORT_SYMBOL_GPL(device_property_read_u16_array);
  
   * device_property_read_u32_array - return a u32 array property of a device
   * @dev: Device to get the property of
   * @propname: Name of the property
-  * @val: The values are stored here
+  * @val: The values are stored here or %NULL to return the number of values
   * @nval: Size of the @val array
   *
   * Function reads an array of u32 properties with @propname from the device
   * firmware description and stores them to @val if found.
   *
-  * Return: %0 if the property was found (success),
+  * Return: number of values if @val was %NULL,
+  *         %0 if the property was found (success),
   *       %-EINVAL if given arguments are not valid,
   *       %-ENODATA if the property does not have a value,
   *       %-EPROTO if the property is not an array of numbers,
  int device_property_read_u32_array(struct device *dev, const char *propname,
                                   u32 *val, size_t nval)
  {
-       return DEV_PROP_READ_ARRAY(dev, propname, u32, DEV_PROP_U32, val, nval);
+       return fwnode_property_read_u32_array(dev_fwnode(dev), propname, val, nval);
  }
  EXPORT_SYMBOL_GPL(device_property_read_u32_array);
  
   * device_property_read_u64_array - return a u64 array property of a device
   * @dev: Device to get the property of
   * @propname: Name of the property
-  * @val: The values are stored here
+  * @val: The values are stored here or %NULL to return the number of values
   * @nval: Size of the @val array
   *
   * Function reads an array of u64 properties with @propname from the device
   * firmware description and stores them to @val if found.
   *
-  * Return: %0 if the property was found (success),
+  * Return: number of values if @val was %NULL,
+  *         %0 if the property was found (success),
   *       %-EINVAL if given arguments are not valid,
   *       %-ENODATA if the property does not have a value,
   *       %-EPROTO if the property is not an array of numbers,
  int device_property_read_u64_array(struct device *dev, const char *propname,
                                   u64 *val, size_t nval)
  {
-       return DEV_PROP_READ_ARRAY(dev, propname, u64, DEV_PROP_U64, val, nval);
+       return fwnode_property_read_u64_array(dev_fwnode(dev), propname, val, nval);
  }
  EXPORT_SYMBOL_GPL(device_property_read_u64_array);
  
   * device_property_read_string_array - return a string array property of device
   * @dev: Device to get the property of
   * @propname: Name of the property
-  * @val: The values are stored here
+  * @val: The values are stored here or %NULL to return the number of values
   * @nval: Size of the @val array
   *
   * Function reads an array of string properties with @propname from the device
   * firmware description and stores them to @val if found.
   *
-  * Return: %0 if the property was found (success),
+  * Return: number of values if @val was %NULL,
+  *         %0 if the property was found (success),
   *       %-EINVAL if given arguments are not valid,
   *       %-ENODATA if the property does not have a value,
   *       %-EPROTO or %-EILSEQ if the property is not an array of strings,
  int device_property_read_string_array(struct device *dev, const char *propname,
                                      const char **val, size_t nval)
  {
-       return IS_ENABLED(CONFIG_OF) && dev->of_node ?
-               of_property_read_string_array(dev->of_node, propname, val, nval) :
-               acpi_dev_prop_read(ACPI_COMPANION(dev), propname,
-                                  DEV_PROP_STRING, val, nval);
+       return fwnode_property_read_string_array(dev_fwnode(dev), propname, val, nval);
  }
  EXPORT_SYMBOL_GPL(device_property_read_string_array);
  
  int device_property_read_string(struct device *dev, const char *propname,
                                const char **val)
  {
-       return IS_ENABLED(CONFIG_OF) && dev->of_node ?
-               of_property_read_string(dev->of_node, propname, val) :
-               acpi_dev_prop_read(ACPI_COMPANION(dev), propname,
-                                  DEV_PROP_STRING, val, 1);
+       return fwnode_property_read_string(dev_fwnode(dev), propname, val);
  }
  EXPORT_SYMBOL_GPL(device_property_read_string);
  
+ #define OF_DEV_PROP_READ_ARRAY(node, propname, type, val, nval) \
+       (val) ? of_property_read_##type##_array((node), (propname), (val), (nval)) \
+             : of_property_count_elems_of_size((node), (propname), sizeof(type))
  #define FWNODE_PROP_READ_ARRAY(_fwnode_, _propname_, _type_, _proptype_, _val_, _nval_) \
  ({ \
        int _ret_; \
                _ret_ = acpi_dev_prop_read(acpi_node(_fwnode_), _propname_, \
                                           _proptype_, _val_, _nval_); \
        else \
-               _ret_ = -ENXIO; \
+               _ret_ = pset_prop_read_array(to_pset(_fwnode_), _propname_, \
+                                            _proptype_, _val_, _nval_); \
        _ret_; \
  })
  
   * fwnode_property_read_u8_array - return a u8 array property of firmware node
   * @fwnode: Firmware node to get the property of
   * @propname: Name of the property
-  * @val: The values are stored here
+  * @val: The values are stored here or %NULL to return the number of values
   * @nval: Size of the @val array
   *
   * Read an array of u8 properties with @propname from @fwnode and stores them to
   * @val if found.
   *
-  * Return: %0 if the property was found (success),
+  * Return: number of values if @val was %NULL,
+  *         %0 if the property was found (success),
   *       %-EINVAL if given arguments are not valid,
   *       %-ENODATA if the property does not have a value,
   *       %-EPROTO if the property is not an array of numbers,
@@@ -243,13 -326,14 +326,14 @@@ EXPORT_SYMBOL_GPL(fwnode_property_read_
   * fwnode_property_read_u16_array - return a u16 array property of firmware node
   * @fwnode: Firmware node to get the property of
   * @propname: Name of the property
-  * @val: The values are stored here
+  * @val: The values are stored here or %NULL to return the number of values
   * @nval: Size of the @val array
   *
   * Read an array of u16 properties with @propname from @fwnode and store them to
   * @val if found.
   *
-  * Return: %0 if the property was found (success),
+  * Return: number of values if @val was %NULL,
+  *         %0 if the property was found (success),
   *       %-EINVAL if given arguments are not valid,
   *       %-ENODATA if the property does not have a value,
   *       %-EPROTO if the property is not an array of numbers,
@@@ -268,13 -352,14 +352,14 @@@ EXPORT_SYMBOL_GPL(fwnode_property_read_
   * fwnode_property_read_u32_array - return a u32 array property of firmware node
   * @fwnode: Firmware node to get the property of
   * @propname: Name of the property
-  * @val: The values are stored here
+  * @val: The values are stored here or %NULL to return the number of values
   * @nval: Size of the @val array
   *
   * Read an array of u32 properties with @propname from @fwnode store them to
   * @val if found.
   *
-  * Return: %0 if the property was found (success),
+  * Return: number of values if @val was %NULL,
+  *         %0 if the property was found (success),
   *       %-EINVAL if given arguments are not valid,
   *       %-ENODATA if the property does not have a value,
   *       %-EPROTO if the property is not an array of numbers,
@@@ -293,13 -378,14 +378,14 @@@ EXPORT_SYMBOL_GPL(fwnode_property_read_
   * fwnode_property_read_u64_array - return a u64 array property firmware node
   * @fwnode: Firmware node to get the property of
   * @propname: Name of the property
-  * @val: The values are stored here
+  * @val: The values are stored here or %NULL to return the number of values
   * @nval: Size of the @val array
   *
   * Read an array of u64 properties with @propname from @fwnode and store them to
   * @val if found.
   *
-  * Return: %0 if the property was found (success),
+  * Return: number of values if @val was %NULL,
+  *         %0 if the property was found (success),
   *       %-EINVAL if given arguments are not valid,
   *       %-ENODATA if the property does not have a value,
   *       %-EPROTO if the property is not an array of numbers,
@@@ -318,13 -404,14 +404,14 @@@ EXPORT_SYMBOL_GPL(fwnode_property_read_
   * fwnode_property_read_string_array - return string array property of a node
   * @fwnode: Firmware node to get the property of
   * @propname: Name of the property
-  * @val: The values are stored here
+  * @val: The values are stored here or %NULL to return the number of values
   * @nval: Size of the @val array
   *
   * Read an string list property @propname from the given firmware node and store
   * them to @val if found.
   *
-  * Return: %0 if the property was found (success),
+  * Return: number of values if @val was %NULL,
+  *         %0 if the property was found (success),
   *       %-EINVAL if given arguments are not valid,
   *       %-ENODATA if the property does not have a value,
   *       %-EPROTO if the property is not an array of strings,
@@@ -336,13 -423,16 +423,16 @@@ int fwnode_property_read_string_array(s
                                      size_t nval)
  {
        if (is_of_node(fwnode))
-               return of_property_read_string_array(of_node(fwnode), propname,
-                                                    val, nval);
+               return val ?
+                       of_property_read_string_array(of_node(fwnode), propname,
+                                                     val, nval) :
+                       of_property_count_strings(of_node(fwnode), propname);
        else if (is_acpi_node(fwnode))
                return acpi_dev_prop_read(acpi_node(fwnode), propname,
                                          DEV_PROP_STRING, val, nval);
  
-       return -ENXIO;
+       return pset_prop_read_array(to_pset(fwnode), propname,
+                                   DEV_PROP_STRING, val, nval);
  }
  EXPORT_SYMBOL_GPL(fwnode_property_read_string_array);
  
@@@ -365,7 -455,7 +455,7 @@@ int fwnode_property_read_string(struct 
                                const char *propname, const char **val)
  {
        if (is_of_node(fwnode))
 -              return of_property_read_string(of_node(fwnode),propname, val);
 +              return of_property_read_string(of_node(fwnode), propname, val);
        else if (is_acpi_node(fwnode))
                return acpi_dev_prop_read(acpi_node(fwnode), propname,
                                          DEV_PROP_STRING, val, 1);
@@@ -143,8 -143,10 +143,8 @@@ static int dw_i2c_probe(struct platform
        u32 clk_freq, ht = 0;
  
        irq = platform_get_irq(pdev, 0);
 -      if (irq < 0) {
 -              dev_err(&pdev->dev, "no irq resource?\n");
 -              return irq; /* -ENXIO */
 -      }
 +      if (irq < 0)
 +              return irq;
  
        dev = devm_kzalloc(&pdev->dev, sizeof(struct dw_i2c_dev), GFP_KERNEL);
        if (!dev)
        /* fast mode by default because of legacy reasons */
        clk_freq = 400000;
  
-       if (ACPI_COMPANION(&pdev->dev)) {
+       if (has_acpi_companion(&pdev->dev)) {
                dw_i2c_acpi_configure(pdev);
        } else if (pdev->dev.of_node) {
                of_property_read_u32(pdev->dev.of_node,
@@@ -284,7 -286,7 +284,7 @@@ static int dw_i2c_remove(struct platfor
        pm_runtime_put(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
  
-       if (ACPI_COMPANION(&pdev->dev))
+       if (has_acpi_companion(&pdev->dev))
                dw_i2c_acpi_unconfigure(pdev);
  
        return 0;
diff --combined drivers/i2c/i2c-core.c
@@@ -133,7 -133,7 +133,7 @@@ static acpi_status acpi_i2c_add_device(
                return AE_OK;
  
        memset(&info, 0, sizeof(info));
-       info.acpi_node.companion = adev;
+       info.fwnode = acpi_fwnode_handle(adev);
        info.irq = -1;
  
        INIT_LIST_HEAD(&resource_list);
@@@ -561,7 -561,7 +561,7 @@@ static int i2c_generic_recovery(struct 
        int i = 0, val = 1, ret = 0;
  
        if (bri->prepare_recovery)
 -              bri->prepare_recovery(bri);
 +              bri->prepare_recovery(adap);
  
        /*
         * By this time SCL is high, as we need to give 9 falling-rising edges
        }
  
        if (bri->unprepare_recovery)
 -              bri->unprepare_recovery(bri);
 +              bri->unprepare_recovery(adap);
  
        return ret;
  }
@@@ -971,7 -971,7 +971,7 @@@ i2c_new_device(struct i2c_adapter *adap
        client->dev.bus = &i2c_bus_type;
        client->dev.type = &i2c_client_type;
        client->dev.of_node = info->of_node;
-       ACPI_COMPANION_SET(&client->dev, info->acpi_node.companion);
+       client->dev.fwnode = info->fwnode;
  
        i2c_dev_set_name(adap, client);
        status = device_register(&client->dev);
@@@ -1875,13 -1875,6 +1875,13 @@@ static int __init i2c_init(void
  {
        int retval;
  
 +      retval = of_alias_get_highest_id("i2c");
 +
 +      down_write(&__i2c_board_lock);
 +      if (retval >= __i2c_first_dynamic_bus_num)
 +              __i2c_first_dynamic_bus_num = retval + 1;
 +      up_write(&__i2c_board_lock);
 +
        retval = bus_register(&i2c_bus_type);
        if (retval)
                return retval;
@@@ -1933,65 -1926,6 +1933,65 @@@ module_exit(i2c_exit)
   * ----------------------------------------------------
   */
  
 +/* Check if val is exceeding the quirk IFF quirk is non 0 */
 +#define i2c_quirk_exceeded(val, quirk) ((quirk) && ((val) > (quirk)))
 +
 +static int i2c_quirk_error(struct i2c_adapter *adap, struct i2c_msg *msg, char *err_msg)
 +{
 +      dev_err_ratelimited(&adap->dev, "adapter quirk: %s (addr 0x%04x, size %u, %s)\n",
 +                          err_msg, msg->addr, msg->len,
 +                          msg->flags & I2C_M_RD ? "read" : "write");
 +      return -EOPNOTSUPP;
 +}
 +
 +static int i2c_check_for_quirks(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
 +{
 +      const struct i2c_adapter_quirks *q = adap->quirks;
 +      int max_num = q->max_num_msgs, i;
 +      bool do_len_check = true;
 +
 +      if (q->flags & I2C_AQ_COMB) {
 +              max_num = 2;
 +
 +              /* special checks for combined messages */
 +              if (num == 2) {
 +                      if (q->flags & I2C_AQ_COMB_WRITE_FIRST && msgs[0].flags & I2C_M_RD)
 +                              return i2c_quirk_error(adap, &msgs[0], "1st comb msg must be write");
 +
 +                      if (q->flags & I2C_AQ_COMB_READ_SECOND && !(msgs[1].flags & I2C_M_RD))
 +                              return i2c_quirk_error(adap, &msgs[1], "2nd comb msg must be read");
 +
 +                      if (q->flags & I2C_AQ_COMB_SAME_ADDR && msgs[0].addr != msgs[1].addr)
 +                              return i2c_quirk_error(adap, &msgs[0], "comb msg only to same addr");
 +
 +                      if (i2c_quirk_exceeded(msgs[0].len, q->max_comb_1st_msg_len))
 +                              return i2c_quirk_error(adap, &msgs[0], "msg too long");
 +
 +                      if (i2c_quirk_exceeded(msgs[1].len, q->max_comb_2nd_msg_len))
 +                              return i2c_quirk_error(adap, &msgs[1], "msg too long");
 +
 +                      do_len_check = false;
 +              }
 +      }
 +
 +      if (i2c_quirk_exceeded(num, max_num))
 +              return i2c_quirk_error(adap, &msgs[0], "too many messages");
 +
 +      for (i = 0; i < num; i++) {
 +              u16 len = msgs[i].len;
 +
 +              if (msgs[i].flags & I2C_M_RD) {
 +                      if (do_len_check && i2c_quirk_exceeded(len, q->max_read_len))
 +                              return i2c_quirk_error(adap, &msgs[i], "msg too long");
 +              } else {
 +                      if (do_len_check && i2c_quirk_exceeded(len, q->max_write_len))
 +                              return i2c_quirk_error(adap, &msgs[i], "msg too long");
 +              }
 +      }
 +
 +      return 0;
 +}
 +
  /**
   * __i2c_transfer - unlocked flavor of i2c_transfer
   * @adap: Handle to I2C bus
@@@ -2009,9 -1943,6 +2009,9 @@@ int __i2c_transfer(struct i2c_adapter *
        unsigned long orig_jiffies;
        int ret, try;
  
 +      if (adap->quirks && i2c_check_for_quirks(adap, msgs, num))
 +              return -EOPNOTSUPP;
 +
        /* i2c_trace_msg gets enabled when tracepoint i2c_transfer gets
         * enabled.  This is an efficient way of keeping the for-loop from
         * being executed when not needed.
@@@ -55,7 -55,7 +55,7 @@@
  
  #include <linux/kernel.h>
  #include <linux/cpuidle.h>
 -#include <linux/clockchips.h>
 +#include <linux/tick.h>
  #include <trace/events/power.h>
  #include <linux/sched.h>
  #include <linux/notifier.h>
@@@ -217,19 -217,11 +217,11 @@@ static struct cpuidle_state byt_cstates
                .target_residency = 1,
                .enter = &intel_idle,
                .enter_freeze = intel_idle_freeze, },
-       {
-               .name = "C1E-BYT",
-               .desc = "MWAIT 0x01",
-               .flags = MWAIT2flg(0x01),
-               .exit_latency = 15,
-               .target_residency = 30,
-               .enter = &intel_idle,
-               .enter_freeze = intel_idle_freeze, },
        {
                .name = "C6N-BYT",
                .desc = "MWAIT 0x58",
                .flags = MWAIT2flg(0x58) | CPUIDLE_FLAG_TLB_FLUSHED,
-               .exit_latency = 40,
+               .exit_latency = 300,
                .target_residency = 275,
                .enter = &intel_idle,
                .enter_freeze = intel_idle_freeze, },
                .name = "C6S-BYT",
                .desc = "MWAIT 0x52",
                .flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED,
-               .exit_latency = 140,
+               .exit_latency = 500,
                .target_residency = 560,
                .enter = &intel_idle,
                .enter_freeze = intel_idle_freeze, },
                .desc = "MWAIT 0x60",
                .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
                .exit_latency = 1200,
-               .target_residency = 1500,
+               .target_residency = 4000,
                .enter = &intel_idle,
                .enter_freeze = intel_idle_freeze, },
        {
                .enter = NULL }
  };
  
+ static struct cpuidle_state cht_cstates[] = {
+       {
+               .name = "C1-CHT",
+               .desc = "MWAIT 0x00",
+               .flags = MWAIT2flg(0x00),
+               .exit_latency = 1,
+               .target_residency = 1,
+               .enter = &intel_idle,
+               .enter_freeze = intel_idle_freeze, },
+       {
+               .name = "C6N-CHT",
+               .desc = "MWAIT 0x58",
+               .flags = MWAIT2flg(0x58) | CPUIDLE_FLAG_TLB_FLUSHED,
+               .exit_latency = 80,
+               .target_residency = 275,
+               .enter = &intel_idle,
+               .enter_freeze = intel_idle_freeze, },
+       {
+               .name = "C6S-CHT",
+               .desc = "MWAIT 0x52",
+               .flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED,
+               .exit_latency = 200,
+               .target_residency = 560,
+               .enter = &intel_idle,
+               .enter_freeze = intel_idle_freeze, },
+       {
+               .name = "C7-CHT",
+               .desc = "MWAIT 0x60",
+               .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
+               .exit_latency = 1200,
+               .target_residency = 4000,
+               .enter = &intel_idle,
+               .enter_freeze = intel_idle_freeze, },
+       {
+               .name = "C7S-CHT",
+               .desc = "MWAIT 0x64",
+               .flags = MWAIT2flg(0x64) | CPUIDLE_FLAG_TLB_FLUSHED,
+               .exit_latency = 10000,
+               .target_residency = 20000,
+               .enter = &intel_idle,
+               .enter_freeze = intel_idle_freeze, },
+       {
+               .enter = NULL }
+ };
  static struct cpuidle_state ivb_cstates[] = {
        {
                .name = "C1-IVB",
@@@ -638,12 -675,12 +675,12 @@@ static int intel_idle(struct cpuidle_de
                leave_mm(cpu);
  
        if (!(lapic_timer_reliable_states & (1 << (cstate))))
 -              clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
 +              tick_broadcast_enter();
  
        mwait_idle_with_hints(eax, ecx);
  
        if (!(lapic_timer_reliable_states & (1 << (cstate))))
 -              clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
 +              tick_broadcast_exit();
  
        return index;
  }
@@@ -665,12 -702,13 +702,12 @@@ static void intel_idle_freeze(struct cp
  
  static void __setup_broadcast_timer(void *arg)
  {
 -      unsigned long reason = (unsigned long)arg;
 -      int cpu = smp_processor_id();
 -
 -      reason = reason ?
 -              CLOCK_EVT_NOTIFY_BROADCAST_ON : CLOCK_EVT_NOTIFY_BROADCAST_OFF;
 +      unsigned long on = (unsigned long)arg;
  
 -      clockevents_notify(reason, &cpu);
 +      if (on)
 +              tick_broadcast_enable();
 +      else
 +              tick_broadcast_disable();
  }
  
  static int cpu_hotplug_notify(struct notifier_block *n,
@@@ -747,6 -785,12 +784,12 @@@ static const struct idle_cpu idle_cpu_b
        .byt_auto_demotion_disable_flag = true,
  };
  
+ static const struct idle_cpu idle_cpu_cht = {
+       .state_table = cht_cstates,
+       .disable_promotion_to_c1e = true,
+       .byt_auto_demotion_disable_flag = true,
+ };
  static const struct idle_cpu idle_cpu_ivb = {
        .state_table = ivb_cstates,
        .disable_promotion_to_c1e = true,
@@@ -775,7 -819,7 +818,7 @@@ static const struct idle_cpu idle_cpu_a
  #define ICPU(model, cpu) \
        { X86_VENDOR_INTEL, 6, model, X86_FEATURE_MWAIT, (unsigned long)&cpu }
  
- static const struct x86_cpu_id intel_idle_ids[] = {
+ static const struct x86_cpu_id intel_idle_ids[] __initconst = {
        ICPU(0x1a, idle_cpu_nehalem),
        ICPU(0x1e, idle_cpu_nehalem),
        ICPU(0x1f, idle_cpu_nehalem),
        ICPU(0x2d, idle_cpu_snb),
        ICPU(0x36, idle_cpu_atom),
        ICPU(0x37, idle_cpu_byt),
+       ICPU(0x4c, idle_cpu_cht),
        ICPU(0x3a, idle_cpu_ivb),
        ICPU(0x3e, idle_cpu_ivt),
        ICPU(0x3c, idle_cpu_hsw),
  #define FTRACE_EVENTS()       . = ALIGN(8);                                   \
                        VMLINUX_SYMBOL(__start_ftrace_events) = .;      \
                        *(_ftrace_events)                               \
 -                      VMLINUX_SYMBOL(__stop_ftrace_events) = .;
 +                      VMLINUX_SYMBOL(__stop_ftrace_events) = .;       \
 +                      VMLINUX_SYMBOL(__start_ftrace_enum_maps) = .;   \
 +                      *(_ftrace_enum_map)                             \
 +                      VMLINUX_SYMBOL(__stop_ftrace_enum_maps) = .;
  #else
  #define FTRACE_EVENTS()
  #endif
  #define IOMMU_OF_TABLES()     OF_TABLE(CONFIG_OF_IOMMU, iommu)
  #define RESERVEDMEM_OF_TABLES()       OF_TABLE(CONFIG_OF_RESERVED_MEM, reservedmem)
  #define CPU_METHOD_OF_TABLES()        OF_TABLE(CONFIG_SMP, cpu_method)
+ #define CPUIDLE_METHOD_OF_TABLES() OF_TABLE(CONFIG_CPU_IDLE, cpuidle_method)
  #define EARLYCON_OF_TABLES()  OF_TABLE(CONFIG_SERIAL_EARLYCON, earlycon)
  
  #define KERNEL_DTB()                                                  \
        CLKSRC_OF_TABLES()                                              \
        IOMMU_OF_TABLES()                                               \
        CPU_METHOD_OF_TABLES()                                          \
+       CPUIDLE_METHOD_OF_TABLES()                                      \
        KERNEL_DTB()                                                    \
        IRQCHIP_OF_MATCH_TABLE()                                        \
        EARLYCON_OF_TABLES()
diff --combined include/linux/device.h
@@@ -38,6 -38,7 +38,7 @@@ struct class
  struct subsys_private;
  struct bus_type;
  struct device_node;
+ struct fwnode_handle;
  struct iommu_ops;
  struct iommu_group;
  
@@@ -650,14 -651,6 +651,6 @@@ struct device_dma_parameters 
        unsigned long segment_boundary_mask;
  };
  
- struct acpi_device;
- struct acpi_dev_node {
- #ifdef CONFIG_ACPI
-       struct acpi_device *companion;
- #endif
- };
  /**
   * struct device - The basic device structure
   * @parent:   The device's "parent" device, the device to which it is attached.
   * @cma_area: Contiguous memory area for dma allocations
   * @archdata: For arch-specific additions.
   * @of_node:  Associated device tree node.
-  * @acpi_node:        Associated ACPI device node.
+  * @fwnode:   Associated device node supplied by platform firmware.
   * @devt:     For creating the sysfs "dev".
   * @id:               device instance
   * @devres_lock: Spinlock to protect the resource of the device.
@@@ -779,7 -772,7 +772,7 @@@ struct device 
        struct dev_archdata     archdata;
  
        struct device_node      *of_node; /* associated device tree node */
-       struct acpi_dev_node    acpi_node; /* associated ACPI device node */
+       struct fwnode_handle    *fwnode; /* firmware device node */
  
        dev_t                   devt;   /* dev_t, creates the sysfs "dev" */
        u32                     id;     /* device instance */
@@@ -916,13 -909,6 +909,13 @@@ static inline void device_lock_assert(s
        lockdep_assert_held(&dev->mutex);
  }
  
 +static inline struct device_node *dev_of_node(struct device *dev)
 +{
 +      if (!IS_ENABLED(CONFIG_OF))
 +              return NULL;
 +      return dev->of_node;
 +}
 +
  void driver_init(void);
  
  /*
@@@ -954,6 -940,9 +947,9 @@@ extern void unlock_device_hotplug(void)
  extern int lock_device_hotplug_sysfs(void);
  extern int device_offline(struct device *dev);
  extern int device_online(struct device *dev);
+ extern void set_primary_fwnode(struct device *dev, struct fwnode_handle *fwnode);
+ extern void set_secondary_fwnode(struct device *dev, struct fwnode_handle *fwnode);
  /*
   * Root device objects for grouping under /sys/devices
   */
diff --combined include/linux/i2c.h
@@@ -253,10 -253,10 +253,10 @@@ static inline void i2c_set_clientdata(s
  
  #if IS_ENABLED(CONFIG_I2C_SLAVE)
  enum i2c_slave_event {
 -      I2C_SLAVE_REQ_READ_START,
 -      I2C_SLAVE_REQ_READ_END,
 -      I2C_SLAVE_REQ_WRITE_START,
 -      I2C_SLAVE_REQ_WRITE_END,
 +      I2C_SLAVE_READ_REQUESTED,
 +      I2C_SLAVE_WRITE_REQUESTED,
 +      I2C_SLAVE_READ_PROCESSED,
 +      I2C_SLAVE_WRITE_RECEIVED,
        I2C_SLAVE_STOP,
  };
  
@@@ -278,7 -278,7 +278,7 @@@ static inline int i2c_slave_event(struc
   * @platform_data: stored in i2c_client.dev.platform_data
   * @archdata: copied into i2c_client.dev.archdata
   * @of_node: pointer to OpenFirmware device node
-  * @acpi_node: ACPI device node
+  * @fwnode: device node supplied by the platform firmware
   * @irq: stored in i2c_client.irq
   *
   * I2C doesn't actually support hardware probing, although controllers and
@@@ -299,7 -299,7 +299,7 @@@ struct i2c_board_info 
        void            *platform_data;
        struct dev_archdata     *archdata;
        struct device_node *of_node;
-       struct acpi_dev_node acpi_node;
+       struct fwnode_handle *fwnode;
        int             irq;
  };
  
@@@ -435,8 -435,8 +435,8 @@@ struct i2c_bus_recovery_info 
        void (*set_scl)(struct i2c_adapter *, int val);
        int (*get_sda)(struct i2c_adapter *);
  
 -      void (*prepare_recovery)(struct i2c_bus_recovery_info *bri);
 -      void (*unprepare_recovery)(struct i2c_bus_recovery_info *bri);
 +      void (*prepare_recovery)(struct i2c_adapter *);
 +      void (*unprepare_recovery)(struct i2c_adapter *);
  
        /* gpio recovery */
        int scl_gpio;
@@@ -449,48 -449,6 +449,48 @@@ int i2c_recover_bus(struct i2c_adapter 
  int i2c_generic_gpio_recovery(struct i2c_adapter *adap);
  int i2c_generic_scl_recovery(struct i2c_adapter *adap);
  
 +/**
 + * struct i2c_adapter_quirks - describe flaws of an i2c adapter
 + * @flags: see I2C_AQ_* for possible flags and read below
 + * @max_num_msgs: maximum number of messages per transfer
 + * @max_write_len: maximum length of a write message
 + * @max_read_len: maximum length of a read message
 + * @max_comb_1st_msg_len: maximum length of the first msg in a combined message
 + * @max_comb_2nd_msg_len: maximum length of the second msg in a combined message
 + *
 + * Note about combined messages: Some I2C controllers can only send one message
 + * per transfer, plus something called combined message or write-then-read.
 + * This is (usually) a small write message followed by a read message and
 + * barely enough to access register based devices like EEPROMs. There is a flag
 + * to support this mode. It implies max_num_msg = 2 and does the length checks
 + * with max_comb_*_len because combined message mode usually has its own
 + * limitations. Because of HW implementations, some controllers can actually do
 + * write-then-anything or other variants. To support that, write-then-read has
 + * been broken out into smaller bits like write-first and read-second which can
 + * be combined as needed.
 + */
 +
 +struct i2c_adapter_quirks {
 +      u64 flags;
 +      int max_num_msgs;
 +      u16 max_write_len;
 +      u16 max_read_len;
 +      u16 max_comb_1st_msg_len;
 +      u16 max_comb_2nd_msg_len;
 +};
 +
 +/* enforce max_num_msgs = 2 and use max_comb_*_len for length checks */
 +#define I2C_AQ_COMB                   BIT(0)
 +/* first combined message must be write */
 +#define I2C_AQ_COMB_WRITE_FIRST               BIT(1)
 +/* second combined message must be read */
 +#define I2C_AQ_COMB_READ_SECOND               BIT(2)
 +/* both combined messages must have the same target address */
 +#define I2C_AQ_COMB_SAME_ADDR         BIT(3)
 +/* convenience macro for typical write-then read case */
 +#define I2C_AQ_COMB_WRITE_THEN_READ   (I2C_AQ_COMB | I2C_AQ_COMB_WRITE_FIRST | \
 +                                       I2C_AQ_COMB_READ_SECOND | I2C_AQ_COMB_SAME_ADDR)
 +
  /*
   * i2c_adapter is the structure used to identify a physical i2c bus along
   * with the access algorithms necessary to access it.
@@@ -516,7 -474,6 +516,7 @@@ struct i2c_adapter 
        struct list_head userspace_clients;
  
        struct i2c_bus_recovery_info *bus_recovery_info;
 +      const struct i2c_adapter_quirks *quirks;
  };
  #define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev)