Merge branches 'acpi-config', 'acpi-osl', 'acpi-utils' and 'acpi-tables'
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Mon, 8 Dec 2014 18:51:12 +0000 (19:51 +0100)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Mon, 8 Dec 2014 18:51:12 +0000 (19:51 +0100)
* acpi-config:
  ACPI / Kconfig: Remove redundant depends on ACPI

* acpi-osl:
  ACPI / OSL: Add IRQ handler flushing support in the OSL.
  ACPI / osl: speedup grace period in acpi_os_map_cleanup

* acpi-utils:
  ACPI: remove unnecessary sizeof(u8)

* acpi-tables:
  ACPI / table: Always count matched and successfully parsed entries
  ACPI / table: Add new function to get table entries

233 files changed:
Documentation/acpi/gpio-properties.txt [new file with mode: 0644]
Documentation/gpio/consumer.txt
Documentation/networking/timestamping.txt
MAINTAINERS
Makefile
arch/arm/boot/dts/exynos5250-snow.dts
arch/arm/boot/dts/exynos5250.dtsi
arch/arm/configs/exynos_defconfig
arch/arm/include/asm/thread_info.h
arch/arm/kernel/traps.c
arch/arm/kvm/mmu.c
arch/arm/mach-mvebu/coherency.c
arch/arm/mach-s3c24xx/h1940-bluetooth.c
arch/arm/mach-s3c24xx/h1940.h
arch/arm/mach-s3c24xx/mach-h1940.c
arch/arm/mach-s3c24xx/mach-rx1950.c
arch/arm/mach-tegra/irq.c
arch/arm/mm/proc-v7.S
arch/arm/mm/proc-xscale.S
arch/arm/plat-orion/gpio.c
arch/arm/plat-orion/include/plat/orion-gpio.h
arch/arm64/kvm/sys_regs.c
arch/ia64/kvm/kvm-ia64.c
arch/mips/Kconfig
arch/mips/include/asm/mipsregs.h
arch/mips/include/asm/r4kcache.h
arch/mips/include/asm/uaccess.h
arch/mips/include/uapi/asm/unistd.h
arch/mips/kernel/bmips_vec.S
arch/mips/kernel/cps-vec.S
arch/mips/kernel/cpu-probe.c
arch/mips/kernel/rtlx.c
arch/mips/kernel/setup.c
arch/mips/kernel/signal.c
arch/mips/loongson/common/Makefile
arch/mips/mm/tlbex.c
arch/mips/mti-sead3/sead3-leds.c
arch/mips/netlogic/xlp/Makefile
arch/powerpc/include/asm/pci-bridge.h
arch/powerpc/kernel/eeh_sysfs.c
arch/powerpc/kernel/pci_64.c
arch/powerpc/kernel/vdso32/getcpu.S
arch/powerpc/platforms/powernv/opal-hmi.c
arch/powerpc/platforms/powernv/pci-ioda.c
arch/powerpc/platforms/powernv/pci.c
arch/powerpc/platforms/pseries/msi.c
arch/powerpc/xmon/xmon.c
arch/s390/kernel/nmi.c
arch/sparc/include/asm/dma-mapping.h
arch/x86/boot/compressed/Makefile
arch/x86/kernel/cpu/microcode/core.c
arch/x86/kvm/mmu.c
block/bio-integrity.c
drivers/acpi/Kconfig
drivers/acpi/Makefile
drivers/acpi/internal.h
drivers/acpi/osl.c
drivers/acpi/property.c [new file with mode: 0644]
drivers/acpi/scan.c
drivers/acpi/utils.c
drivers/acpi/video.c
drivers/ata/ahci.c
drivers/ata/sata_fsl.c
drivers/atm/solos-pci.c
drivers/base/Makefile
drivers/base/property.c [new file with mode: 0644]
drivers/clk/at91/clk-usb.c
drivers/clk/clk-divider.c
drivers/clk/pxa/clk-pxa27x.c
drivers/clk/qcom/mmcc-apq8084.c
drivers/clk/rockchip/clk.c
drivers/gpio/devres.c
drivers/gpio/gpio-sch.c
drivers/gpio/gpiolib-acpi.c
drivers/gpio/gpiolib.c
drivers/gpio/gpiolib.h
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/nouveau/core/engine/device/nvc0.c
drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c
drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c
drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c
drivers/gpu/drm/nouveau/nouveau_drm.c
drivers/gpu/drm/nouveau/nouveau_fence.c
drivers/gpu/drm/nouveau/nouveau_fence.h
drivers/gpu/drm/radeon/radeon_connectors.c
drivers/gpu/drm/radeon/radeon_cs.c
drivers/gpu/drm/radeon/radeon_irq_kms.c
drivers/gpu/drm/radeon/radeon_kms.c
drivers/gpu/drm/radeon/radeon_object.c
drivers/hwmon/g762.c
drivers/i2c/busses/i2c-cadence.c
drivers/i2c/busses/i2c-davinci.c
drivers/i2c/busses/i2c-designware-core.c
drivers/i2c/busses/i2c-omap.c
drivers/iio/accel/bmc150-accel.c
drivers/iio/accel/kxcjk-1013.c
drivers/iio/adc/men_z188_adc.c
drivers/iio/gyro/bmg160.c
drivers/input/evdev.c
drivers/input/joystick/xpad.c
drivers/input/keyboard/gpio_keys_polled.c
drivers/input/mouse/elantech.c
drivers/input/mouse/synaptics.c
drivers/irqchip/irq-atmel-aic-common.c
drivers/irqchip/irq-bcm7120-l2.c
drivers/irqchip/irq-brcmstb-l2.c
drivers/leds/leds-gpio.c
drivers/media/i2c/smiapp/smiapp-core.c
drivers/media/pci/cx23885/cx23885-core.c
drivers/media/pci/solo6x10/solo6x10-core.c
drivers/media/rc/ir-rc6-decoder.c
drivers/media/usb/s2255/s2255drv.c
drivers/misc/eeprom/at25.c
drivers/net/bonding/bond_netlink.c
drivers/net/dsa/bcm_sf2.c
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/intel/igb/igb_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
drivers/net/ethernet/renesas/sh_eth.c
drivers/net/ethernet/renesas/sh_eth.h
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
drivers/net/vxlan.c
drivers/net/wireless/iwlwifi/iwl-fw.h
drivers/net/wireless/iwlwifi/mvm/mac80211.c
drivers/net/wireless/rtlwifi/pci.c
drivers/net/wireless/rtlwifi/rtl8821ae/hw.c
drivers/net/xen-netback/xenbus.c
drivers/net/xen-netfront.c
drivers/of/base.c
drivers/of/fdt.c
drivers/pci/host/pci-tegra.c
drivers/pci/msi.c
drivers/scsi/bnx2fc/bnx2fc_fcoe.c
drivers/scsi/scsi_devinfo.c
drivers/scsi/ufs/ufshcd-pltfrm.c
drivers/scsi/ufs/ufshcd.c
drivers/scsi/ufs/ufshcd.h
drivers/spi/spi-dw.c
drivers/spi/spi-sirf.c
drivers/spi/spi.c
drivers/staging/rtl8188eu/core/rtw_cmd.c
drivers/staging/rtl8188eu/core/rtw_mlme_ext.c
drivers/staging/rtl8188eu/core/rtw_wlan_util.c
drivers/staging/rtl8188eu/os_dep/usb_intf.c
drivers/thermal/cpu_cooling.c
drivers/thermal/samsung/exynos_thermal_common.c
drivers/thermal/st/st_thermal.c
drivers/tty/serial/of_serial.c
drivers/usb/core/quirks.c
drivers/usb/dwc3/ep0.c
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-plat.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
drivers/usb/serial/cp210x.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio_ids.h
drivers/usb/serial/keyspan.c
drivers/usb/serial/ssu100.c
drivers/usb/storage/unusual_uas.h
drivers/watchdog/s3c2410_wdt.c
fs/aio.c
fs/btrfs/compression.c
fs/btrfs/compression.h
fs/btrfs/lzo.c
fs/btrfs/zlib.c
fs/fat/namei_vfat.c
fs/jbd2/journal.c
fs/nfsd/nfs4callback.c
fs/nfsd/nfsd.h
include/acpi/acpi_bus.h
include/dt-bindings/clock/qcom,mmcc-apq8084.h
include/linux/acpi.h
include/linux/clk-provider.h
include/linux/gpio/consumer.h
include/linux/gpio_keys.h
include/linux/iio/events.h
include/linux/kvm_host.h
include/linux/leds.h
include/linux/of.h
include/linux/pci.h
include/linux/property.h [new file with mode: 0644]
include/net/inet_common.h
include/sound/pcm.h
include/uapi/linux/Kbuild
include/uapi/sound/asound.h
ipc/sem.c
kernel/sched/core.c
lib/genalloc.c
lib/show_mem.c
mm/frontswap.c
mm/memory.c
mm/mmap.c
mm/rmap.c
mm/slab.c
mm/vmpressure.c
net/bridge/br_netlink.c
net/core/rtnetlink.c
net/ipv4/af_inet.c
net/ipv4/ip_vti.c
net/ipv4/ping.c
net/ipv4/tcp.c
net/ipv4/tcp_ipv4.c
net/ipv6/ip6_gre.c
net/ipv6/ip6_offload.c
net/ipv6/ip6_udp_tunnel.c
net/ipv6/ip6_vti.c
net/ipv6/tcp_ipv6.c
net/netfilter/nf_conntrack_core.c
net/packet/af_packet.c
net/rfkill/rfkill-gpio.c
net/sunrpc/svcsock.c
security/keys/internal.h
security/keys/keyctl.c
security/keys/keyring.c
security/keys/request_key.c
security/keys/request_key_auth.c
sound/core/pcm.c
sound/core/pcm_misc.c
sound/pci/hda/hda_intel.c
sound/pci/hda/hda_priv.h
sound/pci/hda/patch_realtek.c
sound/usb/mixer_quirks.c
sound/usb/quirks.c
virt/kvm/arm/vgic.c
virt/kvm/kvm_main.c

diff --git a/Documentation/acpi/gpio-properties.txt b/Documentation/acpi/gpio-properties.txt
new file mode 100644 (file)
index 0000000..ae36fcf
--- /dev/null
@@ -0,0 +1,96 @@
+_DSD Device Properties Related to GPIO
+--------------------------------------
+
+With the release of ACPI 5.1 and the _DSD configuration objecte names
+can finally be given to GPIOs (and other things as well) returned by
+_CRS.  Previously, we were only able to use an integer index to find
+the corresponding GPIO, which is pretty error prone (it depends on
+the _CRS output ordering, for example).
+
+With _DSD we can now query GPIOs using a name instead of an integer
+index, like the ASL example below shows:
+
+  // Bluetooth device with reset and shutdown GPIOs
+  Device (BTH)
+  {
+      Name (_HID, ...)
+
+      Name (_CRS, ResourceTemplate ()
+      {
+          GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,
+                  "\\_SB.GPO0", 0, ResourceConsumer) {15}
+          GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,
+                  "\\_SB.GPO0", 0, ResourceConsumer) {27, 31}
+      })
+
+      Name (_DSD, Package ()
+      {
+          ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+          Package ()
+         {
+              Package () {"reset-gpio", Package() {^BTH, 1, 1, 0 }},
+              Package () {"shutdown-gpio", Package() {^BTH, 0, 0, 0 }},
+          }
+      })
+  }
+
+The format of the supported GPIO property is:
+
+  Package () { "name", Package () { ref, index, pin, active_low }}
+
+  ref - The device that has _CRS containing GpioIo()/GpioInt() resources,
+        typically this is the device itself (BTH in our case).
+  index - Index of the GpioIo()/GpioInt() resource in _CRS starting from zero.
+  pin - Pin in the GpioIo()/GpioInt() resource. Typically this is zero.
+  active_low - If 1 the GPIO is marked as active_low.
+
+Since ACPI GpioIo() resource does not have a field saying whether it is
+active low or high, the "active_low" argument can be used here.  Setting
+it to 1 marks the GPIO as active low.
+
+In our Bluetooth example the "reset-gpio" refers to the second GpioIo()
+resource, second pin in that resource with the GPIO number of 31.
+
+ACPI GPIO Mappings Provided by Drivers
+--------------------------------------
+
+There are systems in which the ACPI tables do not contain _DSD but provide _CRS
+with GpioIo()/GpioInt() resources and device drivers still need to work with
+them.
+
+In those cases ACPI device identification objects, _HID, _CID, _CLS, _SUB, _HRV,
+available to the driver can be used to identify the device and that is supposed
+to be sufficient to determine the meaning and purpose of all of the GPIO lines
+listed by the GpioIo()/GpioInt() resources returned by _CRS.  In other words,
+the driver is supposed to know what to use the GpioIo()/GpioInt() resources for
+once it has identified the device.  Having done that, it can simply assign names
+to the GPIO lines it is going to use and provide the GPIO subsystem with a
+mapping between those names and the ACPI GPIO resources corresponding to them.
+
+To do that, the driver needs to define a mapping table as a NULL-terminated
+array of struct acpi_gpio_mapping objects that each contain a name, a pointer
+to an array of line data (struct acpi_gpio_params) objects and the size of that
+array.  Each struct acpi_gpio_params object consists of three fields,
+crs_entry_index, line_index, active_low, representing the index of the target
+GpioIo()/GpioInt() resource in _CRS starting from zero, the index of the target
+line in that resource starting from zero, and the active-low flag for that line,
+respectively, in analogy with the _DSD GPIO property format specified above.
+
+For the example Bluetooth device discussed previously the data structures in
+question would look like this:
+
+static const struct acpi_gpio_params reset_gpio = { 1, 1, false };
+static const struct acpi_gpio_params shutdown_gpio = { 0, 0, false };
+
+static const struct acpi_gpio_mapping bluetooth_acpi_gpios[] = {
+  { "reset-gpio", &reset_gpio, 1 },
+  { "shutdown-gpio", &shutdown_gpio, 1 },
+  { },
+};
+
+Next, the mapping table needs to be passed as the second argument to
+acpi_dev_add_driver_gpios() that will register it with the ACPI device object
+pointed to by its first argument.  That should be done in the driver's .probe()
+routine.  On removal, the driver should unregister its GPIO mapping table by
+calling acpi_dev_remove_driver_gpios() on the ACPI device object where that
+table was previously registered.
index 6ce5441..859918d 100644 (file)
@@ -219,6 +219,24 @@ part of the IRQ interface, e.g. IRQF_TRIGGER_FALLING, as are system wakeup
 capabilities.
 
 
+GPIOs and ACPI
+==============
+
+On ACPI systems, GPIOs are described by GpioIo()/GpioInt() resources listed by
+the _CRS configuration objects of devices.  Those resources do not provide
+connection IDs (names) for GPIOs, so it is necessary to use an additional
+mechanism for this purpose.
+
+Systems compliant with ACPI 5.1 or newer may provide a _DSD configuration object
+which, among other things, may be used to provide connection IDs for specific
+GPIOs described by the GpioIo()/GpioInt() resources in _CRS.  If that is the
+case, it will be handled by the GPIO subsystem automatically.  However, if the
+_DSD is not present, the mappings between GpioIo()/GpioInt() resources and GPIO
+connection IDs need to be provided by device drivers.
+
+For details refer to Documentation/acpi/gpio-properties.txt
+
+
 Interacting With the Legacy GPIO Subsystem
 ==========================================
 Many kernel subsystems still handle GPIOs using the legacy integer-based
index 412f45c..1d6d02d 100644 (file)
@@ -136,7 +136,7 @@ SOF_TIMESTAMPING_OPT_ID:
 
   This option is implemented only for transmit timestamps. There, the
   timestamp is always looped along with a struct sock_extended_err.
-  The option modifies field ee_info to pass an id that is unique
+  The option modifies field ee_data to pass an id that is unique
   among all possibly concurrently outstanding timestamp requests for
   that socket. In practice, it is a monotonically increasing u32
   (that wraps).
index 0ff630d..c721042 100644 (file)
@@ -1828,7 +1828,7 @@ F:        include/net/ax25.h
 F:     net/ax25/
 
 AZ6007 DVB DRIVER
-M:     Mauro Carvalho Chehab <m.chehab@samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 L:     linux-media@vger.kernel.org
 W:     http://linuxtv.org
 T:     git git://linuxtv.org/media_tree.git
@@ -2198,7 +2198,7 @@ F:        Documentation/filesystems/btrfs.txt
 F:     fs/btrfs/
 
 BTTV VIDEO4LINUX DRIVER
-M:     Mauro Carvalho Chehab <m.chehab@samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 L:     linux-media@vger.kernel.org
 W:     http://linuxtv.org
 T:     git git://linuxtv.org/media_tree.git
@@ -2719,7 +2719,7 @@ F:        drivers/media/common/cx2341x*
 F:     include/media/cx2341x*
 
 CX88 VIDEO4LINUX DRIVER
-M:     Mauro Carvalho Chehab <m.chehab@samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 L:     linux-media@vger.kernel.org
 W:     http://linuxtv.org
 T:     git git://linuxtv.org/media_tree.git
@@ -3402,7 +3402,7 @@ F:        fs/ecryptfs/
 EDAC-CORE
 M:     Doug Thompson <dougthompson@xmission.com>
 M:     Borislav Petkov <bp@alien8.de>
-M:     Mauro Carvalho Chehab <m.chehab@samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 L:     linux-edac@vger.kernel.org
 W:     bluesmoke.sourceforge.net
 S:     Supported
@@ -3451,7 +3451,7 @@ S:        Maintained
 F:     drivers/edac/e7xxx_edac.c
 
 EDAC-GHES
-M:     Mauro Carvalho Chehab <m.chehab@samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 L:     linux-edac@vger.kernel.org
 W:     bluesmoke.sourceforge.net
 S:     Maintained
@@ -3479,21 +3479,21 @@ S:      Maintained
 F:     drivers/edac/i5000_edac.c
 
 EDAC-I5400
-M:     Mauro Carvalho Chehab <m.chehab@samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 L:     linux-edac@vger.kernel.org
 W:     bluesmoke.sourceforge.net
 S:     Maintained
 F:     drivers/edac/i5400_edac.c
 
 EDAC-I7300
-M:     Mauro Carvalho Chehab <m.chehab@samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 L:     linux-edac@vger.kernel.org
 W:     bluesmoke.sourceforge.net
 S:     Maintained
 F:     drivers/edac/i7300_edac.c
 
 EDAC-I7CORE
-M:     Mauro Carvalho Chehab <m.chehab@samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 L:     linux-edac@vger.kernel.org
 W:     bluesmoke.sourceforge.net
 S:     Maintained
@@ -3536,7 +3536,7 @@ S:        Maintained
 F:     drivers/edac/r82600_edac.c
 
 EDAC-SBRIDGE
-M:     Mauro Carvalho Chehab <m.chehab@samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 L:     linux-edac@vger.kernel.org
 W:     bluesmoke.sourceforge.net
 S:     Maintained
@@ -3596,7 +3596,7 @@ S:        Maintained
 F:     drivers/net/ethernet/ibm/ehea/
 
 EM28XX VIDEO4LINUX DRIVER
-M:     Mauro Carvalho Chehab <m.chehab@samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 L:     linux-media@vger.kernel.org
 W:     http://linuxtv.org
 T:     git git://linuxtv.org/media_tree.git
@@ -5962,7 +5962,7 @@ S:        Maintained
 F:     drivers/media/radio/radio-maxiradio*
 
 MEDIA INPUT INFRASTRUCTURE (V4L/DVB)
-M:     Mauro Carvalho Chehab <m.chehab@samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 P:     LinuxTV.org Project
 L:     linux-media@vger.kernel.org
 W:     http://linuxtv.org
@@ -8013,7 +8013,7 @@ S:        Odd Fixes
 F:     drivers/media/i2c/saa6588*
 
 SAA7134 VIDEO4LINUX DRIVER
-M:     Mauro Carvalho Chehab <m.chehab@samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 L:     linux-media@vger.kernel.org
 W:     http://linuxtv.org
 T:     git git://linuxtv.org/media_tree.git
@@ -8471,7 +8471,7 @@ S:        Maintained
 F:     drivers/media/radio/si4713/radio-usb-si4713.c
 
 SIANO DVB DRIVER
-M:     Mauro Carvalho Chehab <m.chehab@samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 L:     linux-media@vger.kernel.org
 W:     http://linuxtv.org
 T:     git git://linuxtv.org/media_tree.git
@@ -8682,7 +8682,9 @@ S:        Maintained
 F:     drivers/leds/leds-net48xx.c
 
 SOFTLOGIC 6x10 MPEG CODEC
-M:     Ismael Luceno <ismael.luceno@corp.bluecherry.net>
+M:     Bluecherry Maintainers <maintainers@bluecherrydvr.com>
+M:     Andrey Utkin <andrey.utkin@corp.bluecherry.net>
+M:     Andrey Utkin <andrey.krieger.utkin@gmail.com>
 L:     linux-media@vger.kernel.org
 S:     Supported
 F:     drivers/media/pci/solo6x10/
@@ -9156,7 +9158,7 @@ S:        Maintained
 F:     drivers/media/i2c/tda9840*
 
 TEA5761 TUNER DRIVER
-M:     Mauro Carvalho Chehab <m.chehab@samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 L:     linux-media@vger.kernel.org
 W:     http://linuxtv.org
 T:     git git://linuxtv.org/media_tree.git
@@ -9164,7 +9166,7 @@ S:        Odd fixes
 F:     drivers/media/tuners/tea5761.*
 
 TEA5767 TUNER DRIVER
-M:     Mauro Carvalho Chehab <m.chehab@samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 L:     linux-media@vger.kernel.org
 W:     http://linuxtv.org
 T:     git git://linuxtv.org/media_tree.git
@@ -9476,7 +9478,7 @@ F:        include/linux/shmem_fs.h
 F:     mm/shmem.c
 
 TM6000 VIDEO4LINUX DRIVER
-M:     Mauro Carvalho Chehab <m.chehab@samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 L:     linux-media@vger.kernel.org
 W:     http://linuxtv.org
 T:     git git://linuxtv.org/media_tree.git
@@ -10297,7 +10299,7 @@ S:      Maintained
 F:     arch/x86/kernel/cpu/mcheck/*
 
 XC2028/3028 TUNER DRIVER
-M:     Mauro Carvalho Chehab <m.chehab@samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 L:     linux-media@vger.kernel.org
 W:     http://linuxtv.org
 T:     git git://linuxtv.org/media_tree.git
index 2fd5c4e..fd80c6e 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 18
 SUBLEVEL = 0
-EXTRAVERSION = -rc6
+EXTRAVERSION =
 NAME = Diseased Newt
 
 # *DOCUMENTATION*
index e51fcef..60429ad 100644 (file)
        num-cs = <1>;
 };
 
+&usbdrd_dwc3 {
+       dr_mode = "host";
+};
+
 #include "cros-ec-keyboard.dtsi"
index f21b9aa..d55c1a2 100644 (file)
                #size-cells = <1>;
                ranges;
 
-               dwc3 {
+               usbdrd_dwc3: dwc3 {
                        compatible = "synopsys,dwc3";
                        reg = <0x12000000 0x10000>;
                        interrupts = <0 72 0>;
index 72058b8..e21ef83 100644 (file)
@@ -142,11 +142,13 @@ CONFIG_MMC_DW_IDMAC=y
 CONFIG_MMC_DW_EXYNOS=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_MAX77686=y
+CONFIG_RTC_DRV_MAX77802=y
 CONFIG_RTC_DRV_S5M=y
 CONFIG_RTC_DRV_S3C=y
 CONFIG_DMADEVICES=y
 CONFIG_PL330_DMA=y
 CONFIG_COMMON_CLK_MAX77686=y
+CONFIG_COMMON_CLK_MAX77802=y
 CONFIG_COMMON_CLK_S2MPS11=y
 CONFIG_EXYNOS_IOMMU=y
 CONFIG_IIO=y
index fc44d37..ce73ab6 100644 (file)
@@ -44,16 +44,6 @@ struct cpu_context_save {
        __u32   extra[2];               /* Xscale 'acc' register, etc */
 };
 
-struct arm_restart_block {
-       union {
-               /* For user cache flushing */
-               struct {
-                       unsigned long start;
-                       unsigned long end;
-               } cache;
-       };
-};
-
 /*
  * low level task data that entry.S needs immediate access to.
  * __switch_to() assumes cpu_context follows immediately after cpu_domain.
@@ -79,7 +69,6 @@ struct thread_info {
        unsigned long           thumbee_state;  /* ThumbEE Handler Base register */
 #endif
        struct restart_block    restart_block;
-       struct arm_restart_block        arm_restart_block;
 };
 
 #define INIT_THREAD_INFO(tsk)                                          \
index 0c8b108..9f5d818 100644 (file)
@@ -533,8 +533,6 @@ static int bad_syscall(int n, struct pt_regs *regs)
        return regs->ARM_r0;
 }
 
-static long do_cache_op_restart(struct restart_block *);
-
 static inline int
 __do_cache_op(unsigned long start, unsigned long end)
 {
@@ -543,24 +541,8 @@ __do_cache_op(unsigned long start, unsigned long end)
        do {
                unsigned long chunk = min(PAGE_SIZE, end - start);
 
-               if (signal_pending(current)) {
-                       struct thread_info *ti = current_thread_info();
-
-                       ti->restart_block = (struct restart_block) {
-                               .fn     = do_cache_op_restart,
-                       };
-
-                       ti->arm_restart_block = (struct arm_restart_block) {
-                               {
-                                       .cache = {
-                                               .start  = start,
-                                               .end    = end,
-                                       },
-                               },
-                       };
-
-                       return -ERESTART_RESTARTBLOCK;
-               }
+               if (fatal_signal_pending(current))
+                       return 0;
 
                ret = flush_cache_user_range(start, start + chunk);
                if (ret)
@@ -573,15 +555,6 @@ __do_cache_op(unsigned long start, unsigned long end)
        return 0;
 }
 
-static long do_cache_op_restart(struct restart_block *unused)
-{
-       struct arm_restart_block *restart_block;
-
-       restart_block = &current_thread_info()->arm_restart_block;
-       return __do_cache_op(restart_block->cache.start,
-                            restart_block->cache.end);
-}
-
 static inline int
 do_cache_op(unsigned long start, unsigned long end, int flags)
 {
index 57a403a..8664ff1 100644 (file)
@@ -197,7 +197,8 @@ static void unmap_range(struct kvm *kvm, pgd_t *pgdp,
        pgd = pgdp + pgd_index(addr);
        do {
                next = kvm_pgd_addr_end(addr, end);
-               unmap_puds(kvm, pgd, addr, next);
+               if (!pgd_none(*pgd))
+                       unmap_puds(kvm, pgd, addr, next);
        } while (pgd++, addr = next, addr != end);
 }
 
@@ -834,6 +835,11 @@ static bool kvm_is_write_fault(struct kvm_vcpu *vcpu)
        return kvm_vcpu_dabt_iswrite(vcpu);
 }
 
+static bool kvm_is_device_pfn(unsigned long pfn)
+{
+       return !pfn_valid(pfn);
+}
+
 static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
                          struct kvm_memory_slot *memslot, unsigned long hva,
                          unsigned long fault_status)
@@ -904,7 +910,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
        if (is_error_pfn(pfn))
                return -EFAULT;
 
-       if (kvm_is_mmio_pfn(pfn))
+       if (kvm_is_device_pfn(pfn))
                mem_type = PAGE_S2_DEVICE;
 
        spin_lock(&kvm->mmu_lock);
index 2bdc323..044b511 100644 (file)
@@ -400,6 +400,8 @@ int __init coherency_init(void)
                 type == COHERENCY_FABRIC_TYPE_ARMADA_380)
                armada_375_380_coherency_init(np);
 
+       of_node_put(np);
+
        return 0;
 }
 
index b4d14b8..9c8b127 100644 (file)
@@ -41,7 +41,7 @@ static void h1940bt_enable(int on)
                mdelay(10);
                gpio_set_value(S3C2410_GPH(1), 0);
 
-               h1940_led_blink_set(-EINVAL, GPIO_LED_BLINK, NULL, NULL);
+               h1940_led_blink_set(NULL, GPIO_LED_BLINK, NULL, NULL);
        }
        else {
                gpio_set_value(S3C2410_GPH(1), 1);
@@ -50,7 +50,7 @@ static void h1940bt_enable(int on)
                mdelay(10);
                gpio_set_value(H1940_LATCH_BLUETOOTH_POWER, 0);
 
-               h1940_led_blink_set(-EINVAL, GPIO_LED_NO_BLINK_LOW, NULL, NULL);
+               h1940_led_blink_set(NULL, GPIO_LED_NO_BLINK_LOW, NULL, NULL);
        }
 }
 
index 2950cc4..596d9f6 100644 (file)
 #define H1940_SUSPEND_RESUMEAT         (0x30081000)
 #define H1940_SUSPEND_CHECK            (0x30080000)
 
+struct gpio_desc;
+
 extern void h1940_pm_return(void);
-extern int h1940_led_blink_set(unsigned gpio, int state,
+extern int h1940_led_blink_set(struct gpio_desc *desc, int state,
                               unsigned long *delay_on,
                               unsigned long *delay_off);
 
index d35ddc1..d40d4f5 100644 (file)
@@ -359,10 +359,11 @@ static struct platform_device h1940_battery = {
 
 static DEFINE_SPINLOCK(h1940_blink_spin);
 
-int h1940_led_blink_set(unsigned gpio, int state,
+int h1940_led_blink_set(struct gpio_desc *desc, int state,
        unsigned long *delay_on, unsigned long *delay_off)
 {
        int blink_gpio, check_gpio1, check_gpio2;
+       int gpio = desc ? desc_to_gpio(desc) : -EINVAL;
 
        switch (gpio) {
        case H1940_LATCH_LED_GREEN:
index c3f2682..1d35ff3 100644 (file)
@@ -250,9 +250,10 @@ static void rx1950_disable_charger(void)
 
 static DEFINE_SPINLOCK(rx1950_blink_spin);
 
-static int rx1950_led_blink_set(unsigned gpio, int state,
+static int rx1950_led_blink_set(struct gpio_desc *desc, int state,
        unsigned long *delay_on, unsigned long *delay_off)
 {
+       int gpio = desc_to_gpio(desc);
        int blink_gpio, check_gpio;
 
        switch (gpio) {
index da7be13..ab95f53 100644 (file)
@@ -99,42 +99,42 @@ static inline void tegra_irq_write_mask(unsigned int irq, unsigned long reg)
 
 static void tegra_mask(struct irq_data *d)
 {
-       if (d->irq < FIRST_LEGACY_IRQ)
+       if (d->hwirq < FIRST_LEGACY_IRQ)
                return;
 
-       tegra_irq_write_mask(d->irq, ICTLR_CPU_IER_CLR);
+       tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IER_CLR);
 }
 
 static void tegra_unmask(struct irq_data *d)
 {
-       if (d->irq < FIRST_LEGACY_IRQ)
+       if (d->hwirq < FIRST_LEGACY_IRQ)
                return;
 
-       tegra_irq_write_mask(d->irq, ICTLR_CPU_IER_SET);
+       tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IER_SET);
 }
 
 static void tegra_ack(struct irq_data *d)
 {
-       if (d->irq < FIRST_LEGACY_IRQ)
+       if (d->hwirq < FIRST_LEGACY_IRQ)
                return;
 
-       tegra_irq_write_mask(d->irq, ICTLR_CPU_IEP_FIR_CLR);
+       tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IEP_FIR_CLR);
 }
 
 static void tegra_eoi(struct irq_data *d)
 {
-       if (d->irq < FIRST_LEGACY_IRQ)
+       if (d->hwirq < FIRST_LEGACY_IRQ)
                return;
 
-       tegra_irq_write_mask(d->irq, ICTLR_CPU_IEP_FIR_CLR);
+       tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IEP_FIR_CLR);
 }
 
 static int tegra_retrigger(struct irq_data *d)
 {
-       if (d->irq < FIRST_LEGACY_IRQ)
+       if (d->hwirq < FIRST_LEGACY_IRQ)
                return 0;
 
-       tegra_irq_write_mask(d->irq, ICTLR_CPU_IEP_FIR_SET);
+       tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IEP_FIR_SET);
 
        return 1;
 }
@@ -142,7 +142,7 @@ static int tegra_retrigger(struct irq_data *d)
 #ifdef CONFIG_PM_SLEEP
 static int tegra_set_wake(struct irq_data *d, unsigned int enable)
 {
-       u32 irq = d->irq;
+       u32 irq = d->hwirq;
        u32 index, mask;
 
        if (irq < FIRST_LEGACY_IRQ ||
index b3a9478..22ac2a6 100644 (file)
@@ -270,7 +270,6 @@ __v7_pj4b_setup:
 /* Auxiliary Debug Modes Control 1 Register */
 #define PJ4B_STATIC_BP (1 << 2) /* Enable Static BP */
 #define PJ4B_INTER_PARITY (1 << 8) /* Disable Internal Parity Handling */
-#define PJ4B_BCK_OFF_STREX (1 << 5) /* Enable the back off of STREX instr */
 #define PJ4B_CLEAN_LINE (1 << 16) /* Disable data transfer for clean line */
 
 /* Auxiliary Debug Modes Control 2 Register */
@@ -293,7 +292,6 @@ __v7_pj4b_setup:
        /* Auxiliary Debug Modes Control 1 Register */
        mrc     p15, 1, r0, c15, c1, 1
        orr     r0, r0, #PJ4B_CLEAN_LINE
-       orr     r0, r0, #PJ4B_BCK_OFF_STREX
        orr     r0, r0, #PJ4B_INTER_PARITY
        bic     r0, r0, #PJ4B_STATIC_BP
        mcr     p15, 1, r0, c15, c1, 1
index 23259f1..afa2b3c 100644 (file)
@@ -535,7 +535,7 @@ ENTRY(cpu_xscale_do_suspend)
        mrc     p15, 0, r5, c15, c1, 0  @ CP access reg
        mrc     p15, 0, r6, c13, c0, 0  @ PID
        mrc     p15, 0, r7, c3, c0, 0   @ domain ID
-       mrc     p15, 0, r8, c1, c1, 0   @ auxiliary control reg
+       mrc     p15, 0, r8, c1, c0, 1   @ auxiliary control reg
        mrc     p15, 0, r9, c1, c0, 0   @ control reg
        bic     r4, r4, #2              @ clear frequency change bit
        stmia   r0, {r4 - r9}           @ store cp regs
@@ -552,7 +552,7 @@ ENTRY(cpu_xscale_do_resume)
        mcr     p15, 0, r6, c13, c0, 0  @ PID
        mcr     p15, 0, r7, c3, c0, 0   @ domain ID
        mcr     p15, 0, r1, c2, c0, 0   @ translation table base addr
-       mcr     p15, 0, r8, c1, c1, 0   @ auxiliary control reg
+       mcr     p15, 0, r8, c1, c0, 1   @ auxiliary control reg
        mov     r0, r9                  @ control register
        b       cpu_resume_mmu
 ENDPROC(cpu_xscale_do_resume)
index e048f61..e53fc8d 100644 (file)
@@ -306,9 +306,10 @@ EXPORT_SYMBOL(orion_gpio_set_blink);
 
 #define ORION_BLINK_HALF_PERIOD 100 /* ms */
 
-int orion_gpio_led_blink_set(unsigned gpio, int state,
+int orion_gpio_led_blink_set(struct gpio_desc *desc, int state,
        unsigned long *delay_on, unsigned long *delay_off)
 {
+       unsigned gpio = desc_to_gpio(desc);
 
        if (delay_on && delay_off && !*delay_on && !*delay_off)
                *delay_on = *delay_off = ORION_BLINK_HALF_PERIOD;
index e763988..e856b07 100644 (file)
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/irqdomain.h>
+
+struct gpio_desc;
+
 /*
  * Orion-specific GPIO API extensions.
  */
 void orion_gpio_set_unused(unsigned pin);
 void orion_gpio_set_blink(unsigned pin, int blink);
-int orion_gpio_led_blink_set(unsigned gpio, int state,
+int orion_gpio_led_blink_set(struct gpio_desc *desc, int state,
        unsigned long *delay_on, unsigned long *delay_off);
 
 #define GPIO_INPUT_OK          (1 << 0)
index 4cc3b71..3d7c2df 100644 (file)
@@ -424,6 +424,11 @@ static const struct sys_reg_desc sys_reg_descs[] = {
        /* VBAR_EL1 */
        { Op0(0b11), Op1(0b000), CRn(0b1100), CRm(0b0000), Op2(0b000),
          NULL, reset_val, VBAR_EL1, 0 },
+
+       /* ICC_SRE_EL1 */
+       { Op0(0b11), Op1(0b000), CRn(0b1100), CRm(0b1100), Op2(0b101),
+         trap_raz_wi },
+
        /* CONTEXTIDR_EL1 */
        { Op0(0b11), Op1(0b000), CRn(0b1101), CRm(0b0000), Op2(0b001),
          access_vm_reg, reset_val, CONTEXTIDR_EL1, 0 },
@@ -690,6 +695,10 @@ static const struct sys_reg_desc cp15_regs[] = {
        { Op1( 0), CRn(10), CRm( 2), Op2( 1), access_vm_reg, NULL, c10_NMRR },
        { Op1( 0), CRn(10), CRm( 3), Op2( 0), access_vm_reg, NULL, c10_AMAIR0 },
        { Op1( 0), CRn(10), CRm( 3), Op2( 1), access_vm_reg, NULL, c10_AMAIR1 },
+
+       /* ICC_SRE */
+       { Op1( 0), CRn(12), CRm(12), Op2( 5), trap_raz_wi },
+
        { Op1( 0), CRn(13), CRm( 0), Op2( 1), access_vm_reg, NULL, c13_CID },
 };
 
index ec6b9ac..dbe46f4 100644 (file)
@@ -1563,7 +1563,7 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
 
        for (i = 0; i < npages; i++) {
                pfn = gfn_to_pfn(kvm, base_gfn + i);
-               if (!kvm_is_mmio_pfn(pfn)) {
+               if (!kvm_is_reserved_pfn(pfn)) {
                        kvm_set_pmt_entry(kvm, base_gfn + i,
                                        pfn << PAGE_SHIFT,
                                _PAGE_AR_RWX | _PAGE_MA_WB);
index f43aa53..9536ef9 100644 (file)
@@ -2101,9 +2101,17 @@ config 64BIT_PHYS_ADDR
 config ARCH_PHYS_ADDR_T_64BIT
        def_bool 64BIT_PHYS_ADDR
 
+choice
+       prompt "SmartMIPS or microMIPS ASE support"
+
+config CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS
+       bool "None"
+       help
+         Select this if you want neither microMIPS nor SmartMIPS support
+
 config CPU_HAS_SMARTMIPS
        depends on SYS_SUPPORTS_SMARTMIPS
-       bool "Support for the SmartMIPS ASE"
+       bool "SmartMIPS"
        help
          SmartMIPS is a extension of the MIPS32 architecture aimed at
          increased security at both hardware and software level for
@@ -2115,11 +2123,13 @@ config CPU_HAS_SMARTMIPS
 
 config CPU_MICROMIPS
        depends on SYS_SUPPORTS_MICROMIPS
-       bool "Build kernel using microMIPS ISA"
+       bool "microMIPS"
        help
          When this option is enabled the kernel will be built using the
          microMIPS ISA
 
+endchoice
+
 config CPU_HAS_MSA
        bool "Support for the MIPS SIMD Architecture (EXPERIMENTAL)"
        depends on CPU_SUPPORTS_MSA
index b46cd22..22a135a 100644 (file)
 #define MIPS_CONF6_SYND                (_ULCAST_(1) << 13)
 /* proAptiv FTLB on/off bit */
 #define MIPS_CONF6_FTLBEN      (_ULCAST_(1) << 15)
+/* FTLB probability bits */
+#define MIPS_CONF6_FTLBP_SHIFT (16)
 
 #define MIPS_CONF7_WII         (_ULCAST_(1) << 31)
 
index 4520adc..cd6e0af 100644 (file)
@@ -257,7 +257,11 @@ static inline void protected_flush_icache_line(unsigned long addr)
  */
 static inline void protected_writeback_dcache_line(unsigned long addr)
 {
+#ifdef CONFIG_EVA
+       protected_cachee_op(Hit_Writeback_Inv_D, addr);
+#else
        protected_cache_op(Hit_Writeback_Inv_D, addr);
+#endif
 }
 
 static inline void protected_writeback_scache_line(unsigned long addr)
index 133678a..22a5624 100644 (file)
@@ -1422,7 +1422,7 @@ static inline long __strnlen_user(const char __user *s, long n)
 }
 
 /*
- * strlen_user: - Get the size of a string in user space.
+ * strnlen_user: - Get the size of a string in user space.
  * @str: The string to measure.
  *
  * Context: User context only. This function may sleep.
@@ -1431,9 +1431,7 @@ static inline long __strnlen_user(const char __user *s, long n)
  *
  * Returns the size of the string INCLUDING the terminating NUL.
  * On exception, returns 0.
- *
- * If there is a limit on the length of a valid string, you may wish to
- * consider using strnlen_user() instead.
+ * If the string is too long, returns a value greater than @n.
  */
 static inline long strnlen_user(const char __user *s, long n)
 {
index 9dc5856..d001bb1 100644 (file)
 #define __NR_seccomp                   (__NR_Linux + 316)
 #define __NR_getrandom                 (__NR_Linux + 317)
 #define __NR_memfd_create              (__NR_Linux + 318)
-#define __NR_memfd_create              (__NR_Linux + 319)
+#define __NR_bpf                       (__NR_Linux + 319)
 
 /*
  * Offset of the last N32 flavoured syscall
index 290c23b..8649507 100644 (file)
@@ -208,7 +208,6 @@ bmips_reset_nmi_vec_end:
 END(bmips_reset_nmi_vec)
 
        .set    pop
-       .previous
 
 /***********************************************************************
  * CPU1 warm restart vector (used for second and subsequent boots).
@@ -281,5 +280,3 @@ LEAF(bmips_enable_xks01)
        jr      ra
 
 END(bmips_enable_xks01)
-
-       .previous
index e6e97d2..0384b05 100644 (file)
@@ -229,6 +229,7 @@ LEAF(mips_cps_core_init)
         nop
 
        .set    push
+       .set    mips32r2
        .set    mt
 
        /* Only allow 1 TC per VPE to execute... */
@@ -345,6 +346,7 @@ LEAF(mips_cps_boot_vpes)
         nop
 
        .set    push
+       .set    mips32r2
        .set    mt
 
 1:     /* Enter VPE configuration state */
index d5a4f38..dc49cf3 100644 (file)
@@ -193,6 +193,32 @@ static void set_isa(struct cpuinfo_mips *c, unsigned int isa)
 static char unknown_isa[] = KERN_ERR \
        "Unsupported ISA type, c0.config0: %d.";
 
+static unsigned int calculate_ftlb_probability(struct cpuinfo_mips *c)
+{
+
+       unsigned int probability = c->tlbsize / c->tlbsizevtlb;
+
+       /*
+        * 0 = All TLBWR instructions go to FTLB
+        * 1 = 15:1: For every 16 TBLWR instructions, 15 go to the
+        * FTLB and 1 goes to the VTLB.
+        * 2 = 7:1: As above with 7:1 ratio.
+        * 3 = 3:1: As above with 3:1 ratio.
+        *
+        * Use the linear midpoint as the probability threshold.
+        */
+       if (probability >= 12)
+               return 1;
+       else if (probability >= 6)
+               return 2;
+       else
+               /*
+                * So FTLB is less than 4 times bigger than VTLB.
+                * A 3:1 ratio can still be useful though.
+                */
+               return 3;
+}
+
 static void set_ftlb_enable(struct cpuinfo_mips *c, int enable)
 {
        unsigned int config6;
@@ -203,9 +229,14 @@ static void set_ftlb_enable(struct cpuinfo_mips *c, int enable)
        case CPU_P5600:
                /* proAptiv & related cores use Config6 to enable the FTLB */
                config6 = read_c0_config6();
+               /* Clear the old probability value */
+               config6 &= ~(3 << MIPS_CONF6_FTLBP_SHIFT);
                if (enable)
                        /* Enable FTLB */
-                       write_c0_config6(config6 | MIPS_CONF6_FTLBEN);
+                       write_c0_config6(config6 |
+                                        (calculate_ftlb_probability(c)
+                                         << MIPS_CONF6_FTLBP_SHIFT)
+                                        | MIPS_CONF6_FTLBEN);
                else
                        /* Disable FTLB */
                        write_c0_config6(config6 &  ~MIPS_CONF6_FTLBEN);
index 31b1b76..c5c4fd5 100644 (file)
@@ -94,12 +94,12 @@ int rtlx_open(int index, int can_sleep)
        int ret = 0;
 
        if (index >= RTLX_CHANNELS) {
-               pr_debug(KERN_DEBUG "rtlx_open index out of range\n");
+               pr_debug("rtlx_open index out of range\n");
                return -ENOSYS;
        }
 
        if (atomic_inc_return(&channel_wqs[index].in_open) > 1) {
-               pr_debug(KERN_DEBUG "rtlx_open channel %d already opened\n", index);
+               pr_debug("rtlx_open channel %d already opened\n", index);
                ret = -EBUSY;
                goto out_fail;
        }
index d21ec57..f3b635f 100644 (file)
@@ -485,7 +485,7 @@ static void __init bootmem_init(void)
  * NOTE: historically plat_mem_setup did the entire platform initialization.
  *      This was rather impractical because it meant plat_mem_setup had to
  * get away without any kind of memory allocator.  To keep old code from
- * breaking plat_setup was just renamed to plat_setup and a second platform
+ * breaking plat_setup was just renamed to plat_mem_setup and a second platform
  * initialization hook for anything else was introduced.
  */
 
@@ -493,7 +493,7 @@ static int usermem __initdata;
 
 static int __init early_parse_mem(char *p)
 {
-       unsigned long start, size;
+       phys_t start, size;
 
        /*
         * If a user specifies memory size, we
index 1d57605..16f1e4f 100644 (file)
@@ -658,13 +658,13 @@ static int signal_setup(void)
                save_fp_context = _save_fp_context;
                restore_fp_context = _restore_fp_context;
        } else {
-               save_fp_context = copy_fp_from_sigcontext;
-               restore_fp_context = copy_fp_to_sigcontext;
+               save_fp_context = copy_fp_to_sigcontext;
+               restore_fp_context = copy_fp_from_sigcontext;
        }
 #endif /* CONFIG_SMP */
 #else
-       save_fp_context = copy_fp_from_sigcontext;;
-       restore_fp_context = copy_fp_to_sigcontext;
+       save_fp_context = copy_fp_to_sigcontext;
+       restore_fp_context = copy_fp_from_sigcontext;
 #endif
 
        return 0;
index 0bb9cc9..d87e033 100644 (file)
@@ -11,7 +11,8 @@ obj-$(CONFIG_PCI) += pci.o
 # Serial port support
 #
 obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
-obj-$(CONFIG_SERIAL_8250) += serial.o
+loongson-serial-$(CONFIG_SERIAL_8250) := serial.o
+obj-y += $(loongson-serial-m) $(loongson-serial-y)
 obj-$(CONFIG_LOONGSON_UART_BASE) += uart_base.o
 obj-$(CONFIG_LOONGSON_MC146818) += rtc.o
 
index b5f228e..e3328a9 100644 (file)
@@ -1872,8 +1872,16 @@ build_r4000_tlbchange_handler_head(u32 **p, struct uasm_label **l,
        uasm_l_smp_pgtable_change(l, *p);
 #endif
        iPTE_LW(p, wr.r1, wr.r2); /* get even pte */
-       if (!m4kc_tlbp_war())
+       if (!m4kc_tlbp_war()) {
                build_tlb_probe_entry(p);
+               if (cpu_has_htw) {
+                       /* race condition happens, leaving */
+                       uasm_i_ehb(p);
+                       uasm_i_mfc0(p, wr.r3, C0_INDEX);
+                       uasm_il_bltz(p, r, wr.r3, label_leave);
+                       uasm_i_nop(p);
+               }
+       }
        return wr;
 }
 
index 20102a6..c427c57 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Copyright (C) 2012 MIPS Technologies, Inc.  All rights reserved.
  */
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/leds.h>
 #include <linux/platform_device.h>
 
@@ -76,8 +76,4 @@ static int __init led_init(void)
        return platform_device_register(&fled_device);
 }
 
-module_init(led_init);
-
-MODULE_AUTHOR("Chris Dearman <chris@mips.com>");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("LED probe driver for SEAD-3");
+device_initcall(led_init);
index be358a8..6b43af0 100644 (file)
@@ -1,6 +1,10 @@
 obj-y                          += setup.o nlm_hal.o cop2-ex.o dt.o
 obj-$(CONFIG_SMP)              += wakeup.o
-obj-$(CONFIG_USB)              += usb-init.o
-obj-$(CONFIG_USB)              += usb-init-xlp2.o
-obj-$(CONFIG_SATA_AHCI)                += ahci-init.o
-obj-$(CONFIG_SATA_AHCI)                += ahci-init-xlp2.o
+ifdef CONFIG_USB
+obj-y                          += usb-init.o
+obj-y                          += usb-init-xlp2.o
+endif
+ifdef CONFIG_SATA_AHCI
+obj-y                          += ahci-init.o
+obj-y                          += ahci-init-xlp2.o
+endif
index 4ca90a3..725247b 100644 (file)
@@ -159,8 +159,6 @@ struct pci_dn {
 
        int     pci_ext_config_space;   /* for pci devices */
 
-       bool    force_32bit_msi;
-
        struct  pci_dev *pcidev;        /* back-pointer to the pci device */
 #ifdef CONFIG_EEH
        struct eeh_dev *edev;           /* eeh device */
index f19b1e5..1ceecdd 100644 (file)
@@ -65,7 +65,7 @@ static ssize_t eeh_pe_state_show(struct device *dev,
                return -ENODEV;
 
        state = eeh_ops->get_state(edev->pe, NULL);
-       return sprintf(buf, "%0x08x %0x08x\n",
+       return sprintf(buf, "0x%08x 0x%08x\n",
                       state, edev->pe->state);
 }
 
index 155013d..b15194e 100644 (file)
@@ -266,13 +266,3 @@ int pcibus_to_node(struct pci_bus *bus)
 }
 EXPORT_SYMBOL(pcibus_to_node);
 #endif
-
-static void quirk_radeon_32bit_msi(struct pci_dev *dev)
-{
-       struct pci_dn *pdn = pci_get_pdn(dev);
-
-       if (pdn)
-               pdn->force_32bit_msi = true;
-}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x68f2, quirk_radeon_32bit_msi);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0xaa68, quirk_radeon_32bit_msi);
index 23eb9a9..c62be60 100644 (file)
@@ -30,8 +30,8 @@
 V_FUNCTION_BEGIN(__kernel_getcpu)
   .cfi_startproc
        mfspr   r5,SPRN_SPRG_VDSO_READ
-       cmpdi   cr0,r3,0
-       cmpdi   cr1,r4,0
+       cmpwi   cr0,r3,0
+       cmpwi   cr1,r4,0
        clrlwi  r6,r5,16
        rlwinm  r7,r5,16,31-15,31-0
        beq     cr0,1f
index 5e1ed15..b322bfb 100644 (file)
@@ -57,7 +57,7 @@ static void print_hmi_event_info(struct OpalHMIEvent *hmi_evt)
        };
 
        /* Print things out */
-       if (hmi_evt->version != OpalHMIEvt_V1) {
+       if (hmi_evt->version < OpalHMIEvt_V1) {
                pr_err("HMI Interrupt, Unknown event version %d !\n",
                        hmi_evt->version);
                return;
index 468a0f2..3ba435e 100644 (file)
@@ -1509,7 +1509,6 @@ static int pnv_pci_ioda_msi_setup(struct pnv_phb *phb, struct pci_dev *dev,
                                  unsigned int is_64, struct msi_msg *msg)
 {
        struct pnv_ioda_pe *pe = pnv_ioda_get_pe(dev);
-       struct pci_dn *pdn = pci_get_pdn(dev);
        unsigned int xive_num = hwirq - phb->msi_base;
        __be32 data;
        int rc;
@@ -1523,7 +1522,7 @@ static int pnv_pci_ioda_msi_setup(struct pnv_phb *phb, struct pci_dev *dev,
                return -ENXIO;
 
        /* Force 32-bit MSI on some broken devices */
-       if (pdn && pdn->force_32bit_msi)
+       if (dev->no_64bit_msi)
                is_64 = 0;
 
        /* Assign XIVE to PE */
@@ -1997,7 +1996,7 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np,
        if (is_kdump_kernel()) {
                pr_info("  Issue PHB reset ...\n");
                ioda_eeh_phb_reset(hose, EEH_RESET_FUNDAMENTAL);
-               ioda_eeh_phb_reset(hose, OPAL_DEASSERT_RESET);
+               ioda_eeh_phb_reset(hose, EEH_RESET_DEACTIVATE);
        }
 
        /* Configure M64 window */
index b2187d0..4b20f2c 100644 (file)
@@ -50,7 +50,6 @@ static int pnv_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
 {
        struct pci_controller *hose = pci_bus_to_host(pdev->bus);
        struct pnv_phb *phb = hose->private_data;
-       struct pci_dn *pdn = pci_get_pdn(pdev);
        struct msi_desc *entry;
        struct msi_msg msg;
        int hwirq;
@@ -60,7 +59,7 @@ static int pnv_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
        if (WARN_ON(!phb) || !phb->msi_bmp.bitmap)
                return -ENODEV;
 
-       if (pdn && pdn->force_32bit_msi && !phb->msi32_support)
+       if (pdev->no_64bit_msi && !phb->msi32_support)
                return -ENODEV;
 
        list_for_each_entry(entry, &pdev->msi_list, list) {
index 8ab5add..8b909e9 100644 (file)
@@ -420,7 +420,7 @@ static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec_in, int type)
         */
 again:
        if (type == PCI_CAP_ID_MSI) {
-               if (pdn->force_32bit_msi) {
+               if (pdev->no_64bit_msi) {
                        rc = rtas_change_msi(pdn, RTAS_CHANGE_32MSI_FN, nvec);
                        if (rc < 0) {
                                /*
index b988b5a..c8efbb3 100644 (file)
@@ -293,10 +293,10 @@ static inline void disable_surveillance(void)
        args.token = rtas_token("set-indicator");
        if (args.token == RTAS_UNKNOWN_SERVICE)
                return;
-       args.nargs = 3;
-       args.nret = 1;
+       args.nargs = cpu_to_be32(3);
+       args.nret = cpu_to_be32(1);
        args.rets = &args.args[3];
-       args.args[0] = SURVEILLANCE_TOKEN;
+       args.args[0] = cpu_to_be32(SURVEILLANCE_TOKEN);
        args.args[1] = 0;
        args.args[2] = 0;
        enter_rtas(__pa(&args));
index dd1c24c..3f51cf4 100644 (file)
@@ -54,12 +54,8 @@ void s390_handle_mcck(void)
         */
        local_irq_save(flags);
        local_mcck_disable();
-       /*
-        * Ummm... Does this make sense at all? Copying the percpu struct
-        * and then zapping it one statement later?
-        */
-       memcpy(&mcck, this_cpu_ptr(&cpu_mcck), sizeof(mcck));
-       memset(&mcck, 0, sizeof(struct mcck_struct));
+       mcck = *this_cpu_ptr(&cpu_mcck);
+       memset(this_cpu_ptr(&cpu_mcck), 0, sizeof(mcck));
        clear_cpu_flag(CIF_MCCK_PENDING);
        local_mcck_enable();
        local_irq_restore(flags);
index 5b1b52a..7e064c6 100644 (file)
@@ -12,6 +12,14 @@ int dma_supported(struct device *dev, u64 mask);
 #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
 #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
 
+static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
+                                 enum dma_data_direction dir)
+{
+       /* Since dma_{alloc,free}_noncoherent() allocated coherent memory, this
+        * routine can be a nop.
+        */
+}
+
 extern struct dma_map_ops *dma_ops;
 extern struct dma_map_ops *leon_dma_ops;
 extern struct dma_map_ops pci32_dma_ops;
index be1e07d..45abc36 100644 (file)
@@ -76,7 +76,7 @@ suffix-$(CONFIG_KERNEL_XZ)    := xz
 suffix-$(CONFIG_KERNEL_LZO)    := lzo
 suffix-$(CONFIG_KERNEL_LZ4)    := lz4
 
-RUN_SIZE = $(shell objdump -h vmlinux | \
+RUN_SIZE = $(shell $(OBJDUMP) -h vmlinux | \
             perl $(srctree)/arch/x86/tools/calc_run_size.pl)
 quiet_cmd_mkpiggy = MKPIGGY $@
       cmd_mkpiggy = $(obj)/mkpiggy $< $(RUN_SIZE) > $@ || ( rm -f $@ ; false )
index 2ce9051..08fe6e8 100644 (file)
@@ -465,6 +465,7 @@ static void mc_bp_resume(void)
 
        if (uci->valid && uci->mc)
                microcode_ops->apply_microcode(cpu);
+#ifdef CONFIG_X86_64
        else if (!uci->mc)
                /*
                 * We might resume and not have applied late microcode but still
@@ -473,6 +474,7 @@ static void mc_bp_resume(void)
                 * applying patches early on the APs.
                 */
                load_ucode_ap();
+#endif
 }
 
 static struct syscore_ops mc_syscore_ops = {
index ac1c4de..978f402 100644 (file)
@@ -630,7 +630,7 @@ static int mmu_spte_clear_track_bits(u64 *sptep)
         * kvm mmu, before reclaiming the page, we should
         * unmap it from mmu first.
         */
-       WARN_ON(!kvm_is_mmio_pfn(pfn) && !page_count(pfn_to_page(pfn)));
+       WARN_ON(!kvm_is_reserved_pfn(pfn) && !page_count(pfn_to_page(pfn)));
 
        if (!shadow_accessed_mask || old_spte & shadow_accessed_mask)
                kvm_set_pfn_accessed(pfn);
@@ -2461,7 +2461,7 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
                spte |= PT_PAGE_SIZE_MASK;
        if (tdp_enabled)
                spte |= kvm_x86_ops->get_mt_mask(vcpu, gfn,
-                       kvm_is_mmio_pfn(pfn));
+                       kvm_is_reserved_pfn(pfn));
 
        if (host_writable)
                spte |= SPTE_HOST_WRITEABLE;
@@ -2737,7 +2737,7 @@ static void transparent_hugepage_adjust(struct kvm_vcpu *vcpu,
         * PT_PAGE_TABLE_LEVEL and there would be no adjustment done
         * here.
         */
-       if (!is_error_noslot_pfn(pfn) && !kvm_is_mmio_pfn(pfn) &&
+       if (!is_error_noslot_pfn(pfn) && !kvm_is_reserved_pfn(pfn) &&
            level == PT_PAGE_TABLE_LEVEL &&
            PageTransCompound(pfn_to_page(pfn)) &&
            !has_wrprotected_page(vcpu->kvm, gfn, PT_DIRECTORY_LEVEL)) {
index 0984232..5cbd5d9 100644 (file)
@@ -216,9 +216,10 @@ static int bio_integrity_process(struct bio *bio,
 {
        struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev);
        struct blk_integrity_iter iter;
-       struct bio_vec *bv;
+       struct bvec_iter bviter;
+       struct bio_vec bv;
        struct bio_integrity_payload *bip = bio_integrity(bio);
-       unsigned int i, ret = 0;
+       unsigned int ret = 0;
        void *prot_buf = page_address(bip->bip_vec->bv_page) +
                bip->bip_vec->bv_offset;
 
@@ -227,11 +228,11 @@ static int bio_integrity_process(struct bio *bio,
        iter.seed = bip_get_seed(bip);
        iter.prot_buf = prot_buf;
 
-       bio_for_each_segment_all(bv, bio, i) {
-               void *kaddr = kmap_atomic(bv->bv_page);
+       bio_for_each_segment(bv, bio, bviter) {
+               void *kaddr = kmap_atomic(bv.bv_page);
 
-               iter.data_buf = kaddr + bv->bv_offset;
-               iter.data_size = bv->bv_len;
+               iter.data_buf = kaddr + bv.bv_offset;
+               iter.data_size = bv.bv_len;
 
                ret = proc_fn(&iter);
                if (ret) {
index b23fe37..79078b8 100644 (file)
@@ -360,15 +360,14 @@ config ACPI_BGRT
 config ACPI_REDUCED_HARDWARE_ONLY
        bool "Hardware-reduced ACPI support only" if EXPERT
        def_bool n
-       depends on ACPI
        help
-       This config item changes the way the ACPI code is built.  When this
-       option is selected, the kernel will use a specialized version of
-       ACPICA that ONLY supports the ACPI "reduced hardware" mode.  The
-       resulting kernel will be smaller but it will also be restricted to
-       running in ACPI reduced hardware mode ONLY.
+         This config item changes the way the ACPI code is built.  When this
+         option is selected, the kernel will use a specialized version of
+         ACPICA that ONLY supports the ACPI "reduced hardware" mode.  The
+         resulting kernel will be smaller but it will also be restricted to
+         running in ACPI reduced hardware mode ONLY.
 
-       If you are unsure what to do, do not enable this option.
+         If you are unsure what to do, do not enable this option.
 
 source "drivers/acpi/apei/Kconfig"
 
index c3b2fcb..6d11522 100644 (file)
@@ -47,6 +47,7 @@ acpi-y                                += int340x_thermal.o
 acpi-y                         += power.o
 acpi-y                         += event.o
 acpi-y                         += sysfs.o
+acpi-y                         += property.o
 acpi-$(CONFIG_X86)             += acpi_cmos_rtc.o
 acpi-$(CONFIG_DEBUG_FS)                += debugfs.o
 acpi-$(CONFIG_ACPI_NUMA)       += numa.o
index 447f6d6..163e82f 100644 (file)
@@ -173,4 +173,10 @@ static inline void suspend_nvs_restore(void) {}
 bool acpi_osi_is_win8(void);
 #endif
 
+/*--------------------------------------------------------------------------
+                               Device properties
+  -------------------------------------------------------------------------- */
+void acpi_init_properties(struct acpi_device *adev);
+void acpi_free_properties(struct acpi_device *adev);
+
 #endif /* _ACPI_INTERNAL_H_ */
index 9964f70..f9eeae8 100644 (file)
@@ -436,7 +436,7 @@ static void acpi_os_drop_map_ref(struct acpi_ioremap *map)
 static void acpi_os_map_cleanup(struct acpi_ioremap *map)
 {
        if (!map->refcount) {
-               synchronize_rcu();
+               synchronize_rcu_expedited();
                acpi_unmap(map->phys, map->virt);
                kfree(map);
        }
@@ -1188,6 +1188,12 @@ EXPORT_SYMBOL(acpi_os_execute);
 
 void acpi_os_wait_events_complete(void)
 {
+       /*
+        * Make sure the GPE handler or the fixed event handler is not used
+        * on another CPU after removal.
+        */
+       if (acpi_irq_handler)
+               synchronize_hardirq(acpi_gbl_FADT.sci_interrupt);
        flush_workqueue(kacpid_wq);
        flush_workqueue(kacpi_notify_wq);
 }
diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c
new file mode 100644 (file)
index 0000000..0d08373
--- /dev/null
@@ -0,0 +1,551 @@
+/*
+ * ACPI device specific properties support.
+ *
+ * Copyright (C) 2014, Intel Corporation
+ * All rights reserved.
+ *
+ * Authors: Mika Westerberg <mika.westerberg@linux.intel.com>
+ *          Darren Hart <dvhart@linux.intel.com>
+ *          Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/acpi.h>
+#include <linux/device.h>
+#include <linux/export.h>
+
+#include "internal.h"
+
+/* ACPI _DSD device properties UUID: daffd814-6eba-4d8c-8a91-bc9bbf4aa301 */
+static const u8 prp_uuid[16] = {
+       0x14, 0xd8, 0xff, 0xda, 0xba, 0x6e, 0x8c, 0x4d,
+       0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01
+};
+
+static bool acpi_property_value_ok(const union acpi_object *value)
+{
+       int j;
+
+       /*
+        * The value must be an integer, a string, a reference, or a package
+        * whose every element must be an integer, a string, or a reference.
+        */
+       switch (value->type) {
+       case ACPI_TYPE_INTEGER:
+       case ACPI_TYPE_STRING:
+       case ACPI_TYPE_LOCAL_REFERENCE:
+               return true;
+
+       case ACPI_TYPE_PACKAGE:
+               for (j = 0; j < value->package.count; j++)
+                       switch (value->package.elements[j].type) {
+                       case ACPI_TYPE_INTEGER:
+                       case ACPI_TYPE_STRING:
+                       case ACPI_TYPE_LOCAL_REFERENCE:
+                               continue;
+
+                       default:
+                               return false;
+                       }
+
+               return true;
+       }
+       return false;
+}
+
+static bool acpi_properties_format_valid(const union acpi_object *properties)
+{
+       int i;
+
+       for (i = 0; i < properties->package.count; i++) {
+               const union acpi_object *property;
+
+               property = &properties->package.elements[i];
+               /*
+                * Only two elements allowed, the first one must be a string and
+                * the second one has to satisfy certain conditions.
+                */
+               if (property->package.count != 2
+                   || property->package.elements[0].type != ACPI_TYPE_STRING
+                   || !acpi_property_value_ok(&property->package.elements[1]))
+                       return false;
+       }
+       return true;
+}
+
+static void acpi_init_of_compatible(struct acpi_device *adev)
+{
+       const union acpi_object *of_compatible;
+       struct acpi_hardware_id *hwid;
+       bool acpi_of = false;
+       int ret;
+
+       /*
+        * Check if the special PRP0001 ACPI ID is present and in that
+        * case we fill in Device Tree compatible properties for this
+        * device.
+        */
+       list_for_each_entry(hwid, &adev->pnp.ids, list) {
+               if (!strcmp(hwid->id, "PRP0001")) {
+                       acpi_of = true;
+                       break;
+               }
+       }
+
+       if (!acpi_of)
+               return;
+
+       ret = acpi_dev_get_property_array(adev, "compatible", ACPI_TYPE_STRING,
+                                         &of_compatible);
+       if (ret) {
+               ret = acpi_dev_get_property(adev, "compatible",
+                                           ACPI_TYPE_STRING, &of_compatible);
+               if (ret) {
+                       acpi_handle_warn(adev->handle,
+                                        "PRP0001 requires compatible property\n");
+                       return;
+               }
+       }
+       adev->data.of_compatible = of_compatible;
+}
+
+void acpi_init_properties(struct acpi_device *adev)
+{
+       struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
+       const union acpi_object *desc;
+       acpi_status status;
+       int i;
+
+       status = acpi_evaluate_object_typed(adev->handle, "_DSD", NULL, &buf,
+                                           ACPI_TYPE_PACKAGE);
+       if (ACPI_FAILURE(status))
+               return;
+
+       desc = buf.pointer;
+       if (desc->package.count % 2)
+               goto fail;
+
+       /* Look for the device properties UUID. */
+       for (i = 0; i < desc->package.count; i += 2) {
+               const union acpi_object *uuid, *properties;
+
+               uuid = &desc->package.elements[i];
+               properties = &desc->package.elements[i + 1];
+
+               /*
+                * The first element must be a UUID and the second one must be
+                * a package.
+                */
+               if (uuid->type != ACPI_TYPE_BUFFER || uuid->buffer.length != 16
+                   || properties->type != ACPI_TYPE_PACKAGE)
+                       break;
+
+               if (memcmp(uuid->buffer.pointer, prp_uuid, sizeof(prp_uuid)))
+                       continue;
+
+               /*
+                * We found the matching UUID. Now validate the format of the
+                * package immediately following it.
+                */
+               if (!acpi_properties_format_valid(properties))
+                       break;
+
+               adev->data.pointer = buf.pointer;
+               adev->data.properties = properties;
+
+               acpi_init_of_compatible(adev);
+               return;
+       }
+
+ fail:
+       dev_warn(&adev->dev, "Returned _DSD data is not valid, skipping\n");
+       ACPI_FREE(buf.pointer);
+}
+
+void acpi_free_properties(struct acpi_device *adev)
+{
+       ACPI_FREE((void *)adev->data.pointer);
+       adev->data.of_compatible = NULL;
+       adev->data.pointer = NULL;
+       adev->data.properties = NULL;
+}
+
+/**
+ * acpi_dev_get_property - return an ACPI property with given name
+ * @adev: ACPI device to get property
+ * @name: Name of the property
+ * @type: Expected property type
+ * @obj: Location to store the property value (if not %NULL)
+ *
+ * Look up a property with @name and store a pointer to the resulting ACPI
+ * object at the location pointed to by @obj if found.
+ *
+ * Callers must not attempt to free the returned objects.  These objects will be
+ * freed by the ACPI core automatically during the removal of @adev.
+ *
+ * Return: %0 if property with @name has been found (success),
+ *         %-EINVAL if the arguments are invalid,
+ *         %-ENODATA if the property doesn't exist,
+ *         %-EPROTO if the property value type doesn't match @type.
+ */
+int acpi_dev_get_property(struct acpi_device *adev, const char *name,
+                         acpi_object_type type, const union acpi_object **obj)
+{
+       const union acpi_object *properties;
+       int i;
+
+       if (!adev || !name)
+               return -EINVAL;
+
+       if (!adev->data.pointer || !adev->data.properties)
+               return -ENODATA;
+
+       properties = adev->data.properties;
+       for (i = 0; i < properties->package.count; i++) {
+               const union acpi_object *propname, *propvalue;
+               const union acpi_object *property;
+
+               property = &properties->package.elements[i];
+
+               propname = &property->package.elements[0];
+               propvalue = &property->package.elements[1];
+
+               if (!strcmp(name, propname->string.pointer)) {
+                       if (type != ACPI_TYPE_ANY && propvalue->type != type)
+                               return -EPROTO;
+                       else if (obj)
+                               *obj = propvalue;
+
+                       return 0;
+               }
+       }
+       return -ENODATA;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_get_property);
+
+/**
+ * acpi_dev_get_property_array - return an ACPI array property with given name
+ * @adev: ACPI device to get property
+ * @name: Name of the property
+ * @type: Expected type of array elements
+ * @obj: Location to store a pointer to the property value (if not NULL)
+ *
+ * Look up an array property with @name and store a pointer to the resulting
+ * ACPI object at the location pointed to by @obj if found.
+ *
+ * Callers must not attempt to free the returned objects.  Those objects will be
+ * freed by the ACPI core automatically during the removal of @adev.
+ *
+ * Return: %0 if array property (package) with @name has been found (success),
+ *         %-EINVAL if the arguments are invalid,
+ *         %-ENODATA if the property doesn't exist,
+ *         %-EPROTO if the property is not a package or the type of its elements
+ *           doesn't match @type.
+ */
+int acpi_dev_get_property_array(struct acpi_device *adev, const char *name,
+                               acpi_object_type type,
+                               const union acpi_object **obj)
+{
+       const union acpi_object *prop;
+       int ret, i;
+
+       ret = acpi_dev_get_property(adev, name, ACPI_TYPE_PACKAGE, &prop);
+       if (ret)
+               return ret;
+
+       if (type != ACPI_TYPE_ANY) {
+               /* Check that all elements are of correct type. */
+               for (i = 0; i < prop->package.count; i++)
+                       if (prop->package.elements[i].type != type)
+                               return -EPROTO;
+       }
+       if (obj)
+               *obj = prop;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_get_property_array);
+
+/**
+ * acpi_dev_get_property_reference - returns handle to the referenced object
+ * @adev: ACPI device to get property
+ * @name: Name of the property
+ * @index: Index of the reference to return
+ * @args: Location to store the returned reference with optional arguments
+ *
+ * Find property with @name, verifify that it is a package containing at least
+ * one object reference and if so, store the ACPI device object pointer to the
+ * target object in @args->adev.  If the reference includes arguments, store
+ * them in the @args->args[] array.
+ *
+ * If there's more than one reference in the property value package, @index is
+ * used to select the one to return.
+ *
+ * Return: %0 on success, negative error code on failure.
+ */
+int acpi_dev_get_property_reference(struct acpi_device *adev,
+                                   const char *name, size_t index,
+                                   struct acpi_reference_args *args)
+{
+       const union acpi_object *element, *end;
+       const union acpi_object *obj;
+       struct acpi_device *device;
+       int ret, idx = 0;
+
+       ret = acpi_dev_get_property(adev, name, ACPI_TYPE_ANY, &obj);
+       if (ret)
+               return ret;
+
+       /*
+        * The simplest case is when the value is a single reference.  Just
+        * return that reference then.
+        */
+       if (obj->type == ACPI_TYPE_LOCAL_REFERENCE) {
+               if (index)
+                       return -EINVAL;
+
+               ret = acpi_bus_get_device(obj->reference.handle, &device);
+               if (ret)
+                       return ret;
+
+               args->adev = device;
+               args->nargs = 0;
+               return 0;
+       }
+
+       /*
+        * If it is not a single reference, then it is a package of
+        * references followed by number of ints as follows:
+        *
+        *  Package () { REF, INT, REF, INT, INT }
+        *
+        * The index argument is then used to determine which reference
+        * the caller wants (along with the arguments).
+        */
+       if (obj->type != ACPI_TYPE_PACKAGE || index >= obj->package.count)
+               return -EPROTO;
+
+       element = obj->package.elements;
+       end = element + obj->package.count;
+
+       while (element < end) {
+               u32 nargs, i;
+
+               if (element->type != ACPI_TYPE_LOCAL_REFERENCE)
+                       return -EPROTO;
+
+               ret = acpi_bus_get_device(element->reference.handle, &device);
+               if (ret)
+                       return -ENODEV;
+
+               element++;
+               nargs = 0;
+
+               /* assume following integer elements are all args */
+               for (i = 0; element + i < end; i++) {
+                       int type = element[i].type;
+
+                       if (type == ACPI_TYPE_INTEGER)
+                               nargs++;
+                       else if (type == ACPI_TYPE_LOCAL_REFERENCE)
+                               break;
+                       else
+                               return -EPROTO;
+               }
+
+               if (idx++ == index) {
+                       args->adev = device;
+                       args->nargs = nargs;
+                       for (i = 0; i < nargs; i++)
+                               args->args[i] = element[i].integer.value;
+
+                       return 0;
+               }
+
+               element += nargs;
+       }
+
+       return -EPROTO;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_get_property_reference);
+
+int acpi_dev_prop_get(struct acpi_device *adev, const char *propname,
+                     void **valptr)
+{
+       return acpi_dev_get_property(adev, propname, ACPI_TYPE_ANY,
+                                    (const union acpi_object **)valptr);
+}
+
+int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname,
+                             enum dev_prop_type proptype, void *val)
+{
+       const union acpi_object *obj;
+       int ret;
+
+       if (!val)
+               return -EINVAL;
+
+       if (proptype >= DEV_PROP_U8 && proptype <= DEV_PROP_U64) {
+               ret = acpi_dev_get_property(adev, propname, ACPI_TYPE_INTEGER, &obj);
+               if (ret)
+                       return ret;
+
+               switch (proptype) {
+               case DEV_PROP_U8:
+                       if (obj->integer.value > U8_MAX)
+                               return -EOVERFLOW;
+                       *(u8 *)val = obj->integer.value;
+                       break;
+               case DEV_PROP_U16:
+                       if (obj->integer.value > U16_MAX)
+                               return -EOVERFLOW;
+                       *(u16 *)val = obj->integer.value;
+                       break;
+               case DEV_PROP_U32:
+                       if (obj->integer.value > U32_MAX)
+                               return -EOVERFLOW;
+                       *(u32 *)val = obj->integer.value;
+                       break;
+               default:
+                       *(u64 *)val = obj->integer.value;
+                       break;
+               }
+       } else if (proptype == DEV_PROP_STRING) {
+               ret = acpi_dev_get_property(adev, propname, ACPI_TYPE_STRING, &obj);
+               if (ret)
+                       return ret;
+
+               *(char **)val = obj->string.pointer;
+       } else {
+               ret = -EINVAL;
+       }
+       return ret;
+}
+
+static int acpi_copy_property_array_u8(const union acpi_object *items, u8 *val,
+                                      size_t nval)
+{
+       int i;
+
+       for (i = 0; i < nval; i++) {
+               if (items[i].type != ACPI_TYPE_INTEGER)
+                       return -EPROTO;
+               if (items[i].integer.value > U8_MAX)
+                       return -EOVERFLOW;
+
+               val[i] = items[i].integer.value;
+       }
+       return 0;
+}
+
+static int acpi_copy_property_array_u16(const union acpi_object *items,
+                                       u16 *val, size_t nval)
+{
+       int i;
+
+       for (i = 0; i < nval; i++) {
+               if (items[i].type != ACPI_TYPE_INTEGER)
+                       return -EPROTO;
+               if (items[i].integer.value > U16_MAX)
+                       return -EOVERFLOW;
+
+               val[i] = items[i].integer.value;
+       }
+       return 0;
+}
+
+static int acpi_copy_property_array_u32(const union acpi_object *items,
+                                       u32 *val, size_t nval)
+{
+       int i;
+
+       for (i = 0; i < nval; i++) {
+               if (items[i].type != ACPI_TYPE_INTEGER)
+                       return -EPROTO;
+               if (items[i].integer.value > U32_MAX)
+                       return -EOVERFLOW;
+
+               val[i] = items[i].integer.value;
+       }
+       return 0;
+}
+
+static int acpi_copy_property_array_u64(const union acpi_object *items,
+                                       u64 *val, size_t nval)
+{
+       int i;
+
+       for (i = 0; i < nval; i++) {
+               if (items[i].type != ACPI_TYPE_INTEGER)
+                       return -EPROTO;
+
+               val[i] = items[i].integer.value;
+       }
+       return 0;
+}
+
+static int acpi_copy_property_array_string(const union acpi_object *items,
+                                          char **val, size_t nval)
+{
+       int i;
+
+       for (i = 0; i < nval; i++) {
+               if (items[i].type != ACPI_TYPE_STRING)
+                       return -EPROTO;
+
+               val[i] = items[i].string.pointer;
+       }
+       return 0;
+}
+
+int acpi_dev_prop_read(struct acpi_device *adev, const char *propname,
+                      enum dev_prop_type proptype, void *val, size_t nval)
+{
+       const union acpi_object *obj;
+       const union acpi_object *items;
+       int ret;
+
+       if (val && nval == 1) {
+               ret = acpi_dev_prop_read_single(adev, propname, proptype, val);
+               if (!ret)
+                       return ret;
+       }
+
+       ret = acpi_dev_get_property_array(adev, propname, ACPI_TYPE_ANY, &obj);
+       if (ret)
+               return ret;
+
+       if (!val)
+               return obj->package.count;
+       else if (nval <= 0)
+               return -EINVAL;
+
+       if (nval > obj->package.count)
+               return -EOVERFLOW;
+
+       items = obj->package.elements;
+       switch (proptype) {
+       case DEV_PROP_U8:
+               ret = acpi_copy_property_array_u8(items, (u8 *)val, nval);
+               break;
+       case DEV_PROP_U16:
+               ret = acpi_copy_property_array_u16(items, (u16 *)val, nval);
+               break;
+       case DEV_PROP_U32:
+               ret = acpi_copy_property_array_u32(items, (u32 *)val, nval);
+               break;
+       case DEV_PROP_U64:
+               ret = acpi_copy_property_array_u64(items, (u64 *)val, nval);
+               break;
+       case DEV_PROP_STRING:
+               ret = acpi_copy_property_array_string(items, (char **)val, nval);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+       return ret;
+}
index 0476e90..9cb5cca 100644 (file)
@@ -124,17 +124,56 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias,
        if (list_empty(&acpi_dev->pnp.ids))
                return 0;
 
-       len = snprintf(modalias, size, "acpi:");
-       size -= len;
-
-       list_for_each_entry(id, &acpi_dev->pnp.ids, list) {
-               count = snprintf(&modalias[len], size, "%s:", id->id);
-               if (count < 0)
-                       return -EINVAL;
-               if (count >= size)
-                       return -ENOMEM;
-               len += count;
-               size -= count;
+       /*
+        * If the device has PRP0001 we expose DT compatible modalias
+        * instead in form of of:NnameTCcompatible.
+        */
+       if (acpi_dev->data.of_compatible) {
+               struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
+               const union acpi_object *of_compatible, *obj;
+               int i, nval;
+               char *c;
+
+               acpi_get_name(acpi_dev->handle, ACPI_SINGLE_NAME, &buf);
+               /* DT strings are all in lower case */
+               for (c = buf.pointer; *c != '\0'; c++)
+                       *c = tolower(*c);
+
+               len = snprintf(modalias, size, "of:N%sT", (char *)buf.pointer);
+               ACPI_FREE(buf.pointer);
+
+               of_compatible = acpi_dev->data.of_compatible;
+               if (of_compatible->type == ACPI_TYPE_PACKAGE) {
+                       nval = of_compatible->package.count;
+                       obj = of_compatible->package.elements;
+               } else { /* Must be ACPI_TYPE_STRING. */
+                       nval = 1;
+                       obj = of_compatible;
+               }
+               for (i = 0; i < nval; i++, obj++) {
+                       count = snprintf(&modalias[len], size, "C%s",
+                                        obj->string.pointer);
+                       if (count < 0)
+                               return -EINVAL;
+                       if (count >= size)
+                               return -ENOMEM;
+
+                       len += count;
+                       size -= count;
+               }
+       } else {
+               len = snprintf(modalias, size, "acpi:");
+               size -= len;
+
+               list_for_each_entry(id, &acpi_dev->pnp.ids, list) {
+                       count = snprintf(&modalias[len], size, "%s:", id->id);
+                       if (count < 0)
+                               return -EINVAL;
+                       if (count >= size)
+                               return -ENOMEM;
+                       len += count;
+                       size -= count;
+               }
        }
 
        modalias[len] = '\0';
@@ -902,6 +941,51 @@ int acpi_match_device_ids(struct acpi_device *device,
 }
 EXPORT_SYMBOL(acpi_match_device_ids);
 
+/* Performs match against special "PRP0001" shoehorn ACPI ID */
+static bool acpi_of_driver_match_device(struct device *dev,
+                                       const struct device_driver *drv)
+{
+       const union acpi_object *of_compatible, *obj;
+       struct acpi_device *adev;
+       int i, nval;
+
+       adev = ACPI_COMPANION(dev);
+       if (!adev)
+               return false;
+
+       of_compatible = adev->data.of_compatible;
+       if (!drv->of_match_table || !of_compatible)
+               return false;
+
+       if (of_compatible->type == ACPI_TYPE_PACKAGE) {
+               nval = of_compatible->package.count;
+               obj = of_compatible->package.elements;
+       } else { /* Must be ACPI_TYPE_STRING. */
+               nval = 1;
+               obj = of_compatible;
+       }
+       /* Now we can look for the driver DT compatible strings */
+       for (i = 0; i < nval; i++, obj++) {
+               const struct of_device_id *id;
+
+               for (id = drv->of_match_table; id->compatible[0]; id++)
+                       if (!strcasecmp(obj->string.pointer, id->compatible))
+                               return true;
+       }
+
+       return false;
+}
+
+bool acpi_driver_match_device(struct device *dev,
+                             const struct device_driver *drv)
+{
+       if (!drv->acpi_match_table)
+               return acpi_of_driver_match_device(dev, drv);
+
+       return !!acpi_match_device(drv->acpi_match_table, dev);
+}
+EXPORT_SYMBOL_GPL(acpi_driver_match_device);
+
 static void acpi_free_power_resources_lists(struct acpi_device *device)
 {
        int i;
@@ -922,6 +1006,7 @@ static void acpi_device_release(struct device *dev)
 {
        struct acpi_device *acpi_dev = to_acpi_device(dev);
 
+       acpi_free_properties(acpi_dev);
        acpi_free_pnp_ids(&acpi_dev->pnp);
        acpi_free_power_resources_lists(acpi_dev);
        kfree(acpi_dev);
@@ -1304,6 +1389,26 @@ int acpi_device_add(struct acpi_device *device,
        return result;
 }
 
+struct acpi_device *acpi_get_next_child(struct device *dev,
+                                       struct acpi_device *child)
+{
+       struct acpi_device *adev = ACPI_COMPANION(dev);
+       struct list_head *head, *next;
+
+       if (!adev)
+               return NULL;
+
+       head = &adev->children;
+       if (list_empty(head))
+               return NULL;
+
+       if (!child)
+               return list_first_entry(head, struct acpi_device, node);
+
+       next = child->node.next;
+       return next == head ? NULL : list_entry(next, struct acpi_device, node);
+}
+
 /* --------------------------------------------------------------------------
                                  Driver Management
    -------------------------------------------------------------------------- */
@@ -1923,9 +2028,11 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
        device->device_type = type;
        device->handle = handle;
        device->parent = acpi_bus_get_parent(handle);
+       device->fwnode.type = FWNODE_ACPI;
        acpi_set_device_status(device, sta);
        acpi_device_get_busid(device);
        acpi_set_pnp_ids(handle, &device->pnp, type);
+       acpi_init_properties(device);
        acpi_bus_get_flags(device);
        device->flags.match_driver = false;
        device->flags.initialized = true;
index 371ac12..dd8ff63 100644 (file)
@@ -136,8 +136,7 @@ acpi_extract_package(union acpi_object *package,
                                break;
                        case 'B':
                                size_required +=
-                                   sizeof(u8 *) +
-                                   (element->buffer.length * sizeof(u8));
+                                   sizeof(u8 *) + element->buffer.length;
                                tail_offset += sizeof(u8 *);
                                break;
                        default:
@@ -255,7 +254,7 @@ acpi_extract_package(union acpi_object *package,
                                memcpy(tail, element->buffer.pointer,
                                       element->buffer.length);
                                head += sizeof(u8 *);
-                               tail += element->buffer.length * sizeof(u8);
+                               tail += element->buffer.length;
                                break;
                        default:
                                /* Should never get here */
index 807a88a..9d75ead 100644 (file)
@@ -1164,7 +1164,8 @@ static bool acpi_video_device_in_dod(struct acpi_video_device *device)
                return true;
 
        for (i = 0; i < video->attached_count; i++) {
-               if (video->attached_array[i].bind_info == device)
+               if ((video->attached_array[i].value.int_val & 0xfff) ==
+                   (device->device_id & 0xfff))
                        return true;
        }
 
index e45f837..49f1e68 100644 (file)
@@ -321,6 +321,9 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(INTEL, 0x8c87), board_ahci }, /* 9 Series RAID */
        { PCI_VDEVICE(INTEL, 0x8c8e), board_ahci }, /* 9 Series RAID */
        { PCI_VDEVICE(INTEL, 0x8c8f), board_ahci }, /* 9 Series RAID */
+       { PCI_VDEVICE(INTEL, 0x9d03), board_ahci }, /* Sunrise Point-LP AHCI */
+       { PCI_VDEVICE(INTEL, 0x9d05), board_ahci }, /* Sunrise Point-LP RAID */
+       { PCI_VDEVICE(INTEL, 0x9d07), board_ahci }, /* Sunrise Point-LP RAID */
        { PCI_VDEVICE(INTEL, 0xa103), board_ahci }, /* Sunrise Point-H AHCI */
        { PCI_VDEVICE(INTEL, 0xa103), board_ahci }, /* Sunrise Point-H RAID */
        { PCI_VDEVICE(INTEL, 0xa105), board_ahci }, /* Sunrise Point-H RAID */
@@ -492,6 +495,7 @@ static const struct pci_device_id ahci_pci_tbl[] = {
         * enabled.  https://bugzilla.kernel.org/show_bug.cgi?id=60731
         */
        { PCI_VDEVICE(SAMSUNG, 0x1600), board_ahci_nomsi },
+       { PCI_VDEVICE(SAMSUNG, 0xa800), board_ahci_nomsi },
 
        /* Enmotus */
        { PCI_DEVICE(0x1c44, 0x8000), board_ahci },
index 07bc7e4..6507159 100644 (file)
@@ -1488,7 +1488,7 @@ static int sata_fsl_probe(struct platform_device *ofdev)
        host_priv->csr_base = csr_base;
 
        irq = irq_of_parse_and_map(ofdev->dev.of_node, 0);
-       if (irq < 0) {
+       if (!irq) {
                dev_err(&ofdev->dev, "invalid irq from platform\n");
                goto error_exit_with_cleanup;
        }
index 7652e8d..21b0bc6 100644 (file)
@@ -1225,11 +1225,13 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id)
        card->config_regs = pci_iomap(dev, 0, CONFIG_RAM_SIZE);
        if (!card->config_regs) {
                dev_warn(&dev->dev, "Failed to ioremap config registers\n");
+               err = -ENOMEM;
                goto out_release_regions;
        }
        card->buffers = pci_iomap(dev, 1, DATA_RAM_SIZE);
        if (!card->buffers) {
                dev_warn(&dev->dev, "Failed to ioremap data buffers\n");
+               err = -ENOMEM;
                goto out_unmap_config;
        }
 
index 6922cd6..53c3fe1 100644 (file)
@@ -4,7 +4,7 @@ obj-y                   := component.o core.o bus.o dd.o syscore.o \
                           driver.o class.o platform.o \
                           cpu.o firmware.o init.o map.o devres.o \
                           attribute_container.o transport_class.o \
-                          topology.o container.o
+                          topology.o container.o property.o
 obj-$(CONFIG_DEVTMPFS) += devtmpfs.o
 obj-$(CONFIG_DMA_CMA) += dma-contiguous.o
 obj-y                  += power/
diff --git a/drivers/base/property.c b/drivers/base/property.c
new file mode 100644 (file)
index 0000000..c458458
--- /dev/null
@@ -0,0 +1,431 @@
+/*
+ * property.c - Unified device property interface.
+ *
+ * Copyright (C) 2014, Intel Corporation
+ * Authors: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+ *          Mika Westerberg <mika.westerberg@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/property.h>
+#include <linux/export.h>
+#include <linux/acpi.h>
+#include <linux/of.h>
+
+/**
+ * device_property_present - check if a property of a device is present
+ * @dev: Device whose property is being checked
+ * @propname: Name of the property
+ *
+ * Check if property @propname is present in the device firmware description.
+ */
+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);
+}
+EXPORT_SYMBOL_GPL(device_property_present);
+
+/**
+ * fwnode_property_present - check if a property of a firmware node is present
+ * @fwnode: Firmware node whose property to check
+ * @propname: Name of the property
+ */
+bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname)
+{
+       if (is_of_node(fwnode))
+               return of_property_read_bool(of_node(fwnode), propname);
+       else if (is_acpi_node(fwnode))
+               return !acpi_dev_prop_get(acpi_node(fwnode), propname, NULL);
+
+       return false;
+}
+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
+ * @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),
+ *        %-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,
+ *        %-EOVERFLOW if the size of the property is not as expected.
+ */
+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);
+}
+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
+ * @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),
+ *        %-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,
+ *        %-EOVERFLOW if the size of the property is not as expected.
+ */
+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);
+}
+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
+ * @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),
+ *        %-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,
+ *        %-EOVERFLOW if the size of the property is not as expected.
+ */
+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);
+}
+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
+ * @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),
+ *        %-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,
+ *        %-EOVERFLOW if the size of the property is not as expected.
+ */
+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);
+}
+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
+ * @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),
+ *        %-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,
+ *        %-EOVERFLOW if the size of the property is not as expected.
+ */
+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);
+}
+EXPORT_SYMBOL_GPL(device_property_read_string_array);
+
+/**
+ * device_property_read_string - return a string property of a device
+ * @dev: Device to get the property of
+ * @propname: Name of the property
+ * @val: The value is stored here
+ *
+ * Function reads property @propname from the device firmware description and
+ * stores the value into @val if found. The value is checked to be a string.
+ *
+ * Return: %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 type is not a string.
+ */
+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);
+}
+EXPORT_SYMBOL_GPL(device_property_read_string);
+
+#define FWNODE_PROP_READ_ARRAY(_fwnode_, _propname_, _type_, _proptype_, _val_, _nval_) \
+({ \
+       int _ret_; \
+       if (is_of_node(_fwnode_)) \
+               _ret_ = OF_DEV_PROP_READ_ARRAY(of_node(_fwnode_), _propname_, \
+                                              _type_, _val_, _nval_); \
+       else if (is_acpi_node(_fwnode_)) \
+               _ret_ = acpi_dev_prop_read(acpi_node(_fwnode_), _propname_, \
+                                          _proptype_, _val_, _nval_); \
+       else \
+               _ret_ = -ENXIO; \
+       _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
+ * @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),
+ *        %-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,
+ *        %-EOVERFLOW if the size of the property is not as expected,
+ *        %-ENXIO if no suitable firmware interface is present.
+ */
+int fwnode_property_read_u8_array(struct fwnode_handle *fwnode,
+                                 const char *propname, u8 *val, size_t nval)
+{
+       return FWNODE_PROP_READ_ARRAY(fwnode, propname, u8, DEV_PROP_U8,
+                                     val, nval);
+}
+EXPORT_SYMBOL_GPL(fwnode_property_read_u8_array);
+
+/**
+ * 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
+ * @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),
+ *        %-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,
+ *        %-EOVERFLOW if the size of the property is not as expected,
+ *        %-ENXIO if no suitable firmware interface is present.
+ */
+int fwnode_property_read_u16_array(struct fwnode_handle *fwnode,
+                                  const char *propname, u16 *val, size_t nval)
+{
+       return FWNODE_PROP_READ_ARRAY(fwnode, propname, u16, DEV_PROP_U16,
+                                     val, nval);
+}
+EXPORT_SYMBOL_GPL(fwnode_property_read_u16_array);
+
+/**
+ * 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
+ * @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),
+ *        %-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,
+ *        %-EOVERFLOW if the size of the property is not as expected,
+ *        %-ENXIO if no suitable firmware interface is present.
+ */
+int fwnode_property_read_u32_array(struct fwnode_handle *fwnode,
+                                  const char *propname, u32 *val, size_t nval)
+{
+       return FWNODE_PROP_READ_ARRAY(fwnode, propname, u32, DEV_PROP_U32,
+                                     val, nval);
+}
+EXPORT_SYMBOL_GPL(fwnode_property_read_u32_array);
+
+/**
+ * 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
+ * @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),
+ *        %-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,
+ *        %-EOVERFLOW if the size of the property is not as expected,
+ *        %-ENXIO if no suitable firmware interface is present.
+ */
+int fwnode_property_read_u64_array(struct fwnode_handle *fwnode,
+                                  const char *propname, u64 *val, size_t nval)
+{
+       return FWNODE_PROP_READ_ARRAY(fwnode, propname, u64, DEV_PROP_U64,
+                                     val, nval);
+}
+EXPORT_SYMBOL_GPL(fwnode_property_read_u64_array);
+
+/**
+ * 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
+ * @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),
+ *        %-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,
+ *        %-EOVERFLOW if the size of the property is not as expected,
+ *        %-ENXIO if no suitable firmware interface is present.
+ */
+int fwnode_property_read_string_array(struct fwnode_handle *fwnode,
+                                     const char *propname, const char **val,
+                                     size_t nval)
+{
+       if (is_of_node(fwnode))
+               return of_property_read_string_array(of_node(fwnode), propname,
+                                                    val, nval);
+       else if (is_acpi_node(fwnode))
+               return acpi_dev_prop_read(acpi_node(fwnode), propname,
+                                         DEV_PROP_STRING, val, nval);
+
+       return -ENXIO;
+}
+EXPORT_SYMBOL_GPL(fwnode_property_read_string_array);
+
+/**
+ * fwnode_property_read_string - return a string property of a firmware node
+ * @fwnode: Firmware node to get the property of
+ * @propname: Name of the property
+ * @val: The value is stored here
+ *
+ * Read property @propname from the given firmware node and store the value into
+ * @val if found.  The value is checked to be a string.
+ *
+ * Return: %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 a string,
+ *        %-ENXIO if no suitable firmware interface is present.
+ */
+int fwnode_property_read_string(struct fwnode_handle *fwnode,
+                               const char *propname, const char **val)
+{
+       if (is_of_node(fwnode))
+               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);
+
+       return -ENXIO;
+}
+EXPORT_SYMBOL_GPL(fwnode_property_read_string);
+
+/**
+ * device_get_next_child_node - Return the next child node handle for a device
+ * @dev: Device to find the next child node for.
+ * @child: Handle to one of the device's child nodes or a null handle.
+ */
+struct fwnode_handle *device_get_next_child_node(struct device *dev,
+                                                struct fwnode_handle *child)
+{
+       if (IS_ENABLED(CONFIG_OF) && dev->of_node) {
+               struct device_node *node;
+
+               node = of_get_next_available_child(dev->of_node, of_node(child));
+               if (node)
+                       return &node->fwnode;
+       } else if (IS_ENABLED(CONFIG_ACPI)) {
+               struct acpi_device *node;
+
+               node = acpi_get_next_child(dev, acpi_node(child));
+               if (node)
+                       return acpi_fwnode_handle(node);
+       }
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(device_get_next_child_node);
+
+/**
+ * fwnode_handle_put - Drop reference to a device node
+ * @fwnode: Pointer to the device node to drop the reference to.
+ *
+ * This has to be used when terminating device_for_each_child_node() iteration
+ * with break or return to prevent stale device node references from being left
+ * behind.
+ */
+void fwnode_handle_put(struct fwnode_handle *fwnode)
+{
+       if (is_of_node(fwnode))
+               of_node_put(of_node(fwnode));
+}
+EXPORT_SYMBOL_GPL(fwnode_handle_put);
+
+/**
+ * device_get_child_node_count - return the number of child nodes for device
+ * @dev: Device to cound the child nodes for
+ */
+unsigned int device_get_child_node_count(struct device *dev)
+{
+       struct fwnode_handle *child;
+       unsigned int count = 0;
+
+       device_for_each_child_node(dev, child)
+               count++;
+
+       return count;
+}
+EXPORT_SYMBOL_GPL(device_get_child_node_count);
index 24b5b02..a23ac0c 100644 (file)
@@ -52,29 +52,26 @@ static unsigned long at91sam9x5_clk_usb_recalc_rate(struct clk_hw *hw,
 
        tmp = pmc_read(pmc, AT91_PMC_USB);
        usbdiv = (tmp & AT91_PMC_OHCIUSBDIV) >> SAM9X5_USB_DIV_SHIFT;
-       return parent_rate / (usbdiv + 1);
+
+       return DIV_ROUND_CLOSEST(parent_rate, (usbdiv + 1));
 }
 
 static long at91sam9x5_clk_usb_round_rate(struct clk_hw *hw, unsigned long rate,
                                          unsigned long *parent_rate)
 {
        unsigned long div;
-       unsigned long bestrate;
-       unsigned long tmp;
+
+       if (!rate)
+               return -EINVAL;
 
        if (rate >= *parent_rate)
                return *parent_rate;
 
-       div = *parent_rate / rate;
-       if (div >= SAM9X5_USB_MAX_DIV)
-               return *parent_rate / (SAM9X5_USB_MAX_DIV + 1);
-
-       bestrate = *parent_rate / div;
-       tmp = *parent_rate / (div + 1);
-       if (bestrate - rate > rate - tmp)
-               bestrate = tmp;
+       div = DIV_ROUND_CLOSEST(*parent_rate, rate);
+       if (div > SAM9X5_USB_MAX_DIV + 1)
+               div = SAM9X5_USB_MAX_DIV + 1;
 
-       return bestrate;
+       return DIV_ROUND_CLOSEST(*parent_rate, div);
 }
 
 static int at91sam9x5_clk_usb_set_parent(struct clk_hw *hw, u8 index)
@@ -106,9 +103,13 @@ static int at91sam9x5_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate,
        u32 tmp;
        struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
        struct at91_pmc *pmc = usb->pmc;
-       unsigned long div = parent_rate / rate;
+       unsigned long div;
+
+       if (!rate)
+               return -EINVAL;
 
-       if (parent_rate % rate || div < 1 || div >= SAM9X5_USB_MAX_DIV)
+       div = DIV_ROUND_CLOSEST(parent_rate, rate);
+       if (div > SAM9X5_USB_MAX_DIV + 1 || !div)
                return -EINVAL;
 
        tmp = pmc_read(pmc, AT91_PMC_USB) & ~AT91_PMC_OHCIUSBDIV;
@@ -253,7 +254,7 @@ static long at91rm9200_clk_usb_round_rate(struct clk_hw *hw, unsigned long rate,
 
                tmp_parent_rate = rate * usb->divisors[i];
                tmp_parent_rate = __clk_round_rate(parent, tmp_parent_rate);
-               tmprate = tmp_parent_rate / usb->divisors[i];
+               tmprate = DIV_ROUND_CLOSEST(tmp_parent_rate, usb->divisors[i]);
                if (tmprate < rate)
                        tmpdiff = rate - tmprate;
                else
@@ -281,10 +282,10 @@ static int at91rm9200_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate,
        struct at91_pmc *pmc = usb->pmc;
        unsigned long div;
 
-       if (!rate || parent_rate % rate)
+       if (!rate)
                return -EINVAL;
 
-       div = parent_rate / rate;
+       div = DIV_ROUND_CLOSEST(parent_rate, rate);
 
        for (i = 0; i < RM9200_USB_DIV_TAB_SIZE; i++) {
                if (usb->divisors[i] == div) {
index 18a9de2..c0a842b 100644 (file)
@@ -263,6 +263,14 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
        if (!rate)
                rate = 1;
 
+       /* if read only, just return current value */
+       if (divider->flags & CLK_DIVIDER_READ_ONLY) {
+               bestdiv = readl(divider->reg) >> divider->shift;
+               bestdiv &= div_mask(divider);
+               bestdiv = _get_div(divider, bestdiv);
+               return bestdiv;
+       }
+
        maxdiv = _get_maxdiv(divider);
 
        if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) {
@@ -361,11 +369,6 @@ const struct clk_ops clk_divider_ops = {
 };
 EXPORT_SYMBOL_GPL(clk_divider_ops);
 
-const struct clk_ops clk_divider_ro_ops = {
-       .recalc_rate = clk_divider_recalc_rate,
-};
-EXPORT_SYMBOL_GPL(clk_divider_ro_ops);
-
 static struct clk *_register_divider(struct device *dev, const char *name,
                const char *parent_name, unsigned long flags,
                void __iomem *reg, u8 shift, u8 width,
@@ -391,10 +394,7 @@ static struct clk *_register_divider(struct device *dev, const char *name,
        }
 
        init.name = name;
-       if (clk_divider_flags & CLK_DIVIDER_READ_ONLY)
-               init.ops = &clk_divider_ro_ops;
-       else
-               init.ops = &clk_divider_ops;
+       init.ops = &clk_divider_ops;
        init.flags = flags | CLK_IS_BASIC;
        init.parent_names = (parent_name ? &parent_name: NULL);
        init.num_parents = (parent_name ? 1 : 0);
index b345cc7..88b9fe1 100644 (file)
@@ -322,7 +322,7 @@ static unsigned long clk_pxa27x_memory_get_rate(struct clk_hw *hw,
        unsigned long ccsr = CCSR;
 
        osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
-       a = cccr & CCCR_A_BIT;
+       a = cccr & (1 << CCCR_A_BIT);
        l  = ccsr & CCSR_L_MASK;
 
        if (osc_forced || a)
@@ -341,7 +341,7 @@ static u8 clk_pxa27x_memory_get_parent(struct clk_hw *hw)
        unsigned long ccsr = CCSR;
 
        osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
-       a = cccr & CCCR_A_BIT;
+       a = cccr & (1 << CCCR_A_BIT);
        if (osc_forced)
                return PXA_MEM_13Mhz;
        if (a)
index dab988a..157139a 100644 (file)
@@ -3122,7 +3122,7 @@ static struct clk_regmap *mmcc_apq8084_clocks[] = {
        [ESC1_CLK_SRC] = &esc1_clk_src.clkr,
        [HDMI_CLK_SRC] = &hdmi_clk_src.clkr,
        [VSYNC_CLK_SRC] = &vsync_clk_src.clkr,
-       [RBCPR_CLK_SRC] = &rbcpr_clk_src.clkr,
+       [MMSS_RBCPR_CLK_SRC] = &rbcpr_clk_src.clkr,
        [RBBMTIMER_CLK_SRC] = &rbbmtimer_clk_src.clkr,
        [MAPLE_CLK_SRC] = &maple_clk_src.clkr,
        [VDP_CLK_SRC] = &vdp_clk_src.clkr,
index 1e68bff..880a266 100644 (file)
@@ -90,9 +90,7 @@ static struct clk *rockchip_clk_register_branch(const char *name,
                div->width = div_width;
                div->lock = lock;
                div->table = div_table;
-               div_ops = (div_flags & CLK_DIVIDER_READ_ONLY)
-                                               ? &clk_divider_ro_ops
-                                               : &clk_divider_ops;
+               div_ops = &clk_divider_ops;
        }
 
        clk = clk_register_composite(NULL, name, parent_names, num_parents,
index 954b9f6..13dbd3d 100644 (file)
@@ -108,6 +108,38 @@ struct gpio_desc *__must_check __devm_gpiod_get_index(struct device *dev,
 }
 EXPORT_SYMBOL(__devm_gpiod_get_index);
 
+/**
+ * devm_get_gpiod_from_child - get a GPIO descriptor from a device's child node
+ * @dev:       GPIO consumer
+ * @child:     firmware node (child of @dev)
+ *
+ * GPIO descriptors returned from this function are automatically disposed on
+ * driver detach.
+ */
+struct gpio_desc *devm_get_gpiod_from_child(struct device *dev,
+                                           struct fwnode_handle *child)
+{
+       struct gpio_desc **dr;
+       struct gpio_desc *desc;
+
+       dr = devres_alloc(devm_gpiod_release, sizeof(struct gpio_desc *),
+                         GFP_KERNEL);
+       if (!dr)
+               return ERR_PTR(-ENOMEM);
+
+       desc = fwnode_get_named_gpiod(child, "gpios");
+       if (IS_ERR(desc)) {
+               devres_free(dr);
+               return desc;
+       }
+
+       *dr = desc;
+       devres_add(dev, dr);
+
+       return desc;
+}
+EXPORT_SYMBOL(devm_get_gpiod_from_child);
+
 /**
  * devm_gpiod_get_index_optional - Resource-managed gpiod_get_index_optional()
  * @dev: GPIO consumer
index 41e91d7..99720c8 100644 (file)
 
 #include <linux/gpio.h>
 
-static DEFINE_SPINLOCK(gpio_lock);
-
-#define CGEN   (0x00)
-#define CGIO   (0x04)
-#define CGLV   (0x08)
-
-#define RGEN   (0x20)
-#define RGIO   (0x24)
-#define RGLV   (0x28)
-
-static unsigned short gpio_ba;
-
-static int sch_gpio_core_direction_in(struct gpio_chip *gc, unsigned  gpio_num)
-{
-       u8 curr_dirs;
-       unsigned short offset, bit;
-
-       spin_lock(&gpio_lock);
-
-       offset = CGIO + gpio_num / 8;
-       bit = gpio_num % 8;
-
-       curr_dirs = inb(gpio_ba + offset);
-
-       if (!(curr_dirs & (1 << bit)))
-               outb(curr_dirs | (1 << bit), gpio_ba + offset);
+#define GEN    0x00
+#define GIO    0x04
+#define GLV    0x08
+
+struct sch_gpio {
+       struct gpio_chip chip;
+       spinlock_t lock;
+       unsigned short iobase;
+       unsigned short core_base;
+       unsigned short resume_base;
+};
 
-       spin_unlock(&gpio_lock);
-       return 0;
-}
+#define to_sch_gpio(c) container_of(c, struct sch_gpio, chip)
 
-static int sch_gpio_core_get(struct gpio_chip *gc, unsigned gpio_num)
+static unsigned sch_gpio_offset(struct sch_gpio *sch, unsigned gpio,
+                               unsigned reg)
 {
-       int res;
-       unsigned short offset, bit;
+       unsigned base = 0;
 
-       offset = CGLV + gpio_num / 8;
-       bit = gpio_num % 8;
+       if (gpio >= sch->resume_base) {
+               gpio -= sch->resume_base;
+               base += 0x20;
+       }
 
-       res = !!(inb(gpio_ba + offset) & (1 << bit));
-       return res;
+       return base + reg + gpio / 8;
 }
 
-static void sch_gpio_core_set(struct gpio_chip *gc, unsigned gpio_num, int val)
+static unsigned sch_gpio_bit(struct sch_gpio *sch, unsigned gpio)
 {
-       u8 curr_vals;
-       unsigned short offset, bit;
-
-       spin_lock(&gpio_lock);
-
-       offset = CGLV + gpio_num / 8;
-       bit = gpio_num % 8;
-
-       curr_vals = inb(gpio_ba + offset);
-
-       if (val)
-               outb(curr_vals | (1 << bit), gpio_ba + offset);
-       else
-               outb((curr_vals & ~(1 << bit)), gpio_ba + offset);
-       spin_unlock(&gpio_lock);
+       if (gpio >= sch->resume_base)
+               gpio -= sch->resume_base;
+       return gpio % 8;
 }
 
-static int sch_gpio_core_direction_out(struct gpio_chip *gc,
-                                       unsigned gpio_num, int val)
+static void sch_gpio_enable(struct sch_gpio *sch, unsigned gpio)
 {
-       u8 curr_dirs;
        unsigned short offset, bit;
+       u8 enable;
 
-       spin_lock(&gpio_lock);
+       spin_lock(&sch->lock);
 
-       offset = CGIO + gpio_num / 8;
-       bit = gpio_num % 8;
-
-       curr_dirs = inb(gpio_ba + offset);
-       if (curr_dirs & (1 << bit))
-               outb(curr_dirs & ~(1 << bit), gpio_ba + offset);
+       offset = sch_gpio_offset(sch, gpio, GEN);
+       bit = sch_gpio_bit(sch, gpio);
 
-       spin_unlock(&gpio_lock);
+       enable = inb(sch->iobase + offset);
+       if (!(enable & (1 << bit)))
+               outb(enable | (1 << bit), sch->iobase + offset);
 
-       /*
-        * according to the datasheet, writing to the level register has no
-        * effect when GPIO is programmed as input.
-        * Actually the the level register is read-only when configured as input.
-        * Thus presetting the output level before switching to output is _NOT_ possible.
-        * Hence we set the level after configuring the GPIO as output.
-        * But we cannot prevent a short low pulse if direction is set to high
-        * and an external pull-up is connected.
-        */
-       sch_gpio_core_set(gc, gpio_num, val);
-       return 0;
+       spin_unlock(&sch->lock);
 }
 
-static struct gpio_chip sch_gpio_core = {
-       .label                  = "sch_gpio_core",
-       .owner                  = THIS_MODULE,
-       .direction_input        = sch_gpio_core_direction_in,
-       .get                    = sch_gpio_core_get,
-       .direction_output       = sch_gpio_core_direction_out,
-       .set                    = sch_gpio_core_set,
-};
-
-static int sch_gpio_resume_direction_in(struct gpio_chip *gc,
-                                       unsigned gpio_num)
+static int sch_gpio_direction_in(struct gpio_chip *gc, unsigned  gpio_num)
 {
+       struct sch_gpio *sch = to_sch_gpio(gc);
        u8 curr_dirs;
        unsigned short offset, bit;
 
-       spin_lock(&gpio_lock);
+       spin_lock(&sch->lock);
 
-       offset = RGIO + gpio_num / 8;
-       bit = gpio_num % 8;
+       offset = sch_gpio_offset(sch, gpio_num, GIO);
+       bit = sch_gpio_bit(sch, gpio_num);
 
-       curr_dirs = inb(gpio_ba + offset);
+       curr_dirs = inb(sch->iobase + offset);
 
        if (!(curr_dirs & (1 << bit)))
-               outb(curr_dirs | (1 << bit), gpio_ba + offset);
+               outb(curr_dirs | (1 << bit), sch->iobase + offset);
 
-       spin_unlock(&gpio_lock);
+       spin_unlock(&sch->lock);
        return 0;
 }
 
-static int sch_gpio_resume_get(struct gpio_chip *gc, unsigned gpio_num)
+static int sch_gpio_get(struct gpio_chip *gc, unsigned gpio_num)
 {
+       struct sch_gpio *sch = to_sch_gpio(gc);
+       int res;
        unsigned short offset, bit;
 
-       offset = RGLV + gpio_num / 8;
-       bit = gpio_num % 8;
+       offset = sch_gpio_offset(sch, gpio_num, GLV);
+       bit = sch_gpio_bit(sch, gpio_num);
+
+       res = !!(inb(sch->iobase + offset) & (1 << bit));
 
-       return !!(inb(gpio_ba + offset) & (1 << bit));
+       return res;
 }
 
-static void sch_gpio_resume_set(struct gpio_chip *gc,
-                               unsigned gpio_num, int val)
+static void sch_gpio_set(struct gpio_chip *gc, unsigned gpio_num, int val)
 {
+       struct sch_gpio *sch = to_sch_gpio(gc);
        u8 curr_vals;
        unsigned short offset, bit;
 
-       spin_lock(&gpio_lock);
+       spin_lock(&sch->lock);
 
-       offset = RGLV + gpio_num / 8;
-       bit = gpio_num % 8;
+       offset = sch_gpio_offset(sch, gpio_num, GLV);
+       bit = sch_gpio_bit(sch, gpio_num);
 
-       curr_vals = inb(gpio_ba + offset);
+       curr_vals = inb(sch->iobase + offset);
 
        if (val)
-               outb(curr_vals | (1 << bit), gpio_ba + offset);
+               outb(curr_vals | (1 << bit), sch->iobase + offset);
        else
-               outb((curr_vals & ~(1 << bit)), gpio_ba + offset);
+               outb((curr_vals & ~(1 << bit)), sch->iobase + offset);
 
-       spin_unlock(&gpio_lock);
+       spin_unlock(&sch->lock);
 }
 
-static int sch_gpio_resume_direction_out(struct gpio_chip *gc,
-                                       unsigned gpio_num, int val)
+static int sch_gpio_direction_out(struct gpio_chip *gc, unsigned gpio_num,
+                                 int val)
 {
+       struct sch_gpio *sch = to_sch_gpio(gc);
        u8 curr_dirs;
        unsigned short offset, bit;
 
-       offset = RGIO + gpio_num / 8;
-       bit = gpio_num % 8;
+       spin_lock(&sch->lock);
 
-       spin_lock(&gpio_lock);
+       offset = sch_gpio_offset(sch, gpio_num, GIO);
+       bit = sch_gpio_bit(sch, gpio_num);
 
-       curr_dirs = inb(gpio_ba + offset);
+       curr_dirs = inb(sch->iobase + offset);
        if (curr_dirs & (1 << bit))
-               outb(curr_dirs & ~(1 << bit), gpio_ba + offset);
+               outb(curr_dirs & ~(1 << bit), sch->iobase + offset);
 
-       spin_unlock(&gpio_lock);
+       spin_unlock(&sch->lock);
 
        /*
-       * according to the datasheet, writing to the level register has no
-       * effect when GPIO is programmed as input.
-       * Actually the the level register is read-only when configured as input.
-       * Thus presetting the output level before switching to output is _NOT_ possible.
-       * Hence we set the level after configuring the GPIO as output.
-       * But we cannot prevent a short low pulse if direction is set to high
-       * and an external pull-up is connected.
-       */
-       sch_gpio_resume_set(gc, gpio_num, val);
+        * according to the datasheet, writing to the level register has no
+        * effect when GPIO is programmed as input.
+        * Actually the the level register is read-only when configured as input.
+        * Thus presetting the output level before switching to output is _NOT_ possible.
+        * Hence we set the level after configuring the GPIO as output.
+        * But we cannot prevent a short low pulse if direction is set to high
+        * and an external pull-up is connected.
+        */
+       sch_gpio_set(gc, gpio_num, val);
        return 0;
 }
 
-static struct gpio_chip sch_gpio_resume = {
-       .label                  = "sch_gpio_resume",
+static struct gpio_chip sch_gpio_chip = {
+       .label                  = "sch_gpio",
        .owner                  = THIS_MODULE,
-       .direction_input        = sch_gpio_resume_direction_in,
-       .get                    = sch_gpio_resume_get,
-       .direction_output       = sch_gpio_resume_direction_out,
-       .set                    = sch_gpio_resume_set,
+       .direction_input        = sch_gpio_direction_in,
+       .get                    = sch_gpio_get,
+       .direction_output       = sch_gpio_direction_out,
+       .set                    = sch_gpio_set,
 };
 
 static int sch_gpio_probe(struct platform_device *pdev)
 {
+       struct sch_gpio *sch;
        struct resource *res;
-       int err, id;
 
-       id = pdev->id;
-       if (!id)
-               return -ENODEV;
+       sch = devm_kzalloc(&pdev->dev, sizeof(*sch), GFP_KERNEL);
+       if (!sch)
+               return -ENOMEM;
 
        res = platform_get_resource(pdev, IORESOURCE_IO, 0);
        if (!res)
                return -EBUSY;
 
-       if (!request_region(res->start, resource_size(res), pdev->name))
+       if (!devm_request_region(&pdev->dev, res->start, resource_size(res),
+                                pdev->name))
                return -EBUSY;
 
-       gpio_ba = res->start;
+       spin_lock_init(&sch->lock);
+       sch->iobase = res->start;
+       sch->chip = sch_gpio_chip;
+       sch->chip.label = dev_name(&pdev->dev);
+       sch->chip.dev = &pdev->dev;
 
-       switch (id) {
+       switch (pdev->id) {
        case PCI_DEVICE_ID_INTEL_SCH_LPC:
-               sch_gpio_core.base = 0;
-               sch_gpio_core.ngpio = 10;
-               sch_gpio_resume.base = 10;
-               sch_gpio_resume.ngpio = 4;
+               sch->core_base = 0;
+               sch->resume_base = 10;
+               sch->chip.ngpio = 14;
+
                /*
                 * GPIO[6:0] enabled by default
                 * GPIO7 is configured by the CMC as SLPIOVR
                 * Enable GPIO[9:8] core powered gpios explicitly
                 */
-               outb(0x3, gpio_ba + CGEN + 1);
+               sch_gpio_enable(sch, 8);
+               sch_gpio_enable(sch, 9);
                /*
                 * SUS_GPIO[2:0] enabled by default
                 * Enable SUS_GPIO3 resume powered gpio explicitly
                 */
-               outb(0x8, gpio_ba + RGEN);
+               sch_gpio_enable(sch, 13);
                break;
 
        case PCI_DEVICE_ID_INTEL_ITC_LPC:
-               sch_gpio_core.base = 0;
-               sch_gpio_core.ngpio = 5;
-               sch_gpio_resume.base = 5;
-               sch_gpio_resume.ngpio = 9;
+               sch->core_base = 0;
+               sch->resume_base = 5;
+               sch->chip.ngpio = 14;
                break;
 
        case PCI_DEVICE_ID_INTEL_CENTERTON_ILB:
-               sch_gpio_core.base = 0;
-               sch_gpio_core.ngpio = 21;
-               sch_gpio_resume.base = 21;
-               sch_gpio_resume.ngpio = 9;
+               sch->core_base = 0;
+               sch->resume_base = 21;
+               sch->chip.ngpio = 30;
                break;
 
        default:
-               err = -ENODEV;
-               goto err_sch_gpio_core;
+               return -ENODEV;
        }
 
-       sch_gpio_core.dev = &pdev->dev;
-       sch_gpio_resume.dev = &pdev->dev;
-
-       err = gpiochip_add(&sch_gpio_core);
-       if (err < 0)
-               goto err_sch_gpio_core;
+       platform_set_drvdata(pdev, sch);
 
-       err = gpiochip_add(&sch_gpio_resume);
-       if (err < 0)
-               goto err_sch_gpio_resume;
-
-       return 0;
-
-err_sch_gpio_resume:
-       gpiochip_remove(&sch_gpio_core);
-
-err_sch_gpio_core:
-       release_region(res->start, resource_size(res));
-       gpio_ba = 0;
-
-       return err;
+       return gpiochip_add(&sch->chip);
 }
 
 static int sch_gpio_remove(struct platform_device *pdev)
 {
-       struct resource *res;
-       if (gpio_ba) {
-
-               gpiochip_remove(&sch_gpio_core);
-               gpiochip_remove(&sch_gpio_resume);
-
-               res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-
-               release_region(res->start, resource_size(res));
-               gpio_ba = 0;
-       }
+       struct sch_gpio *sch = platform_get_drvdata(pdev);
 
+       gpiochip_remove(&sch->chip);
        return 0;
 }
 
index 05c6275..ba98bb5 100644 (file)
@@ -287,9 +287,45 @@ void acpi_gpiochip_free_interrupts(struct gpio_chip *chip)
        }
 }
 
+int acpi_dev_add_driver_gpios(struct acpi_device *adev,
+                             const struct acpi_gpio_mapping *gpios)
+{
+       if (adev && gpios) {
+               adev->driver_gpios = gpios;
+               return 0;
+       }
+       return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_add_driver_gpios);
+
+static bool acpi_get_driver_gpio_data(struct acpi_device *adev,
+                                     const char *name, int index,
+                                     struct acpi_reference_args *args)
+{
+       const struct acpi_gpio_mapping *gm;
+
+       if (!adev->driver_gpios)
+               return false;
+
+       for (gm = adev->driver_gpios; gm->name; gm++)
+               if (!strcmp(name, gm->name) && gm->data && index < gm->size) {
+                       const struct acpi_gpio_params *par = gm->data + index;
+
+                       args->adev = adev;
+                       args->args[0] = par->crs_entry_index;
+                       args->args[1] = par->line_index;
+                       args->args[2] = par->active_low;
+                       args->nargs = 3;
+                       return true;
+               }
+
+       return false;
+}
+
 struct acpi_gpio_lookup {
        struct acpi_gpio_info info;
        int index;
+       int pin_index;
        struct gpio_desc *desc;
        int n;
 };
@@ -303,13 +339,24 @@ static int acpi_find_gpio(struct acpi_resource *ares, void *data)
 
        if (lookup->n++ == lookup->index && !lookup->desc) {
                const struct acpi_resource_gpio *agpio = &ares->data.gpio;
+               int pin_index = lookup->pin_index;
+
+               if (pin_index >= agpio->pin_table_length)
+                       return 1;
 
                lookup->desc = acpi_get_gpiod(agpio->resource_source.string_ptr,
-                                             agpio->pin_table[0]);
+                                             agpio->pin_table[pin_index]);
                lookup->info.gpioint =
                        agpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT;
-               lookup->info.active_low =
-                       agpio->polarity == ACPI_ACTIVE_LOW;
+
+               /*
+                * ActiveLow is only specified for GpioInt resource. If
+                * GpioIo is used then the only way to set the flag is
+                * to use _DSD "gpios" property.
+                */
+               if (lookup->info.gpioint)
+                       lookup->info.active_low =
+                               agpio->polarity == ACPI_ACTIVE_LOW;
        }
 
        return 1;
@@ -317,40 +364,79 @@ static int acpi_find_gpio(struct acpi_resource *ares, void *data)
 
 /**
  * acpi_get_gpiod_by_index() - get a GPIO descriptor from device resources
- * @dev: pointer to a device to get GPIO from
+ * @adev: pointer to a ACPI device to get GPIO from
+ * @propname: Property name of the GPIO (optional)
  * @index: index of GpioIo/GpioInt resource (starting from %0)
  * @info: info pointer to fill in (optional)
  *
- * Function goes through ACPI resources for @dev and based on @index looks
+ * Function goes through ACPI resources for @adev and based on @index looks
  * up a GpioIo/GpioInt resource, translates it to the Linux GPIO descriptor,
  * and returns it. @index matches GpioIo/GpioInt resources only so if there
  * are total %3 GPIO resources, the index goes from %0 to %2.
  *
+ * If @propname is specified the GPIO is looked using device property. In
+ * that case @index is used to select the GPIO entry in the property value
+ * (in case of multiple).
+ *
  * If the GPIO cannot be translated or there is an error an ERR_PTR is
  * returned.
  *
  * Note: if the GPIO resource has multiple entries in the pin list, this
  * function only returns the first.
  */
-struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index,
+struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev,
+                                         const char *propname, int index,
                                          struct acpi_gpio_info *info)
 {
        struct acpi_gpio_lookup lookup;
        struct list_head resource_list;
-       struct acpi_device *adev;
-       acpi_handle handle;
+       bool active_low = false;
        int ret;
 
-       if (!dev)
-               return ERR_PTR(-EINVAL);
-
-       handle = ACPI_HANDLE(dev);
-       if (!handle || acpi_bus_get_device(handle, &adev))
+       if (!adev)
                return ERR_PTR(-ENODEV);
 
        memset(&lookup, 0, sizeof(lookup));
        lookup.index = index;
 
+       if (propname) {
+               struct acpi_reference_args args;
+
+               dev_dbg(&adev->dev, "GPIO: looking up %s\n", propname);
+
+               memset(&args, 0, sizeof(args));
+               ret = acpi_dev_get_property_reference(adev, propname,
+                                                     index, &args);
+               if (ret) {
+                       bool found = acpi_get_driver_gpio_data(adev, propname,
+                                                              index, &args);
+                       if (!found)
+                               return ERR_PTR(ret);
+               }
+
+               /*
+                * The property was found and resolved so need to
+                * lookup the GPIO based on returned args instead.
+                */
+               adev = args.adev;
+               if (args.nargs >= 2) {
+                       lookup.index = args.args[0];
+                       lookup.pin_index = args.args[1];
+                       /*
+                        * 3rd argument, if present is used to
+                        * specify active_low.
+                        */
+                       if (args.nargs >= 3)
+                               active_low = !!args.args[2];
+               }
+
+               dev_dbg(&adev->dev, "GPIO: _DSD returned %s %zd %llu %llu %llu\n",
+                       dev_name(&adev->dev), args.nargs,
+                       args.args[0], args.args[1], args.args[2]);
+       } else {
+               dev_dbg(&adev->dev, "GPIO: looking up %d in _CRS\n", index);
+       }
+
        INIT_LIST_HEAD(&resource_list);
        ret = acpi_dev_get_resources(adev, &resource_list, acpi_find_gpio,
                                     &lookup);
@@ -359,8 +445,11 @@ struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index,
 
        acpi_dev_free_resource_list(&resource_list);
 
-       if (lookup.desc && info)
+       if (lookup.desc && info) {
                *info = lookup.info;
+               if (active_low)
+                       info->active_low = active_low;
+       }
 
        return lookup.desc ? lookup.desc : ERR_PTR(-ENOENT);
 }
index e8e98ca..58659db 100644 (file)
@@ -1505,14 +1505,36 @@ static struct gpio_desc *acpi_find_gpio(struct device *dev, const char *con_id,
                                        unsigned int idx,
                                        enum gpio_lookup_flags *flags)
 {
+       static const char * const suffixes[] = { "gpios", "gpio" };
+       struct acpi_device *adev = ACPI_COMPANION(dev);
        struct acpi_gpio_info info;
        struct gpio_desc *desc;
+       char propname[32];
+       int i;
 
-       desc = acpi_get_gpiod_by_index(dev, idx, &info);
-       if (IS_ERR(desc))
-               return desc;
+       /* Try first from _DSD */
+       for (i = 0; i < ARRAY_SIZE(suffixes); i++) {
+               if (con_id && strcmp(con_id, "gpios")) {
+                       snprintf(propname, sizeof(propname), "%s-%s",
+                                con_id, suffixes[i]);
+               } else {
+                       snprintf(propname, sizeof(propname), "%s",
+                                suffixes[i]);
+               }
+
+               desc = acpi_get_gpiod_by_index(adev, propname, idx, &info);
+               if (!IS_ERR(desc) || (PTR_ERR(desc) == -EPROBE_DEFER))
+                       break;
+       }
 
-       if (info.gpioint && info.active_low)
+       /* Then from plain _CRS GPIOs */
+       if (IS_ERR(desc)) {
+               desc = acpi_get_gpiod_by_index(adev, NULL, idx, &info);
+               if (IS_ERR(desc))
+                       return desc;
+       }
+
+       if (info.active_low)
                *flags |= GPIO_ACTIVE_LOW;
 
        return desc;
@@ -1712,6 +1734,61 @@ struct gpio_desc *__must_check __gpiod_get_index(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(__gpiod_get_index);
 
+/**
+ * fwnode_get_named_gpiod - obtain a GPIO from firmware node
+ * @fwnode:    handle of the firmware node
+ * @propname:  name of the firmware property representing the GPIO
+ *
+ * This function can be used for drivers that get their configuration
+ * from firmware.
+ *
+ * Function properly finds the corresponding GPIO using whatever is the
+ * underlying firmware interface and then makes sure that the GPIO
+ * descriptor is requested before it is returned to the caller.
+ *
+ * In case of error an ERR_PTR() is returned.
+ */
+struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
+                                        const char *propname)
+{
+       struct gpio_desc *desc = ERR_PTR(-ENODEV);
+       bool active_low = false;
+       int ret;
+
+       if (!fwnode)
+               return ERR_PTR(-EINVAL);
+
+       if (is_of_node(fwnode)) {
+               enum of_gpio_flags flags;
+
+               desc = of_get_named_gpiod_flags(of_node(fwnode), propname, 0,
+                                               &flags);
+               if (!IS_ERR(desc))
+                       active_low = flags & OF_GPIO_ACTIVE_LOW;
+       } else if (is_acpi_node(fwnode)) {
+               struct acpi_gpio_info info;
+
+               desc = acpi_get_gpiod_by_index(acpi_node(fwnode), propname, 0,
+                                              &info);
+               if (!IS_ERR(desc))
+                       active_low = info.active_low;
+       }
+
+       if (IS_ERR(desc))
+               return desc;
+
+       ret = gpiod_request(desc, NULL);
+       if (ret)
+               return ERR_PTR(ret);
+
+       /* Only value flag can be set from both DT and ACPI is active_low */
+       if (active_low)
+               set_bit(FLAG_ACTIVE_LOW, &desc->flags);
+
+       return desc;
+}
+EXPORT_SYMBOL_GPL(fwnode_get_named_gpiod);
+
 /**
  * gpiod_get_index_optional - obtain an optional GPIO from a multi-index GPIO
  *                            function
index 9db2b6a..e3a5211 100644 (file)
@@ -34,7 +34,8 @@ void acpi_gpiochip_remove(struct gpio_chip *chip);
 void acpi_gpiochip_request_interrupts(struct gpio_chip *chip);
 void acpi_gpiochip_free_interrupts(struct gpio_chip *chip);
 
-struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index,
+struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev,
+                                         const char *propname, int index,
                                          struct acpi_gpio_info *info);
 #else
 static inline void acpi_gpiochip_add(struct gpio_chip *chip) { }
@@ -47,8 +48,8 @@ static inline void
 acpi_gpiochip_free_interrupts(struct gpio_chip *chip) { }
 
 static inline struct gpio_desc *
-acpi_get_gpiod_by_index(struct device *dev, int index,
-                       struct acpi_gpio_info *info)
+acpi_get_gpiod_by_index(struct acpi_device *adev, const char *propname,
+                       int index, struct acpi_gpio_info *info)
 {
        return ERR_PTR(-ENOSYS);
 }
index f0a1a56..9cb5c95 100644 (file)
@@ -4325,7 +4325,6 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
                ironlake_fdi_disable(crtc);
 
                ironlake_disable_pch_transcoder(dev_priv, pipe);
-               intel_set_pch_fifo_underrun_reporting(dev, pipe, true);
 
                if (HAS_PCH_CPT(dev)) {
                        /* disable TRANS_DP_CTL */
@@ -4389,7 +4388,6 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
 
        if (intel_crtc->config.has_pch_encoder) {
                lpt_disable_pch_transcoder(dev_priv);
-               intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, true);
                intel_ddi_fdi_disable(crtc);
        }
 
@@ -9408,6 +9406,10 @@ static bool page_flip_finished(struct intel_crtc *crtc)
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
 
+       if (i915_reset_in_progress(&dev_priv->gpu_error) ||
+           crtc->reset_counter != atomic_read(&dev_priv->gpu_error.reset_counter))
+               return true;
+
        /*
         * The relevant registers doen't exist on pre-ctg.
         * As the flip done interrupt doesn't trigger for mmio
index 5ad45bf..4bcd917 100644 (file)
@@ -4450,6 +4450,7 @@ static void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder)
         * vdd might still be enabled do to the delayed vdd off.
         * Make sure vdd is actually turned off here.
         */
+       cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
        pps_lock(intel_dp);
        edp_panel_vdd_off_sync(intel_dp);
        pps_unlock(intel_dp);
index a6bd142..c0bbf21 100644 (file)
@@ -899,6 +899,17 @@ void intel_lvds_init(struct drm_device *dev)
        int pipe;
        u8 pin;
 
+       /*
+        * Unlock registers and just leave them unlocked. Do this before
+        * checking quirk lists to avoid bogus WARNINGs.
+        */
+       if (HAS_PCH_SPLIT(dev)) {
+               I915_WRITE(PCH_PP_CONTROL,
+                          I915_READ(PCH_PP_CONTROL) | PANEL_UNLOCK_REGS);
+       } else {
+               I915_WRITE(PP_CONTROL,
+                          I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS);
+       }
        if (!intel_lvds_supported(dev))
                return;
 
@@ -1097,17 +1108,6 @@ out:
        lvds_encoder->a3_power = I915_READ(lvds_encoder->reg) &
                                 LVDS_A3_POWER_MASK;
 
-       /*
-        * Unlock registers and just
-        * leave them unlocked
-        */
-       if (HAS_PCH_SPLIT(dev)) {
-               I915_WRITE(PCH_PP_CONTROL,
-                          I915_READ(PCH_PP_CONTROL) | PANEL_UNLOCK_REGS);
-       } else {
-               I915_WRITE(PP_CONTROL,
-                          I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS);
-       }
        lvds_connector->lid_notifier.notifier_call = intel_lid_notify;
        if (acpi_lid_notifier_register(&lvds_connector->lid_notifier)) {
                DRM_DEBUG_KMS("lid notifier registration failed\n");
index cd05677..72a40f9 100644 (file)
@@ -218,7 +218,6 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_BSP    ] = &nvc0_bsp_oclass;
                device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass;
                device->oclass[NVDEV_ENGINE_COPY0  ] = &nvc0_copy0_oclass;
-               device->oclass[NVDEV_ENGINE_COPY1  ] = &nvc0_copy1_oclass;
                device->oclass[NVDEV_ENGINE_DISP   ] =  nva3_disp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;
                break;
index 5ae6a43..1931057 100644 (file)
@@ -551,8 +551,8 @@ nv04_fifo_intr(struct nouveau_subdev *subdev)
                        }
 
                        if (status & 0x40000000) {
-                               nouveau_fifo_uevent(&priv->base);
                                nv_wr32(priv, 0x002100, 0x40000000);
+                               nouveau_fifo_uevent(&priv->base);
                                status &= ~0x40000000;
                        }
                }
index 1fe1f8f..074d434 100644 (file)
@@ -740,6 +740,8 @@ nvc0_fifo_intr_engine_unit(struct nvc0_fifo_priv *priv, int engn)
        u32 inte = nv_rd32(priv, 0x002628);
        u32 unkn;
 
+       nv_wr32(priv, 0x0025a8 + (engn * 0x04), intr);
+
        for (unkn = 0; unkn < 8; unkn++) {
                u32 ints = (intr >> (unkn * 0x04)) & inte;
                if (ints & 0x1) {
@@ -751,8 +753,6 @@ nvc0_fifo_intr_engine_unit(struct nvc0_fifo_priv *priv, int engn)
                        nv_mask(priv, 0x002628, ints, 0);
                }
        }
-
-       nv_wr32(priv, 0x0025a8 + (engn * 0x04), intr);
 }
 
 static void
index d2f0fd3..f8734eb 100644 (file)
@@ -952,8 +952,8 @@ nve0_fifo_intr(struct nouveau_subdev *subdev)
        }
 
        if (stat & 0x80000000) {
-               nve0_fifo_intr_engine(priv);
                nv_wr32(priv, 0x002100, 0x80000000);
+               nve0_fifo_intr_engine(priv);
                stat &= ~0x80000000;
        }
 
index 5723807..62b97c4 100644 (file)
@@ -629,7 +629,6 @@ int nouveau_pmops_suspend(struct device *dev)
 
        pci_save_state(pdev);
        pci_disable_device(pdev);
-       pci_ignore_hotplug(pdev);
        pci_set_power_state(pdev, PCI_D3hot);
        return 0;
 }
@@ -933,6 +932,7 @@ static int nouveau_pmops_runtime_suspend(struct device *dev)
        ret = nouveau_do_suspend(drm_dev, true);
        pci_save_state(pdev);
        pci_disable_device(pdev);
+       pci_ignore_hotplug(pdev);
        pci_set_power_state(pdev, PCI_D3cold);
        drm_dev->switch_power_state = DRM_SWITCH_POWER_DYNAMIC_OFF;
        return ret;
index 515cd9a..f32a434 100644 (file)
@@ -52,20 +52,24 @@ nouveau_fctx(struct nouveau_fence *fence)
        return container_of(fence->base.lock, struct nouveau_fence_chan, lock);
 }
 
-static void
+static int
 nouveau_fence_signal(struct nouveau_fence *fence)
 {
+       int drop = 0;
+
        fence_signal_locked(&fence->base);
        list_del(&fence->head);
+       rcu_assign_pointer(fence->channel, NULL);
 
        if (test_bit(FENCE_FLAG_USER_BITS, &fence->base.flags)) {
                struct nouveau_fence_chan *fctx = nouveau_fctx(fence);
 
                if (!--fctx->notify_ref)
-                       nvif_notify_put(&fctx->notify);
+                       drop = 1;
        }
 
        fence_put(&fence->base);
+       return drop;
 }
 
 static struct nouveau_fence *
@@ -88,16 +92,23 @@ nouveau_fence_context_del(struct nouveau_fence_chan *fctx)
 {
        struct nouveau_fence *fence;
 
-       nvif_notify_fini(&fctx->notify);
-
        spin_lock_irq(&fctx->lock);
        while (!list_empty(&fctx->pending)) {
                fence = list_entry(fctx->pending.next, typeof(*fence), head);
 
-               nouveau_fence_signal(fence);
-               fence->channel = NULL;
+               if (nouveau_fence_signal(fence))
+                       nvif_notify_put(&fctx->notify);
        }
        spin_unlock_irq(&fctx->lock);
+
+       nvif_notify_fini(&fctx->notify);
+       fctx->dead = 1;
+
+       /*
+        * Ensure that all accesses to fence->channel complete before freeing
+        * the channel.
+        */
+       synchronize_rcu();
 }
 
 static void
@@ -112,21 +123,23 @@ nouveau_fence_context_free(struct nouveau_fence_chan *fctx)
        kref_put(&fctx->fence_ref, nouveau_fence_context_put);
 }
 
-static void
+static int
 nouveau_fence_update(struct nouveau_channel *chan, struct nouveau_fence_chan *fctx)
 {
        struct nouveau_fence *fence;
-
+       int drop = 0;
        u32 seq = fctx->read(chan);
 
        while (!list_empty(&fctx->pending)) {
                fence = list_entry(fctx->pending.next, typeof(*fence), head);
 
                if ((int)(seq - fence->base.seqno) < 0)
-                       return;
+                       break;
 
-               nouveau_fence_signal(fence);
+               drop |= nouveau_fence_signal(fence);
        }
+
+       return drop;
 }
 
 static int
@@ -135,18 +148,21 @@ nouveau_fence_wait_uevent_handler(struct nvif_notify *notify)
        struct nouveau_fence_chan *fctx =
                container_of(notify, typeof(*fctx), notify);
        unsigned long flags;
+       int ret = NVIF_NOTIFY_KEEP;
 
        spin_lock_irqsave(&fctx->lock, flags);
        if (!list_empty(&fctx->pending)) {
                struct nouveau_fence *fence;
+               struct nouveau_channel *chan;
 
                fence = list_entry(fctx->pending.next, typeof(*fence), head);
-               nouveau_fence_update(fence->channel, fctx);
+               chan = rcu_dereference_protected(fence->channel, lockdep_is_held(&fctx->lock));
+               if (nouveau_fence_update(fence->channel, fctx))
+                       ret = NVIF_NOTIFY_DROP;
        }
        spin_unlock_irqrestore(&fctx->lock, flags);
 
-       /* Always return keep here. NVIF refcount is handled with nouveau_fence_update */
-       return NVIF_NOTIFY_KEEP;
+       return ret;
 }
 
 void
@@ -262,7 +278,10 @@ nouveau_fence_emit(struct nouveau_fence *fence, struct nouveau_channel *chan)
        if (!ret) {
                fence_get(&fence->base);
                spin_lock_irq(&fctx->lock);
-               nouveau_fence_update(chan, fctx);
+
+               if (nouveau_fence_update(chan, fctx))
+                       nvif_notify_put(&fctx->notify);
+
                list_add_tail(&fence->head, &fctx->pending);
                spin_unlock_irq(&fctx->lock);
        }
@@ -276,13 +295,16 @@ nouveau_fence_done(struct nouveau_fence *fence)
        if (fence->base.ops == &nouveau_fence_ops_legacy ||
            fence->base.ops == &nouveau_fence_ops_uevent) {
                struct nouveau_fence_chan *fctx = nouveau_fctx(fence);
+               struct nouveau_channel *chan;
                unsigned long flags;
 
                if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->base.flags))
                        return true;
 
                spin_lock_irqsave(&fctx->lock, flags);
-               nouveau_fence_update(fence->channel, fctx);
+               chan = rcu_dereference_protected(fence->channel, lockdep_is_held(&fctx->lock));
+               if (chan && nouveau_fence_update(chan, fctx))
+                       nvif_notify_put(&fctx->notify);
                spin_unlock_irqrestore(&fctx->lock, flags);
        }
        return fence_is_signaled(&fence->base);
@@ -387,12 +409,18 @@ nouveau_fence_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan, bool e
 
        if (fence && (!exclusive || !fobj || !fobj->shared_count)) {
                struct nouveau_channel *prev = NULL;
+               bool must_wait = true;
 
                f = nouveau_local_fence(fence, chan->drm);
-               if (f)
-                       prev = f->channel;
+               if (f) {
+                       rcu_read_lock();
+                       prev = rcu_dereference(f->channel);
+                       if (prev && (prev == chan || fctx->sync(f, prev, chan) == 0))
+                               must_wait = false;
+                       rcu_read_unlock();
+               }
 
-               if (!prev || (prev != chan && (ret = fctx->sync(f, prev, chan))))
+               if (must_wait)
                        ret = fence_wait(fence, intr);
 
                return ret;
@@ -403,19 +431,22 @@ nouveau_fence_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan, bool e
 
        for (i = 0; i < fobj->shared_count && !ret; ++i) {
                struct nouveau_channel *prev = NULL;
+               bool must_wait = true;
 
                fence = rcu_dereference_protected(fobj->shared[i],
                                                reservation_object_held(resv));
 
                f = nouveau_local_fence(fence, chan->drm);
-               if (f)
-                       prev = f->channel;
+               if (f) {
+                       rcu_read_lock();
+                       prev = rcu_dereference(f->channel);
+                       if (prev && (prev == chan || fctx->sync(f, prev, chan) == 0))
+                               must_wait = false;
+                       rcu_read_unlock();
+               }
 
-               if (!prev || (prev != chan && (ret = fctx->sync(f, prev, chan))))
+               if (must_wait)
                        ret = fence_wait(fence, intr);
-
-               if (ret)
-                       break;
        }
 
        return ret;
@@ -463,7 +494,7 @@ static const char *nouveau_fence_get_timeline_name(struct fence *f)
        struct nouveau_fence *fence = from_fence(f);
        struct nouveau_fence_chan *fctx = nouveau_fctx(fence);
 
-       return fence->channel ? fctx->name : "dead channel";
+       return !fctx->dead ? fctx->name : "dead channel";
 }
 
 /*
@@ -476,9 +507,16 @@ static bool nouveau_fence_is_signaled(struct fence *f)
 {
        struct nouveau_fence *fence = from_fence(f);
        struct nouveau_fence_chan *fctx = nouveau_fctx(fence);
-       struct nouveau_channel *chan = fence->channel;
+       struct nouveau_channel *chan;
+       bool ret = false;
+
+       rcu_read_lock();
+       chan = rcu_dereference(fence->channel);
+       if (chan)
+               ret = (int)(fctx->read(chan) - fence->base.seqno) >= 0;
+       rcu_read_unlock();
 
-       return (int)(fctx->read(chan) - fence->base.seqno) >= 0;
+       return ret;
 }
 
 static bool nouveau_fence_no_signaling(struct fence *f)
index 943b0b1..96e461c 100644 (file)
@@ -14,7 +14,7 @@ struct nouveau_fence {
 
        bool sysmem;
 
-       struct nouveau_channel *channel;
+       struct nouveau_channel __rcu *channel;
        unsigned long timeout;
 };
 
@@ -47,7 +47,7 @@ struct nouveau_fence_chan {
        char name[32];
 
        struct nvif_notify notify;
-       int notify_ref;
+       int notify_ref, dead;
 };
 
 struct nouveau_fence_priv {
index 300c4b3..26baa9c 100644 (file)
@@ -322,6 +322,12 @@ static void radeon_connector_get_edid(struct drm_connector *connector)
        }
 
        if (!radeon_connector->edid) {
+               /* don't fetch the edid from the vbios if ddc fails and runpm is
+                * enabled so we report disconnected.
+                */
+               if ((rdev->flags & RADEON_IS_PX) && (radeon_runtime_pm != 0))
+                       return;
+
                if (rdev->is_atom_bios) {
                        /* some laptops provide a hardcoded edid in rom for LCDs */
                        if (((connector->connector_type == DRM_MODE_CONNECTOR_LVDS) ||
@@ -826,6 +832,8 @@ static int radeon_lvds_mode_valid(struct drm_connector *connector,
 static enum drm_connector_status
 radeon_lvds_detect(struct drm_connector *connector, bool force)
 {
+       struct drm_device *dev = connector->dev;
+       struct radeon_device *rdev = dev->dev_private;
        struct radeon_connector *radeon_connector = to_radeon_connector(connector);
        struct drm_encoder *encoder = radeon_best_single_encoder(connector);
        enum drm_connector_status ret = connector_status_disconnected;
@@ -842,7 +850,11 @@ radeon_lvds_detect(struct drm_connector *connector, bool force)
                /* check if panel is valid */
                if (native_mode->hdisplay >= 320 && native_mode->vdisplay >= 240)
                        ret = connector_status_connected;
-
+               /* don't fetch the edid from the vbios if ddc fails and runpm is
+                * enabled so we report disconnected.
+                */
+               if ((rdev->flags & RADEON_IS_PX) && (radeon_runtime_pm != 0))
+                       ret = connector_status_disconnected;
        }
 
        /* check for edid as well */
@@ -1589,6 +1601,11 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
                        /* check if panel is valid */
                        if (native_mode->hdisplay >= 320 && native_mode->vdisplay >= 240)
                                ret = connector_status_connected;
+                       /* don't fetch the edid from the vbios if ddc fails and runpm is
+                        * enabled so we report disconnected.
+                        */
+                       if ((rdev->flags & RADEON_IS_PX) && (radeon_runtime_pm != 0))
+                               ret = connector_status_disconnected;
                }
                /* eDP is always DP */
                radeon_dig_connector->dp_sink_type = CONNECTOR_OBJECT_ID_DISPLAYPORT;
index a3e7aed..6f377de 100644 (file)
@@ -251,22 +251,19 @@ static int radeon_cs_get_ring(struct radeon_cs_parser *p, u32 ring, s32 priority
 
 static int radeon_cs_sync_rings(struct radeon_cs_parser *p)
 {
-       int i, r = 0;
+       struct radeon_cs_reloc *reloc;
+       int r;
 
-       for (i = 0; i < p->nrelocs; i++) {
+       list_for_each_entry(reloc, &p->validated, tv.head) {
                struct reservation_object *resv;
 
-               if (!p->relocs[i].robj)
-                       continue;
-
-               resv = p->relocs[i].robj->tbo.resv;
+               resv = reloc->robj->tbo.resv;
                r = radeon_semaphore_sync_resv(p->rdev, p->ib.semaphore, resv,
-                                              p->relocs[i].tv.shared);
-
+                                              reloc->tv.shared);
                if (r)
-                       break;
+                       return r;
        }
-       return r;
+       return 0;
 }
 
 /* XXX: note that this is called from the legacy UMS CS ioctl as well */
index 7784911..00fc597 100644 (file)
@@ -185,6 +185,16 @@ static bool radeon_msi_ok(struct radeon_device *rdev)
        if (rdev->flags & RADEON_IS_AGP)
                return false;
 
+       /*
+        * Older chips have a HW limitation, they can only generate 40 bits
+        * of address for "64-bit" MSIs which breaks on some platforms, notably
+        * IBM POWER servers, so we limit them
+        */
+       if (rdev->family < CHIP_BONAIRE) {
+               dev_info(rdev->dev, "radeon: MSI limited to 32-bit\n");
+               rdev->pdev->no_64bit_msi = 1;
+       }
+
        /* force MSI on */
        if (radeon_msi == 1)
                return true;
index 8309b11..0358676 100644 (file)
@@ -795,6 +795,8 @@ int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc,
 
        /* Get associated drm_crtc: */
        drmcrtc = &rdev->mode_info.crtcs[crtc]->base;
+       if (!drmcrtc)
+               return -EINVAL;
 
        /* Helper routine in DRM core does all the work: */
        return drm_calc_vbltimestamp_from_scanoutpos(dev, crtc, max_error,
index 99a960a..4c0d786 100644 (file)
@@ -213,6 +213,13 @@ int radeon_bo_create(struct radeon_device *rdev,
        if (!(rdev->flags & RADEON_IS_PCIE))
                bo->flags &= ~(RADEON_GEM_GTT_WC | RADEON_GEM_GTT_UC);
 
+#ifdef CONFIG_X86_32
+       /* XXX: Write-combined CPU mappings of GTT seem broken on 32-bit
+        * See https://bugs.freedesktop.org/show_bug.cgi?id=84627
+        */
+       bo->flags &= ~RADEON_GEM_GTT_WC;
+#endif
+
        radeon_ttm_placement_from_domain(bo, domain);
        /* Kernel allocation are uninterruptible */
        down_read(&rdev->pm.mclk_lock);
index 6aac695..9b55e67 100644 (file)
@@ -1084,10 +1084,8 @@ static int g762_probe(struct i2c_client *client, const struct i2c_device_id *id)
        if (ret)
                goto clock_dis;
 
-       data->hwmon_dev = devm_hwmon_device_register_with_groups(dev,
-                                                                client->name,
-                                                                data,
-                                                                g762_groups);
+       data->hwmon_dev = hwmon_device_register_with_groups(dev, client->name,
+                                                           data, g762_groups);
        if (IS_ERR(data->hwmon_dev)) {
                ret = PTR_ERR(data->hwmon_dev);
                goto clock_dis;
index 63f3f03..c604f4c 100644 (file)
 #define CDNS_I2C_DIVA_MAX      4
 #define CDNS_I2C_DIVB_MAX      64
 
+#define CDNS_I2C_TIMEOUT_MAX   0xFF
+
 #define cdns_i2c_readreg(offset)       readl_relaxed(id->membase + offset)
 #define cdns_i2c_writereg(val, offset) writel_relaxed(val, id->membase + offset)
 
@@ -852,6 +854,15 @@ static int cdns_i2c_probe(struct platform_device *pdev)
                goto err_clk_dis;
        }
 
+       /*
+        * Cadence I2C controller has a bug wherein it generates
+        * invalid read transaction after HW timeout in master receiver mode.
+        * HW timeout is not used by this driver and the interrupt is disabled.
+        * But the feature itself cannot be disabled. Hence maximum value
+        * is written to this register to reduce the chances of error.
+        */
+       cdns_i2c_writereg(CDNS_I2C_TIMEOUT_MAX, CDNS_I2C_TIME_OUT_OFFSET);
+
        dev_info(&pdev->dev, "%u kHz mmio %08lx irq %d\n",
                 id->i2c_clk / 1000, (unsigned long)r_mem->start, id->irq);
 
index d15b7c9..01f0cd8 100644 (file)
@@ -407,11 +407,9 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
        if (dev->cmd_err & DAVINCI_I2C_STR_NACK) {
                if (msg->flags & I2C_M_IGNORE_NAK)
                        return msg->len;
-               if (stop) {
-                       w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG);
-                       w |= DAVINCI_I2C_MDR_STP;
-                       davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w);
-               }
+               w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG);
+               w |= DAVINCI_I2C_MDR_STP;
+               davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w);
                return -EREMOTEIO;
        }
        return -EIO;
index edca99d..23628b7 100644 (file)
@@ -359,7 +359,7 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
        }
 
        /* Configure Tx/Rx FIFO threshold levels */
-       dw_writel(dev, dev->tx_fifo_depth - 1, DW_IC_TX_TL);
+       dw_writel(dev, dev->tx_fifo_depth / 2, DW_IC_TX_TL);
        dw_writel(dev, 0, DW_IC_RX_TL);
 
        /* configure the i2c master */
index 26942c1..277a228 100644 (file)
@@ -922,14 +922,12 @@ omap_i2c_isr_thread(int this_irq, void *dev_id)
                if (stat & OMAP_I2C_STAT_NACK) {
                        err |= OMAP_I2C_STAT_NACK;
                        omap_i2c_ack_stat(dev, OMAP_I2C_STAT_NACK);
-                       break;
                }
 
                if (stat & OMAP_I2C_STAT_AL) {
                        dev_err(dev->dev, "Arbitration lost\n");
                        err |= OMAP_I2C_STAT_AL;
                        omap_i2c_ack_stat(dev, OMAP_I2C_STAT_AL);
-                       break;
                }
 
                /*
@@ -954,11 +952,13 @@ omap_i2c_isr_thread(int this_irq, void *dev_id)
                        if (dev->fifo_size)
                                num_bytes = dev->buf_len;
 
-                       omap_i2c_receive_data(dev, num_bytes, true);
-
-                       if (dev->errata & I2C_OMAP_ERRATA_I207)
+                       if (dev->errata & I2C_OMAP_ERRATA_I207) {
                                i2c_omap_errata_i207(dev, stat);
+                               num_bytes = (omap_i2c_read_reg(dev,
+                                       OMAP_I2C_BUFSTAT_REG) >> 8) & 0x3F;
+                       }
 
+                       omap_i2c_receive_data(dev, num_bytes, true);
                        omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RDR);
                        continue;
                }
index 22c096c..513bd6d 100644 (file)
@@ -44,6 +44,9 @@
 
 #define BMC150_ACCEL_REG_INT_STATUS_2          0x0B
 #define BMC150_ACCEL_ANY_MOTION_MASK           0x07
+#define BMC150_ACCEL_ANY_MOTION_BIT_X          BIT(0)
+#define BMC150_ACCEL_ANY_MOTION_BIT_Y          BIT(1)
+#define BMC150_ACCEL_ANY_MOTION_BIT_Z          BIT(2)
 #define BMC150_ACCEL_ANY_MOTION_BIT_SIGN       BIT(3)
 
 #define BMC150_ACCEL_REG_PMU_LPW               0x11
@@ -92,9 +95,9 @@
 #define BMC150_ACCEL_SLOPE_THRES_MASK          0xFF
 
 /* Slope duration in terms of number of samples */
-#define BMC150_ACCEL_DEF_SLOPE_DURATION        2
+#define BMC150_ACCEL_DEF_SLOPE_DURATION                1
 /* in terms of multiples of g's/LSB, based on range */
-#define BMC150_ACCEL_DEF_SLOPE_THRESHOLD       5
+#define BMC150_ACCEL_DEF_SLOPE_THRESHOLD       1
 
 #define BMC150_ACCEL_REG_XOUT_L                0x02
 
@@ -536,6 +539,9 @@ static int bmc150_accel_set_power_state(struct bmc150_accel_data *data, bool on)
        if (ret < 0) {
                dev_err(&data->client->dev,
                        "Failed: bmc150_accel_set_power_state for %d\n", on);
+               if (on)
+                       pm_runtime_put_noidle(&data->client->dev);
+
                return ret;
        }
 
@@ -811,6 +817,7 @@ static int bmc150_accel_write_event_config(struct iio_dev *indio_dev,
 
        ret =  bmc150_accel_setup_any_motion_interrupt(data, state);
        if (ret < 0) {
+               bmc150_accel_set_power_state(data, false);
                mutex_unlock(&data->mutex);
                return ret;
        }
@@ -846,7 +853,7 @@ static const struct attribute_group bmc150_accel_attrs_group = {
 
 static const struct iio_event_spec bmc150_accel_event = {
                .type = IIO_EV_TYPE_ROC,
-               .dir = IIO_EV_DIR_RISING | IIO_EV_DIR_FALLING,
+               .dir = IIO_EV_DIR_EITHER,
                .mask_separate = BIT(IIO_EV_INFO_VALUE) |
                                 BIT(IIO_EV_INFO_ENABLE) |
                                 BIT(IIO_EV_INFO_PERIOD)
@@ -1054,6 +1061,7 @@ static int bmc150_accel_data_rdy_trigger_set_state(struct iio_trigger *trig,
        else
                ret = bmc150_accel_setup_new_data_interrupt(data, state);
        if (ret < 0) {
+               bmc150_accel_set_power_state(data, false);
                mutex_unlock(&data->mutex);
                return ret;
        }
@@ -1092,12 +1100,26 @@ static irqreturn_t bmc150_accel_event_handler(int irq, void *private)
        else
                dir = IIO_EV_DIR_RISING;
 
-       if (ret & BMC150_ACCEL_ANY_MOTION_MASK)
+       if (ret & BMC150_ACCEL_ANY_MOTION_BIT_X)
+               iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL,
+                                                       0,
+                                                       IIO_MOD_X,
+                                                       IIO_EV_TYPE_ROC,
+                                                       dir),
+                                                       data->timestamp);
+       if (ret & BMC150_ACCEL_ANY_MOTION_BIT_Y)
                iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL,
                                                        0,
-                                                       IIO_MOD_X_OR_Y_OR_Z,
+                                                       IIO_MOD_Y,
                                                        IIO_EV_TYPE_ROC,
-                                                       IIO_EV_DIR_EITHER),
+                                                       dir),
+                                                       data->timestamp);
+       if (ret & BMC150_ACCEL_ANY_MOTION_BIT_Z)
+               iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL,
+                                                       0,
+                                                       IIO_MOD_Z,
+                                                       IIO_EV_TYPE_ROC,
+                                                       dir),
                                                        data->timestamp);
 ack_intr_status:
        if (!data->dready_trigger_on)
@@ -1354,10 +1376,14 @@ static int bmc150_accel_runtime_suspend(struct device *dev)
 {
        struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
        struct bmc150_accel_data *data = iio_priv(indio_dev);
+       int ret;
 
        dev_dbg(&data->client->dev,  __func__);
+       ret = bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_SUSPEND, 0);
+       if (ret < 0)
+               return -EAGAIN;
 
-       return bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_SUSPEND, 0);
+       return 0;
 }
 
 static int bmc150_accel_runtime_resume(struct device *dev)
index a23e58c..320aa72 100644 (file)
@@ -269,6 +269,8 @@ static int kxcjk1013_set_range(struct kxcjk1013_data *data, int range_index)
                return ret;
        }
 
+       ret &= ~(KXCJK1013_REG_CTRL1_BIT_GSEL0 |
+                KXCJK1013_REG_CTRL1_BIT_GSEL1);
        ret |= (KXCJK1013_scale_table[range_index].gsel_0 << 3);
        ret |= (KXCJK1013_scale_table[range_index].gsel_1 << 4);
 
index b58d630..d095efe 100644 (file)
@@ -152,6 +152,7 @@ static void men_z188_remove(struct mcb_device *dev)
 
 static const struct mcb_device_id men_z188_ids[] = {
        { .device = 0xbc },
+       { }
 };
 MODULE_DEVICE_TABLE(mcb, men_z188_ids);
 
index 1f967e0..d2fa526 100644 (file)
@@ -67,6 +67,9 @@
 #define BMG160_REG_INT_EN_0            0x15
 #define BMG160_DATA_ENABLE_INT         BIT(7)
 
+#define BMG160_REG_INT_EN_1            0x16
+#define BMG160_INT1_BIT_OD             BIT(1)
+
 #define BMG160_REG_XOUT_L              0x02
 #define BMG160_AXIS_TO_REG(axis)       (BMG160_REG_XOUT_L + (axis * 2))
 
@@ -82,6 +85,9 @@
 
 #define BMG160_REG_INT_STATUS_2        0x0B
 #define BMG160_ANY_MOTION_MASK         0x07
+#define BMG160_ANY_MOTION_BIT_X                BIT(0)
+#define BMG160_ANY_MOTION_BIT_Y                BIT(1)
+#define BMG160_ANY_MOTION_BIT_Z                BIT(2)
 
 #define BMG160_REG_TEMP                0x08
 #define BMG160_TEMP_CENTER_VAL         23
@@ -222,6 +228,19 @@ static int bmg160_chip_init(struct bmg160_data *data)
        data->slope_thres = ret;
 
        /* Set default interrupt mode */
+       ret = i2c_smbus_read_byte_data(data->client, BMG160_REG_INT_EN_1);
+       if (ret < 0) {
+               dev_err(&data->client->dev, "Error reading reg_int_en_1\n");
+               return ret;
+       }
+       ret &= ~BMG160_INT1_BIT_OD;
+       ret = i2c_smbus_write_byte_data(data->client,
+                                       BMG160_REG_INT_EN_1, ret);
+       if (ret < 0) {
+               dev_err(&data->client->dev, "Error writing reg_int_en_1\n");
+               return ret;
+       }
+
        ret = i2c_smbus_write_byte_data(data->client,
                                        BMG160_REG_INT_RST_LATCH,
                                        BMG160_INT_MODE_LATCH_INT |
@@ -250,6 +269,9 @@ static int bmg160_set_power_state(struct bmg160_data *data, bool on)
        if (ret < 0) {
                dev_err(&data->client->dev,
                        "Failed: bmg160_set_power_state for %d\n", on);
+               if (on)
+                       pm_runtime_put_noidle(&data->client->dev);
+
                return ret;
        }
 #endif
@@ -705,6 +727,7 @@ static int bmg160_write_event_config(struct iio_dev *indio_dev,
 
        ret =  bmg160_setup_any_motion_interrupt(data, state);
        if (ret < 0) {
+               bmg160_set_power_state(data, false);
                mutex_unlock(&data->mutex);
                return ret;
        }
@@ -743,7 +766,7 @@ static const struct attribute_group bmg160_attrs_group = {
 
 static const struct iio_event_spec bmg160_event = {
                .type = IIO_EV_TYPE_ROC,
-               .dir = IIO_EV_DIR_RISING | IIO_EV_DIR_FALLING,
+               .dir = IIO_EV_DIR_EITHER,
                .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) |
                                       BIT(IIO_EV_INFO_ENABLE)
 };
@@ -871,6 +894,7 @@ static int bmg160_data_rdy_trigger_set_state(struct iio_trigger *trig,
        else
                ret = bmg160_setup_new_data_interrupt(data, state);
        if (ret < 0) {
+               bmg160_set_power_state(data, false);
                mutex_unlock(&data->mutex);
                return ret;
        }
@@ -908,10 +932,24 @@ static irqreturn_t bmg160_event_handler(int irq, void *private)
        else
                dir = IIO_EV_DIR_FALLING;
 
-       if (ret & BMG160_ANY_MOTION_MASK)
+       if (ret & BMG160_ANY_MOTION_BIT_X)
                iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ANGL_VEL,
                                                        0,
-                                                       IIO_MOD_X_OR_Y_OR_Z,
+                                                       IIO_MOD_X,
+                                                       IIO_EV_TYPE_ROC,
+                                                       dir),
+                                                       data->timestamp);
+       if (ret & BMG160_ANY_MOTION_BIT_Y)
+               iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ANGL_VEL,
+                                                       0,
+                                                       IIO_MOD_Y,
+                                                       IIO_EV_TYPE_ROC,
+                                                       dir),
+                                                       data->timestamp);
+       if (ret & BMG160_ANY_MOTION_BIT_Z)
+               iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ANGL_VEL,
+                                                       0,
+                                                       IIO_MOD_Z,
                                                        IIO_EV_TYPE_ROC,
                                                        dir),
                                                        data->timestamp);
@@ -1169,8 +1207,15 @@ static int bmg160_runtime_suspend(struct device *dev)
 {
        struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
        struct bmg160_data *data = iio_priv(indio_dev);
+       int ret;
+
+       ret = bmg160_set_mode(data, BMG160_MODE_SUSPEND);
+       if (ret < 0) {
+               dev_err(&data->client->dev, "set mode failed\n");
+               return -EAGAIN;
+       }
 
-       return bmg160_set_mode(data, BMG160_MODE_SUSPEND);
+       return 0;
 }
 
 static int bmg160_runtime_resume(struct device *dev)
index bc20348..8afa28e 100644 (file)
@@ -421,7 +421,7 @@ static int evdev_open(struct inode *inode, struct file *file)
 
  err_free_client:
        evdev_detach_client(evdev, client);
-       kfree(client);
+       kvfree(client);
        return error;
 }
 
index 2ed7905..fc55f0d 100644 (file)
@@ -1179,9 +1179,19 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
                }
 
                ep_irq_in = &intf->cur_altsetting->endpoint[1].desc;
-               usb_fill_bulk_urb(xpad->bulk_out, udev,
-                               usb_sndbulkpipe(udev, ep_irq_in->bEndpointAddress),
-                               xpad->bdata, XPAD_PKT_LEN, xpad_bulk_out, xpad);
+               if (usb_endpoint_is_bulk_out(ep_irq_in)) {
+                       usb_fill_bulk_urb(xpad->bulk_out, udev,
+                                         usb_sndbulkpipe(udev,
+                                                         ep_irq_in->bEndpointAddress),
+                                         xpad->bdata, XPAD_PKT_LEN,
+                                         xpad_bulk_out, xpad);
+               } else {
+                       usb_fill_int_urb(xpad->bulk_out, udev,
+                                        usb_sndintpipe(udev,
+                                                       ep_irq_in->bEndpointAddress),
+                                        xpad->bdata, XPAD_PKT_LEN,
+                                        xpad_bulk_out, xpad, 0);
+               }
 
                /*
                 * Submit the int URB immediately rather than waiting for open
index 432d363..c9c1c8c 100644 (file)
 #include <linux/ioport.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/gpio_keys.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
-#include <linux/of_gpio.h>
+#include <linux/property.h>
 
 #define DRV_NAME       "gpio-keys-polled"
 
@@ -51,15 +50,14 @@ static void gpio_keys_polled_check_state(struct input_dev *input,
        int state;
 
        if (bdata->can_sleep)
-               state = !!gpio_get_value_cansleep(button->gpio);
+               state = !!gpiod_get_value_cansleep(button->gpiod);
        else
-               state = !!gpio_get_value(button->gpio);
+               state = !!gpiod_get_value(button->gpiod);
 
        if (state != bdata->last_state) {
                unsigned int type = button->type ?: EV_KEY;
 
-               input_event(input, type, button->code,
-                           !!(state ^ button->active_low));
+               input_event(input, type, button->code, state);
                input_sync(input);
                bdata->count = 0;
                bdata->last_state = state;
@@ -102,21 +100,15 @@ static void gpio_keys_polled_close(struct input_polled_dev *dev)
                pdata->disable(bdev->dev);
 }
 
-#ifdef CONFIG_OF
 static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct device *dev)
 {
-       struct device_node *node, *pp;
        struct gpio_keys_platform_data *pdata;
        struct gpio_keys_button *button;
+       struct fwnode_handle *child;
        int error;
        int nbuttons;
-       int i;
-
-       node = dev->of_node;
-       if (!node)
-               return NULL;
 
-       nbuttons = of_get_child_count(node);
+       nbuttons = device_get_child_node_count(dev);
        if (nbuttons == 0)
                return NULL;
 
@@ -126,52 +118,44 @@ static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct
                return ERR_PTR(-ENOMEM);
 
        pdata->buttons = (struct gpio_keys_button *)(pdata + 1);
-       pdata->nbuttons = nbuttons;
 
-       pdata->rep = !!of_get_property(node, "autorepeat", NULL);
-       of_property_read_u32(node, "poll-interval", &pdata->poll_interval);
+       pdata->rep = device_property_present(dev, "autorepeat");
+       device_property_read_u32(dev, "poll-interval", &pdata->poll_interval);
 
-       i = 0;
-       for_each_child_of_node(node, pp) {
-               int gpio;
-               enum of_gpio_flags flags;
+       device_for_each_child_node(dev, child) {
+               struct gpio_desc *desc;
 
-               if (!of_find_property(pp, "gpios", NULL)) {
-                       pdata->nbuttons--;
-                       dev_warn(dev, "Found button without gpios\n");
-                       continue;
-               }
-
-               gpio = of_get_gpio_flags(pp, 0, &flags);
-               if (gpio < 0) {
-                       error = gpio;
+               desc = devm_get_gpiod_from_child(dev, child);
+               if (IS_ERR(desc)) {
+                       error = PTR_ERR(desc);
                        if (error != -EPROBE_DEFER)
                                dev_err(dev,
                                        "Failed to get gpio flags, error: %d\n",
                                        error);
+                       fwnode_handle_put(child);
                        return ERR_PTR(error);
                }
 
-               button = &pdata->buttons[i++];
-
-               button->gpio = gpio;
-               button->active_low = flags & OF_GPIO_ACTIVE_LOW;
+               button = &pdata->buttons[pdata->nbuttons++];
+               button->gpiod = desc;
 
-               if (of_property_read_u32(pp, "linux,code", &button->code)) {
-                       dev_err(dev, "Button without keycode: 0x%x\n",
-                               button->gpio);
+               if (fwnode_property_read_u32(child, "linux,code", &button->code)) {
+                       dev_err(dev, "Button without keycode: %d\n",
+                               pdata->nbuttons - 1);
+                       fwnode_handle_put(child);
                        return ERR_PTR(-EINVAL);
                }
 
-               button->desc = of_get_property(pp, "label", NULL);
+               fwnode_property_read_string(child, "label", &button->desc);
 
-               if (of_property_read_u32(pp, "linux,input-type", &button->type))
+               if (fwnode_property_read_u32(child, "linux,input-type",
+                                            &button->type))
                        button->type = EV_KEY;
 
-               button->wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL);
+               button->wakeup = fwnode_property_present(child, "gpio-key,wakeup");
 
-               if (of_property_read_u32(pp, "debounce-interval",
-                                        &button->debounce_interval))
+               if (fwnode_property_read_u32(child, "debounce-interval",
+                                            &button->debounce_interval))
                        button->debounce_interval = 5;
        }
 
@@ -187,15 +171,6 @@ static const struct of_device_id gpio_keys_polled_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, gpio_keys_polled_of_match);
 
-#else
-
-static inline struct gpio_keys_platform_data *
-gpio_keys_polled_get_devtree_pdata(struct device *dev)
-{
-       return NULL;
-}
-#endif
-
 static int gpio_keys_polled_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
@@ -259,7 +234,6 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
        for (i = 0; i < pdata->nbuttons; i++) {
                struct gpio_keys_button *button = &pdata->buttons[i];
                struct gpio_keys_button_data *bdata = &bdev->data[i];
-               unsigned int gpio = button->gpio;
                unsigned int type = button->type ?: EV_KEY;
 
                if (button->wakeup) {
@@ -267,15 +241,31 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
                        return -EINVAL;
                }
 
-               error = devm_gpio_request_one(&pdev->dev, gpio, GPIOF_IN,
-                                             button->desc ? : DRV_NAME);
-               if (error) {
-                       dev_err(dev, "unable to claim gpio %u, err=%d\n",
-                               gpio, error);
-                       return error;
+               /*
+                * Legacy GPIO number so request the GPIO here and
+                * convert it to descriptor.
+                */
+               if (!button->gpiod && gpio_is_valid(button->gpio)) {
+                       unsigned flags = 0;
+
+                       if (button->active_low)
+                               flags |= GPIOF_ACTIVE_LOW;
+
+                       error = devm_gpio_request_one(&pdev->dev, button->gpio,
+                                       flags, button->desc ? : DRV_NAME);
+                       if (error) {
+                               dev_err(dev, "unable to claim gpio %u, err=%d\n",
+                                       button->gpio, error);
+                               return error;
+                       }
+
+                       button->gpiod = gpio_to_desc(button->gpio);
                }
 
-               bdata->can_sleep = gpio_cansleep(gpio);
+               if (IS_ERR(button->gpiod))
+                       return PTR_ERR(button->gpiod);
+
+               bdata->can_sleep = gpiod_cansleep(button->gpiod);
                bdata->last_state = -1;
                bdata->threshold = DIV_ROUND_UP(button->debounce_interval,
                                                pdata->poll_interval);
@@ -308,7 +298,7 @@ static struct platform_driver gpio_keys_polled_driver = {
        .driver = {
                .name   = DRV_NAME,
                .owner  = THIS_MODULE,
-               .of_match_table = of_match_ptr(gpio_keys_polled_of_match),
+               .of_match_table = gpio_keys_polled_of_match,
        },
 };
 module_platform_driver(gpio_keys_polled_driver);
index 3fcb6b3..f2b9780 100644 (file)
@@ -428,14 +428,6 @@ static void elantech_report_trackpoint(struct psmouse *psmouse,
        int x, y;
        u32 t;
 
-       if (dev_WARN_ONCE(&psmouse->ps2dev.serio->dev,
-                         !tp_dev,
-                         psmouse_fmt("Unexpected trackpoint message\n"))) {
-               if (etd->debug == 1)
-                       elantech_packet_dump(psmouse);
-               return;
-       }
-
        t = get_unaligned_le32(&packet[0]);
 
        switch (t & ~7U) {
@@ -793,7 +785,7 @@ static int elantech_packet_check_v4(struct psmouse *psmouse)
        unsigned char packet_type = packet[3] & 0x03;
        bool sanity_check;
 
-       if ((packet[3] & 0x0f) == 0x06)
+       if (etd->tp_dev && (packet[3] & 0x0f) == 0x06)
                return PACKET_TRACKPOINT;
 
        /*
index 2a7a917..f947292 100644 (file)
@@ -143,6 +143,10 @@ static const struct min_max_quirk min_max_pnpid_table[] = {
                (const char * const []){"LEN2001", NULL},
                1024, 5022, 2508, 4832
        },
+       {
+               (const char * const []){"LEN2006", NULL},
+               1264, 5675, 1171, 4688
+       },
        { }
 };
 
index 6ae3cde..cc4f9d8 100644 (file)
@@ -217,8 +217,9 @@ struct irq_domain *__init aic_common_of_init(struct device_node *node,
        }
 
        ret = irq_alloc_domain_generic_chips(domain, 32, 1, name,
-                                            handle_level_irq, 0, 0,
-                                            IRQCHIP_SKIP_SET_WAKE);
+                                            handle_fasteoi_irq,
+                                            IRQ_NOREQUEST | IRQ_NOPROBE |
+                                            IRQ_NOAUTOEN, 0, 0);
        if (ret)
                goto err_domain_remove;
 
@@ -230,7 +231,6 @@ struct irq_domain *__init aic_common_of_init(struct device_node *node,
                gc->unused = 0;
                gc->wake_enabled = ~0;
                gc->chip_types[0].type = IRQ_TYPE_SENSE_MASK;
-               gc->chip_types[0].handler = handle_fasteoi_irq;
                gc->chip_types[0].chip.irq_eoi = irq_gc_eoi;
                gc->chip_types[0].chip.irq_set_wake = irq_gc_set_wake;
                gc->chip_types[0].chip.irq_shutdown = aic_common_shutdown;
index b9f4fb8..5fb38a2 100644 (file)
@@ -101,9 +101,9 @@ static int bcm7120_l2_intc_init_one(struct device_node *dn,
        int parent_irq;
 
        parent_irq = irq_of_parse_and_map(dn, irq);
-       if (parent_irq < 0) {
+       if (!parent_irq) {
                pr_err("failed to map interrupt %d\n", irq);
-               return parent_irq;
+               return -EINVAL;
        }
 
        data->irq_map_mask |= be32_to_cpup(map_mask + irq);
index c15c840..14691a4 100644 (file)
@@ -135,9 +135,9 @@ int __init brcmstb_l2_intc_of_init(struct device_node *np,
        __raw_writel(0xffffffff, data->base + CPU_CLEAR);
 
        data->parent_irq = irq_of_parse_and_map(np, 0);
-       if (data->parent_irq < 0) {
+       if (!data->parent_irq) {
                pr_err("failed to find parent interrupt\n");
-               ret = data->parent_irq;
+               ret = -EINVAL;
                goto out_unmap;
        }
 
index b4518c8..868e6fc 100644 (file)
  */
 #include <linux/err.h>
 #include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/kernel.h>
 #include <linux/leds.h>
 #include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_gpio.h>
-#include <linux/of_platform.h>
 #include <linux/platform_device.h>
+#include <linux/property.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
 
 struct gpio_led_data {
        struct led_classdev cdev;
-       unsigned gpio;
+       struct gpio_desc *gpiod;
        struct work_struct work;
        u8 new_level;
        u8 can_sleep;
-       u8 active_low;
        u8 blinking;
-       int (*platform_gpio_blink_set)(unsigned gpio, int state,
+       int (*platform_gpio_blink_set)(struct gpio_desc *desc, int state,
                        unsigned long *delay_on, unsigned long *delay_off);
 };
 
@@ -40,12 +38,11 @@ static void gpio_led_work(struct work_struct *work)
                container_of(work, struct gpio_led_data, work);
 
        if (led_dat->blinking) {
-               led_dat->platform_gpio_blink_set(led_dat->gpio,
-                                                led_dat->new_level,
-                                                NULL, NULL);
+               led_dat->platform_gpio_blink_set(led_dat->gpiod,
+                                       led_dat->new_level, NULL, NULL);
                led_dat->blinking = 0;
        } else
-               gpio_set_value_cansleep(led_dat->gpio, led_dat->new_level);
+               gpiod_set_value_cansleep(led_dat->gpiod, led_dat->new_level);
 }
 
 static void gpio_led_set(struct led_classdev *led_cdev,
@@ -60,9 +57,6 @@ static void gpio_led_set(struct led_classdev *led_cdev,
        else
                level = 1;
 
-       if (led_dat->active_low)
-               level = !level;
-
        /* Setting GPIOs with I2C/etc requires a task context, and we don't
         * seem to have a reliable way to know if we're already in one; so
         * let's just assume the worst.
@@ -72,11 +66,11 @@ static void gpio_led_set(struct led_classdev *led_cdev,
                schedule_work(&led_dat->work);
        } else {
                if (led_dat->blinking) {
-                       led_dat->platform_gpio_blink_set(led_dat->gpio, level,
+                       led_dat->platform_gpio_blink_set(led_dat->gpiod, level,
                                                         NULL, NULL);
                        led_dat->blinking = 0;
                } else
-                       gpio_set_value(led_dat->gpio, level);
+                       gpiod_set_value(led_dat->gpiod, level);
        }
 }
 
@@ -87,34 +81,49 @@ static int gpio_blink_set(struct led_classdev *led_cdev,
                container_of(led_cdev, struct gpio_led_data, cdev);
 
        led_dat->blinking = 1;
-       return led_dat->platform_gpio_blink_set(led_dat->gpio, GPIO_LED_BLINK,
+       return led_dat->platform_gpio_blink_set(led_dat->gpiod, GPIO_LED_BLINK,
                                                delay_on, delay_off);
 }
 
 static int create_gpio_led(const struct gpio_led *template,
        struct gpio_led_data *led_dat, struct device *parent,
-       int (*blink_set)(unsigned, int, unsigned long *, unsigned long *))
+       int (*blink_set)(struct gpio_desc *, int, unsigned long *,
+                        unsigned long *))
 {
        int ret, state;
 
-       led_dat->gpio = -1;
+       led_dat->gpiod = template->gpiod;
+       if (!led_dat->gpiod) {
+               /*
+                * This is the legacy code path for platform code that
+                * still uses GPIO numbers. Ultimately we would like to get
+                * rid of this block completely.
+                */
+               unsigned long flags = 0;
+
+               /* skip leds that aren't available */
+               if (!gpio_is_valid(template->gpio)) {
+                       dev_info(parent, "Skipping unavailable LED gpio %d (%s)\n",
+                                       template->gpio, template->name);
+                       return 0;
+               }
 
-       /* skip leds that aren't available */
-       if (!gpio_is_valid(template->gpio)) {
-               dev_info(parent, "Skipping unavailable LED gpio %d (%s)\n",
-                               template->gpio, template->name);
-               return 0;
-       }
+               if (template->active_low)
+                       flags |= GPIOF_ACTIVE_LOW;
 
-       ret = devm_gpio_request(parent, template->gpio, template->name);
-       if (ret < 0)
-               return ret;
+               ret = devm_gpio_request_one(parent, template->gpio, flags,
+                                           template->name);
+               if (ret < 0)
+                       return ret;
+
+               led_dat->gpiod = gpio_to_desc(template->gpio);
+               if (IS_ERR(led_dat->gpiod))
+                       return PTR_ERR(led_dat->gpiod);
+       }
 
        led_dat->cdev.name = template->name;
        led_dat->cdev.default_trigger = template->default_trigger;
-       led_dat->gpio = template->gpio;
-       led_dat->can_sleep = gpio_cansleep(template->gpio);
-       led_dat->active_low = template->active_low;
+       led_dat->can_sleep = gpiod_cansleep(led_dat->gpiod);
        led_dat->blinking = 0;
        if (blink_set) {
                led_dat->platform_gpio_blink_set = blink_set;
@@ -122,30 +131,24 @@ static int create_gpio_led(const struct gpio_led *template,
        }
        led_dat->cdev.brightness_set = gpio_led_set;
        if (template->default_state == LEDS_GPIO_DEFSTATE_KEEP)
-               state = !!gpio_get_value_cansleep(led_dat->gpio) ^ led_dat->active_low;
+               state = !!gpiod_get_value_cansleep(led_dat->gpiod);
        else
                state = (template->default_state == LEDS_GPIO_DEFSTATE_ON);
        led_dat->cdev.brightness = state ? LED_FULL : LED_OFF;
        if (!template->retain_state_suspended)
                led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
 
-       ret = gpio_direction_output(led_dat->gpio, led_dat->active_low ^ state);
+       ret = gpiod_direction_output(led_dat->gpiod, state);
        if (ret < 0)
                return ret;
 
        INIT_WORK(&led_dat->work, gpio_led_work);
 
-       ret = led_classdev_register(parent, &led_dat->cdev);
-       if (ret < 0)
-               return ret;
-
-       return 0;
+       return led_classdev_register(parent, &led_dat->cdev);
 }
 
 static void delete_gpio_led(struct gpio_led_data *led)
 {
-       if (!gpio_is_valid(led->gpio))
-               return;
        led_classdev_unregister(&led->cdev);
        cancel_work_sync(&led->work);
 }
@@ -161,40 +164,47 @@ static inline int sizeof_gpio_leds_priv(int num_leds)
                (sizeof(struct gpio_led_data) * num_leds);
 }
 
-/* Code to create from OpenFirmware platform devices */
-#ifdef CONFIG_OF_GPIO
-static struct gpio_leds_priv *gpio_leds_create_of(struct platform_device *pdev)
+static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev)
 {
-       struct device_node *np = pdev->dev.of_node, *child;
+       struct device *dev = &pdev->dev;
+       struct fwnode_handle *child;
        struct gpio_leds_priv *priv;
        int count, ret;
+       struct device_node *np;
 
-       /* count LEDs in this device, so we know how much to allocate */
-       count = of_get_available_child_count(np);
+       count = device_get_child_node_count(dev);
        if (!count)
                return ERR_PTR(-ENODEV);
 
-       for_each_available_child_of_node(np, child)
-               if (of_get_gpio(child, 0) == -EPROBE_DEFER)
-                       return ERR_PTR(-EPROBE_DEFER);
-
-       priv = devm_kzalloc(&pdev->dev, sizeof_gpio_leds_priv(count),
-                       GFP_KERNEL);
+       priv = devm_kzalloc(dev, sizeof_gpio_leds_priv(count), GFP_KERNEL);
        if (!priv)
                return ERR_PTR(-ENOMEM);
 
-       for_each_available_child_of_node(np, child) {
+       device_for_each_child_node(dev, child) {
                struct gpio_led led = {};
-               enum of_gpio_flags flags;
-               const char *state;
-
-               led.gpio = of_get_gpio_flags(child, 0, &flags);
-               led.active_low = flags & OF_GPIO_ACTIVE_LOW;
-               led.name = of_get_property(child, "label", NULL) ? : child->name;
-               led.default_trigger =
-                       of_get_property(child, "linux,default-trigger", NULL);
-               state = of_get_property(child, "default-state", NULL);
-               if (state) {
+               const char *state = NULL;
+
+               led.gpiod = devm_get_gpiod_from_child(dev, child);
+               if (IS_ERR(led.gpiod)) {
+                       fwnode_handle_put(child);
+                       goto err;
+               }
+
+               np = of_node(child);
+
+               if (fwnode_property_present(child, "label")) {
+                       fwnode_property_read_string(child, "label", &led.name);
+               } else {
+                       if (IS_ENABLED(CONFIG_OF) && !led.name && np)
+                               led.name = np->name;
+                       if (!led.name)
+                               return ERR_PTR(-EINVAL);
+               }
+               fwnode_property_read_string(child, "linux,default-trigger",
+                                           &led.default_trigger);
+
+               if (!fwnode_property_read_string(child, "linux,default_state",
+                                                &state)) {
                        if (!strcmp(state, "keep"))
                                led.default_state = LEDS_GPIO_DEFSTATE_KEEP;
                        else if (!strcmp(state, "on"))
@@ -203,13 +213,13 @@ static struct gpio_leds_priv *gpio_leds_create_of(struct platform_device *pdev)
                                led.default_state = LEDS_GPIO_DEFSTATE_OFF;
                }
 
-               if (of_get_property(child, "retain-state-suspended", NULL))
+               if (fwnode_property_present(child, "retain-state-suspended"))
                        led.retain_state_suspended = 1;
 
                ret = create_gpio_led(&led, &priv->leds[priv->num_leds++],
-                                     &pdev->dev, NULL);
+                                     dev, NULL);
                if (ret < 0) {
-                       of_node_put(child);
+                       fwnode_handle_put(child);
                        goto err;
                }
        }
@@ -228,12 +238,6 @@ static const struct of_device_id of_gpio_leds_match[] = {
 };
 
 MODULE_DEVICE_TABLE(of, of_gpio_leds_match);
-#else /* CONFIG_OF_GPIO */
-static struct gpio_leds_priv *gpio_leds_create_of(struct platform_device *pdev)
-{
-       return ERR_PTR(-ENODEV);
-}
-#endif /* CONFIG_OF_GPIO */
 
 static int gpio_led_probe(struct platform_device *pdev)
 {
@@ -261,7 +265,7 @@ static int gpio_led_probe(struct platform_device *pdev)
                        }
                }
        } else {
-               priv = gpio_leds_create_of(pdev);
+               priv = gpio_leds_create(pdev);
                if (IS_ERR(priv))
                        return PTR_ERR(priv);
        }
@@ -288,7 +292,7 @@ static struct platform_driver gpio_led_driver = {
        .driver         = {
                .name   = "leds-gpio",
                .owner  = THIS_MODULE,
-               .of_match_table = of_match_ptr(of_gpio_leds_match),
+               .of_match_table = of_gpio_leds_match,
        },
 };
 
index 932ed9b..b10aaed 100644 (file)
@@ -2190,7 +2190,7 @@ static int smiapp_set_selection(struct v4l2_subdev *subdev,
                ret = smiapp_set_compose(subdev, fh, sel);
                break;
        default:
-               BUG();
+               ret = -EINVAL;
        }
 
        mutex_unlock(&sensor->mutex);