]> Git Repo - J-linux.git/commitdiff
Merge tag 'drivers-5.17' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc
authorLinus Torvalds <[email protected]>
Mon, 10 Jan 2022 16:13:52 +0000 (08:13 -0800)
committerLinus Torvalds <[email protected]>
Mon, 10 Jan 2022 16:13:52 +0000 (08:13 -0800)
Pull ARM SoC driver updates from Arnd Bergmann:
 "There are cleanups and minor bugfixes across several SoC specific
  drivers, for Qualcomm, Samsung, NXP i.MX, AT91, Tegra, Keystone,
  Renesas, ZynqMP

  Noteworthy new features are:

   - The op-tee firmware driver gains support for asynchronous
     notifications from secure-world firmware.

   - Qualcomm platforms gain support for new SoC types in various
     drivers: power domain, cache controller, RPM sleep, soc-info

   - Samsung SoC drivers gain support for new SoCs in ChipID and PMU, as
     well as a new USIv2 driver that handles various types of serial
     communiction (uart, i2c, spi)

   - Renesas adds support for R-Car S4-8 (R8A779F0) in multiple drivers,
     as well as memory controller support for RZ/G2L (R9A07G044).

   - Apple M1 gains support for the PMGR power management driver"

* tag 'drivers-5.17' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (94 commits)
  soc: qcom: rpmh-rsc: Fix typo in a comment
  soc: qcom: socinfo: Add SM6350 and SM7225
  dt-bindings: arm: msm: Don't mark LLCC interrupt as required
  dt-bindings: firmware: scm: Add SM6350 compatible
  dt-bindings: arm: msm: Add LLCC for SM6350
  soc: qcom: rpmhpd: Sort power-domain definitions and lists
  soc: qcom: rpmhpd: Remove mx/cx relationship on sc7280
  soc: qcom: rpmhpd: Rename rpmhpd struct names
  soc: qcom: rpmhpd: sm8450: Add the missing .peer for sm8450_cx_ao
  soc: qcom: socinfo: add SM8450 ID
  soc: qcom: rpmhpd: Add SM8450 power domains
  dt-bindings: power: rpmpd: Add SM8450 to rpmpd binding
  soc: qcom: smem: Update max processor count
  dt-bindings: arm: qcom: Document SM8450 SoC and boards
  dt-bindings: firmware: scm: Add SM8450 compatible
  dt-bindings: arm: cpus: Add kryo780 compatible
  soc: qcom: rpmpd: Add support for sm6125
  dt-bindings: qcom-rpmpd: Add sm6125 power domains
  soc: qcom: aoss: constify static struct thermal_cooling_device_ops
  PM: AVS: qcom-cpr: Use div64_ul instead of do_div
  ...

1  2 
MAINTAINERS
drivers/mmc/host/sdhci-tegra.c
drivers/soc/imx/imx8m-blk-ctrl.c
drivers/soc/tegra/fuse/fuse-tegra.c
drivers/soc/tegra/fuse/fuse.h
drivers/tee/optee/core.c
drivers/tee/optee/ffa_abi.c
drivers/tee/optee/smc_abi.c
include/linux/tee_drv.h

diff --combined MAINTAINERS
index 2a737156f4c5029ee18ec7780244c87be935c021,e2d6a021126f97f577eef22ab594b77feeb240a0..ebd992e69c528237dd63ca0647de9e28b5d0ee01
  S:    Maintained
  F:    drivers/counter/microchip-tcb-capture.c
  
 +ARM/MILBEAUT ARCHITECTURE
 +M:    Taichi Sugaya <[email protected]>
 +M:    Takao Orito <[email protected]>
 +L:    [email protected] (moderated for non-subscribers)
 +S:    Maintained
 +F:    arch/arm/boot/dts/milbeaut*
 +F:    arch/arm/mach-milbeaut/
 +N:    milbeaut
 +
  ARM/MIOA701 MACHINE SUPPORT
  M:    Robert Jarzmik <[email protected]>
  L:    [email protected] (moderated for non-subscribers)
@@@ -2551,6 -2542,7 +2551,7 @@@ Q:      https://patchwork.kernel.org/project
  F:    Documentation/arm/samsung/
  F:    Documentation/devicetree/bindings/arm/samsung/
  F:    Documentation/devicetree/bindings/power/pd-samsung.yaml
+ F:    Documentation/devicetree/bindings/soc/samsung/
  F:    arch/arm/boot/dts/exynos*
  F:    arch/arm/boot/dts/s3c*
  F:    arch/arm/boot/dts/s5p*
@@@ -2738,11 -2730,10 +2739,11 @@@ S:   Maintaine
  F:    drivers/memory/*emif*
  
  ARM/TEXAS INSTRUMENT KEYSTONE ARCHITECTURE
 +M:    Nishanth Menon <[email protected]>
  M:    Santosh Shilimkar <[email protected]>
  L:    [email protected] (moderated for non-subscribers)
  S:    Maintained
 -T:    git git://git.kernel.org/pub/scm/linux/kernel/git/ssantosh/linux-keystone.git
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/ti/linux.git
  F:    arch/arm/boot/dts/keystone-*
  F:    arch/arm/mach-keystone/
  
@@@ -3066,7 -3057,7 +3067,7 @@@ F:      Documentation/devicetree/bindings/ph
  F:    drivers/phy/qualcomm/phy-ath79-usb.c
  
  ATHEROS ATH GENERIC UTILITIES
 -M:    Kalle Valo <kvalo@codeaurora.org>
 +M:    Kalle Valo <kvalo@kernel.org>
  L:    [email protected]
  S:    Supported
  F:    drivers/net/wireless/ath/*
@@@ -3081,7 -3072,7 +3082,7 @@@ W:      https://wireless.wiki.kernel.org/en/
  F:    drivers/net/wireless/ath/ath5k/
  
  ATHEROS ATH6KL WIRELESS DRIVER
 -M:    Kalle Valo <kvalo@codeaurora.org>
 +M:    Kalle Valo <kvalo@kernel.org>
  L:    [email protected]
  S:    Supported
  W:    https://wireless.wiki.kernel.org/en/users/Drivers/ath6kl
  S:    Supported
  F:    drivers/net/ethernet/broadcom/b44.*
  
 -BROADCOM B53 ETHERNET SWITCH DRIVER
 +BROADCOM B53/SF2 ETHERNET SWITCH DRIVER
  M:    Florian Fainelli <[email protected]>
  L:    [email protected]
  L:    [email protected] (subscribers-only)
  S:    Supported
  F:    Documentation/devicetree/bindings/net/dsa/brcm,b53.yaml
  F:    drivers/net/dsa/b53/*
 +F:    drivers/net/dsa/bcm_sf2*
  F:    include/linux/dsa/brcm.h
  F:    include/linux/platform_data/b53.h
  
@@@ -3636,7 -3626,6 +3637,7 @@@ F:      drivers/net/ethernet/broadcom/bcm490
  F:    drivers/net/ethernet/broadcom/unimac.h
  
  BROADCOM BCM5301X ARM ARCHITECTURE
 +M:    Florian Fainelli <[email protected]>
  M:    Hauke Mehrtens <[email protected]>
  M:    Rafał Miłecki <[email protected]>
  M:    [email protected]
@@@ -3648,7 -3637,6 +3649,7 @@@ F:      arch/arm/boot/dts/bcm953012
  F:    arch/arm/mach-bcm/bcm_5301x.c
  
  BROADCOM BCM53573 ARM ARCHITECTURE
 +M:    Florian Fainelli <[email protected]>
  M:    Rafał Miłecki <[email protected]>
  L:    [email protected]
  L:    [email protected] (moderated for non-subscribers)
@@@ -3771,8 -3759,7 +3772,8 @@@ S:      Supporte
  F:    drivers/net/wireless/broadcom/brcm80211/
  
  BROADCOM BRCMSTB GPIO DRIVER
 -M:    Gregory Fong <[email protected]>
 +M:    Doug Berger <[email protected]>
 +M:    Florian Fainelli <[email protected]>
  L:    [email protected]
  S:    Supported
  F:    Documentation/devicetree/bindings/gpio/brcm,brcmstb-gpio.txt
@@@ -9332,6 -9319,7 +9333,6 @@@ S:      Maintaine
  F:    drivers/iio/pressure/dps310.c
  
  INFINIBAND SUBSYSTEM
 -M:    Doug Ledford <[email protected]>
  M:    Jason Gunthorpe <[email protected]>
  L:    [email protected]
  S:    Supported
@@@ -10282,9 -10270,9 +10283,9 @@@ F:   lib/Kconfig.kcsa
  F:    scripts/Makefile.kcsan
  
  KDUMP
 -M:    Dave Young <[email protected]>
  M:    Baoquan He <[email protected]>
  R:    Vivek Goyal <[email protected]>
 +R:    Dave Young <[email protected]>
  L:    [email protected]
  S:    Maintained
  W:    http://lse.sourceforge.net/kdump/
@@@ -12182,8 -12170,8 +12183,8 @@@ F:   drivers/net/ethernet/mellanox/mlx5/c
  F:    include/linux/mlx5/mlx5_ifc_fpga.h
  
  MELLANOX ETHERNET SWITCH DRIVERS
 -M:    Jiri Pirko <[email protected]>
  M:    Ido Schimmel <[email protected]>
 +M:    Petr Machata <[email protected]>
  L:    [email protected]
  S:    Supported
  W:    http://www.mellanox.com
@@@ -13251,7 -13239,7 +13252,7 @@@ F:   include/uapi/linux/if_
  F:    include/uapi/linux/netdevice.h
  
  NETWORKING DRIVERS (WIRELESS)
 -M:    Kalle Valo <kvalo@codeaurora.org>
 +M:    Kalle Valo <kvalo@kernel.org>
  L:    [email protected]
  S:    Maintained
  Q:    http://patchwork.kernel.org/project/linux-wireless/list/
@@@ -14848,7 -14836,7 +14849,7 @@@ PCIE DRIVER FOR MEDIATE
  M:    Ryder Lee <[email protected]>
  M:    Jianjun Wang <[email protected]>
  L:    [email protected]
 -L:    [email protected]
 +L:    [email protected] (moderated for non-subscribers)
  S:    Supported
  F:    Documentation/devicetree/bindings/pci/mediatek*
  F:    drivers/pci/controller/*mediatek*
@@@ -15707,7 -15695,7 +15708,7 @@@ T:   git git://linuxtv.org/anttip/media_t
  F:    drivers/media/tuners/qt1010*
  
  QUALCOMM ATHEROS ATH10K WIRELESS DRIVER
 -M:    Kalle Valo <kvalo@codeaurora.org>
 +M:    Kalle Valo <kvalo@kernel.org>
  L:    [email protected]
  S:    Supported
  W:    https://wireless.wiki.kernel.org/en/users/Drivers/ath10k
@@@ -15715,7 -15703,7 +15716,7 @@@ T:   git git://git.kernel.org/pub/scm/lin
  F:    drivers/net/wireless/ath/ath10k/
  
  QUALCOMM ATHEROS ATH11K WIRELESS DRIVER
 -M:    Kalle Valo <kvalo@codeaurora.org>
 +M:    Kalle Valo <kvalo@kernel.org>
  L:    [email protected]
  S:    Supported
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
@@@ -15773,15 -15761,6 +15774,15 @@@ S: Maintaine
  F:    Documentation/devicetree/bindings/net/qcom,ethqos.txt
  F:    drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
  
 +QUALCOMM FASTRPC DRIVER
 +M:    Srinivas Kandagatla <[email protected]>
 +M:    Amol Maheshwari <[email protected]>
 +L:    [email protected]
 +S:    Maintained
 +F:    Documentation/devicetree/bindings/misc/qcom,fastrpc.txt
 +F:    drivers/misc/fastrpc.c
 +F:    include/uapi/misc/fastrpc.h
 +
  QUALCOMM GENERIC INTERFACE I2C DRIVER
  M:    Akash Asthana <[email protected]>
  M:    Mukesh Savaliya <[email protected]>
@@@ -15888,7 -15867,7 +15889,7 @@@ F:   Documentation/devicetree/bindings/me
  F:    drivers/media/platform/qcom/venus/
  
  QUALCOMM WCN36XX WIRELESS DRIVER
 -M:    Kalle Valo <kvalo@codeaurora.org>
 +M:    Kalle Valo <kvalo@kernel.org>
  L:    [email protected]
  S:    Supported
  W:    https://wireless.wiki.kernel.org/en/users/Drivers/wcn36xx
@@@ -15990,7 -15969,6 +15991,7 @@@ F:   arch/mips/generic/board-ranchu.
  
  RANDOM NUMBER DRIVER
  M:    "Theodore Ts'o" <[email protected]>
 +M:    Jason A. Donenfeld <[email protected]>
  S:    Maintained
  F:    drivers/char/random.c
  
@@@ -16513,12 -16491,6 +16514,12 @@@ T: git git://linuxtv.org/media_tree.gi
  F:    Documentation/devicetree/bindings/media/allwinner,sun8i-a83t-de2-rotate.yaml
  F:    drivers/media/platform/sunxi/sun8i-rotate/
  
 +RPMSG TTY DRIVER
 +M:    Arnaud Pouliquen <[email protected]>
 +L:    [email protected]
 +S:    Maintained
 +F:    drivers/tty/rpmsg_tty.c
 +
  RTL2830 MEDIA DRIVER
  M:    Antti Palosaari <[email protected]>
  L:    [email protected]
@@@ -16640,8 -16612,8 +16641,8 @@@ W:   http://www.ibm.com/developerworks/li
  F:    drivers/iommu/s390-iommu.c
  
  S390 IUCV NETWORK LAYER
 -M:    Julian Wiedmann <jwi@linux.ibm.com>
 -M:    Karsten Graul <kgraul@linux.ibm.com>
 +M:    Alexandra Winter <wintera@linux.ibm.com>
 +M:    Wenjia Zhang <wenjia@linux.ibm.com>
  L:    [email protected]
  L:    [email protected]
  S:    Supported
@@@ -16651,8 -16623,8 +16652,8 @@@ F:   include/net/iucv
  F:    net/iucv/
  
  S390 NETWORK DRIVERS
 -M:    Julian Wiedmann <jwi@linux.ibm.com>
 -M:    Karsten Graul <kgraul@linux.ibm.com>
 +M:    Alexandra Winter <wintera@linux.ibm.com>
 +M:    Wenjia Zhang <wenjia@linux.ibm.com>
  L:    [email protected]
  L:    [email protected]
  S:    Supported
@@@ -17426,7 -17398,7 +17427,7 @@@ F:   drivers/video/fbdev/sm712
  SILVACO I3C DUAL-ROLE MASTER
  M:    Miquel Raynal <[email protected]>
  M:    Conor Culhane <[email protected]>
 -L:    [email protected]
 +L:    [email protected] (moderated for non-subscribers)
  S:    Maintained
  F:    Documentation/devicetree/bindings/i3c/silvaco,i3c-master.yaml
  F:    drivers/i3c/master/svc-i3c-master.c
@@@ -18512,7 -18484,6 +18513,7 @@@ F:   include/uapi/linux/pkt_sched.
  F:    include/uapi/linux/tc_act/
  F:    include/uapi/linux/tc_ematch/
  F:    net/sched/
 +F:    tools/testing/selftests/tc-testing
  
  TC90522 MEDIA DRIVER
  M:    Akihiro Tsukada <[email protected]>
@@@ -19061,12 -19032,11 +19062,12 @@@ F:        drivers/mmc/host/tifm_sd.
  F:    include/linux/tifm.h
  
  TI KEYSTONE MULTICORE NAVIGATOR DRIVERS
 +M:    Nishanth Menon <[email protected]>
  M:    Santosh Shilimkar <[email protected]>
  L:    [email protected]
  L:    [email protected] (moderated for non-subscribers)
  S:    Maintained
 -T:    git git://git.kernel.org/pub/scm/linux/kernel/git/ssantosh/linux-keystone.git
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/ti/linux.git
  F:    drivers/soc/ti/*
  
  TI LM49xxx FAMILY ASoC CODEC DRIVERS
@@@ -21062,7 -21032,7 +21063,7 @@@ S:   Maintaine
  F:    arch/x86/kernel/cpu/zhaoxin.c
  
  ZONEFS FILESYSTEM
 -M:    Damien Le Moal <[email protected]>
 +M:    Damien Le Moal <damien.lemoal@opensource.wdc.com>
  M:    Naohiro Aota <[email protected]>
  R:    Johannes Thumshirn <[email protected]>
  L:    [email protected]
index 9762ffab2e236cdc90fe401b29490f715a1aa0b2,6435a75142a6f800d6bc871fb63654b28255e771..35ebba067e875034d425bdac1430b8e0a641ed83
@@@ -15,6 -15,8 +15,8 @@@
  #include <linux/of.h>
  #include <linux/of_device.h>
  #include <linux/pinctrl/consumer.h>
+ #include <linux/pm_opp.h>
+ #include <linux/pm_runtime.h>
  #include <linux/regulator/consumer.h>
  #include <linux/reset.h>
  #include <linux/mmc/card.h>
@@@ -24,6 -26,8 +26,8 @@@
  #include <linux/gpio/consumer.h>
  #include <linux/ktime.h>
  
+ #include <soc/tegra/common.h>
  #include "sdhci-pltfm.h"
  #include "cqhci.h"
  
@@@ -356,6 -360,23 +360,6 @@@ static void tegra_sdhci_set_tap(struct 
        }
  }
  
 -static void tegra_sdhci_hs400_enhanced_strobe(struct mmc_host *mmc,
 -                                            struct mmc_ios *ios)
 -{
 -      struct sdhci_host *host = mmc_priv(mmc);
 -      u32 val;
 -
 -      val = sdhci_readl(host, SDHCI_TEGRA_VENDOR_SYS_SW_CTRL);
 -
 -      if (ios->enhanced_strobe)
 -              val |= SDHCI_TEGRA_SYS_SW_CTRL_ENHANCED_STROBE;
 -      else
 -              val &= ~SDHCI_TEGRA_SYS_SW_CTRL_ENHANCED_STROBE;
 -
 -      sdhci_writel(host, val, SDHCI_TEGRA_VENDOR_SYS_SW_CTRL);
 -
 -}
 -
  static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)
  {
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@@ -743,7 -764,9 +747,9 @@@ static void tegra_sdhci_set_clock(struc
  {
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
        struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
+       struct device *dev = mmc_dev(host->mmc);
        unsigned long host_clk;
+       int err;
  
        if (!clock)
                return sdhci_set_clock(host, clock);
         * from clk_get_rate() is used.
         */
        host_clk = tegra_host->ddr_signaling ? clock * 2 : clock;
-       clk_set_rate(pltfm_host->clk, host_clk);
+       err = dev_pm_opp_set_rate(dev, host_clk);
+       if (err)
+               dev_err(dev, "failed to set clk rate to %luHz: %d\n",
+                       host_clk, err);
        tegra_host->curr_clk_rate = host_clk;
        if (tegra_host->ddr_signaling)
                host->max_clk = host_clk;
        }
  }
  
 +static void tegra_sdhci_hs400_enhanced_strobe(struct mmc_host *mmc,
 +                                            struct mmc_ios *ios)
 +{
 +      struct sdhci_host *host = mmc_priv(mmc);
 +      u32 val;
 +
 +      val = sdhci_readl(host, SDHCI_TEGRA_VENDOR_SYS_SW_CTRL);
 +
 +      if (ios->enhanced_strobe) {
 +              val |= SDHCI_TEGRA_SYS_SW_CTRL_ENHANCED_STROBE;
 +              /*
 +               * When CMD13 is sent from mmc_select_hs400es() after
 +               * switching to HS400ES mode, the bus is operating at
 +               * either MMC_HIGH_26_MAX_DTR or MMC_HIGH_52_MAX_DTR.
 +               * To meet Tegra SDHCI requirement at HS400ES mode, force SDHCI
 +               * interface clock to MMC_HS200_MAX_DTR (200 MHz) so that host
 +               * controller CAR clock and the interface clock are rate matched.
 +               */
 +              tegra_sdhci_set_clock(host, MMC_HS200_MAX_DTR);
 +      } else {
 +              val &= ~SDHCI_TEGRA_SYS_SW_CTRL_ENHANCED_STROBE;
 +      }
 +
 +      sdhci_writel(host, val, SDHCI_TEGRA_VENDOR_SYS_SW_CTRL);
 +}
 +
  static unsigned int tegra_sdhci_get_max_clock(struct sdhci_host *host)
  {
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@@ -1714,7 -1716,6 +1725,6 @@@ static int sdhci_tegra_probe(struct pla
                                   "failed to get clock\n");
                goto err_clk_get;
        }
-       clk_prepare_enable(clk);
        pltfm_host->clk = clk;
  
        tegra_host->rst = devm_reset_control_get_exclusive(&pdev->dev,
                goto err_rst_get;
        }
  
-       rc = reset_control_assert(tegra_host->rst);
+       rc = devm_tegra_core_dev_init_opp_table_common(&pdev->dev);
        if (rc)
                goto err_rst_get;
  
+       pm_runtime_enable(&pdev->dev);
+       rc = pm_runtime_resume_and_get(&pdev->dev);
+       if (rc)
+               goto err_pm_get;
+       rc = reset_control_assert(tegra_host->rst);
+       if (rc)
+               goto err_rst_assert;
        usleep_range(2000, 4000);
  
        rc = reset_control_deassert(tegra_host->rst);
        if (rc)
-               goto err_rst_get;
+               goto err_rst_assert;
  
        usleep_range(2000, 4000);
  
  
  err_add_host:
        reset_control_assert(tegra_host->rst);
+ err_rst_assert:
+       pm_runtime_put_sync_suspend(&pdev->dev);
+ err_pm_get:
+       pm_runtime_disable(&pdev->dev);
  err_rst_get:
-       clk_disable_unprepare(pltfm_host->clk);
  err_clk_get:
        clk_disable_unprepare(tegra_host->tmclk);
  err_power_req:
@@@ -1765,19 -1778,38 +1787,38 @@@ static int sdhci_tegra_remove(struct pl
  
        reset_control_assert(tegra_host->rst);
        usleep_range(2000, 4000);
-       clk_disable_unprepare(pltfm_host->clk);
-       clk_disable_unprepare(tegra_host->tmclk);
  
+       pm_runtime_put_sync_suspend(&pdev->dev);
+       pm_runtime_force_suspend(&pdev->dev);
+       clk_disable_unprepare(tegra_host->tmclk);
        sdhci_pltfm_free(pdev);
  
        return 0;
  }
  
- #ifdef CONFIG_PM_SLEEP
- static int __maybe_unused sdhci_tegra_suspend(struct device *dev)
+ static int __maybe_unused sdhci_tegra_runtime_suspend(struct device *dev)
  {
        struct sdhci_host *host = dev_get_drvdata(dev);
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+       clk_disable_unprepare(pltfm_host->clk);
+       return 0;
+ }
+ static int __maybe_unused sdhci_tegra_runtime_resume(struct device *dev)
+ {
+       struct sdhci_host *host = dev_get_drvdata(dev);
+       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+       return clk_prepare_enable(pltfm_host->clk);
+ }
+ #ifdef CONFIG_PM_SLEEP
+ static int sdhci_tegra_suspend(struct device *dev)
+ {
+       struct sdhci_host *host = dev_get_drvdata(dev);
        int ret;
  
        if (host->mmc->caps2 & MMC_CAP2_CQE) {
                return ret;
        }
  
-       clk_disable_unprepare(pltfm_host->clk);
+       ret = pm_runtime_force_suspend(dev);
+       if (ret) {
+               sdhci_resume_host(host);
+               cqhci_resume(host->mmc);
+               return ret;
+       }
        return 0;
  }
  
- static int __maybe_unused sdhci_tegra_resume(struct device *dev)
+ static int sdhci_tegra_resume(struct device *dev)
  {
        struct sdhci_host *host = dev_get_drvdata(dev);
-       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
        int ret;
  
-       ret = clk_prepare_enable(pltfm_host->clk);
+       ret = pm_runtime_force_resume(dev);
        if (ret)
                return ret;
  
  suspend_host:
        sdhci_suspend_host(host);
  disable_clk:
-       clk_disable_unprepare(pltfm_host->clk);
+       pm_runtime_force_suspend(dev);
        return ret;
  }
  #endif
  
- static SIMPLE_DEV_PM_OPS(sdhci_tegra_dev_pm_ops, sdhci_tegra_suspend,
-                        sdhci_tegra_resume);
+ static const struct dev_pm_ops sdhci_tegra_dev_pm_ops = {
+       SET_RUNTIME_PM_OPS(sdhci_tegra_runtime_suspend, sdhci_tegra_runtime_resume,
+                          NULL)
+       SET_SYSTEM_SLEEP_PM_OPS(sdhci_tegra_suspend, sdhci_tegra_resume)
+ };
  
  static struct platform_driver sdhci_tegra_driver = {
        .driver         = {
index c2f076b56e2471f1736baaf1042a6e6ffcd49e00,58a7f11e7e08bd92829518a76918cc5fc9326d68..511e74f0db8a919d3892b9e1cbad304ad982d567
  #include <linux/clk.h>
  
  #include <dt-bindings/power/imx8mm-power.h>
+ #include <dt-bindings/power/imx8mn-power.h>
  
  #define BLK_SFT_RSTN  0x0
  #define BLK_CLK_EN    0x4
 +#define BLK_MIPI_RESET_DIV    0x8 /* Mini/Nano DISPLAY_BLK_CTRL only */
  
  struct imx8m_blk_ctrl_domain;
  
@@@ -37,15 -37,6 +38,15 @@@ struct imx8m_blk_ctrl_domain_data 
        const char *gpc_name;
        u32 rst_mask;
        u32 clk_mask;
 +
 +      /*
 +       * i.MX8M Mini and Nano have a third DISPLAY_BLK_CTRL register
 +       * which is used to control the reset for the MIPI Phy.
 +       * Since it's only present in certain circumstances,
 +       * an if-statement should be used before setting and clearing this
 +       * register.
 +       */
 +      u32 mipi_phy_rst_mask;
  };
  
  #define DOMAIN_MAX_CLKS 3
@@@ -88,8 -79,6 +89,8 @@@ static int imx8m_blk_ctrl_power_on(stru
  
        /* put devices into reset */
        regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
 +      if (data->mipi_phy_rst_mask)
 +              regmap_clear_bits(bc->regmap, BLK_MIPI_RESET_DIV, data->mipi_phy_rst_mask);
  
        /* enable upstream and blk-ctrl clocks to allow reset to propagate */
        ret = clk_bulk_prepare_enable(data->num_clks, domain->clks);
  
        /* release reset */
        regmap_set_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
 +      if (data->mipi_phy_rst_mask)
 +              regmap_set_bits(bc->regmap, BLK_MIPI_RESET_DIV, data->mipi_phy_rst_mask);
  
        /* disable upstream clocks */
        clk_bulk_disable_unprepare(data->num_clks, domain->clks);
@@@ -134,9 -121,6 +135,9 @@@ static int imx8m_blk_ctrl_power_off(str
        struct imx8m_blk_ctrl *bc = domain->bc;
  
        /* put devices into reset and disable clocks */
 +      if (data->mipi_phy_rst_mask)
 +              regmap_clear_bits(bc->regmap, BLK_MIPI_RESET_DIV, data->mipi_phy_rst_mask);
 +
        regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
        regmap_clear_bits(bc->regmap, BLK_CLK_EN, data->clk_mask);
  
@@@ -497,7 -481,6 +498,7 @@@ static const struct imx8m_blk_ctrl_doma
                .gpc_name = "mipi-dsi",
                .rst_mask = BIT(5),
                .clk_mask = BIT(8) | BIT(9),
 +              .mipi_phy_rst_mask = BIT(17),
        },
        [IMX8MM_DISPBLK_PD_MIPI_CSI] = {
                .name = "dispblk-mipi-csi",
                .gpc_name = "mipi-csi",
                .rst_mask = BIT(3) | BIT(4),
                .clk_mask = BIT(10) | BIT(11),
 +              .mipi_phy_rst_mask = BIT(16),
        },
  };
  
@@@ -517,6 -499,77 +518,77 @@@ static const struct imx8m_blk_ctrl_dat
        .num_domains = ARRAY_SIZE(imx8mm_disp_blk_ctl_domain_data),
  };
  
+ static int imx8mn_disp_power_notifier(struct notifier_block *nb,
+                                     unsigned long action, void *data)
+ {
+       struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl,
+                                                power_nb);
+       if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF)
+               return NOTIFY_OK;
+       /* Enable bus clock and deassert bus reset */
+       regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(8));
+       regmap_set_bits(bc->regmap, BLK_SFT_RSTN, BIT(8));
+       /*
+        * On power up we have no software backchannel to the GPC to
+        * wait for the ADB handshake to happen, so we just delay for a
+        * bit. On power down the GPC driver waits for the handshake.
+        */
+       if (action == GENPD_NOTIFY_ON)
+               udelay(5);
+       return NOTIFY_OK;
+ }
+ static const struct imx8m_blk_ctrl_domain_data imx8mn_disp_blk_ctl_domain_data[] = {
+       [IMX8MN_DISPBLK_PD_MIPI_DSI] = {
+               .name = "dispblk-mipi-dsi",
+               .clk_names = (const char *[]){ "dsi-pclk", "dsi-ref", },
+               .num_clks = 2,
+               .gpc_name = "mipi-dsi",
+               .rst_mask = BIT(0) | BIT(1),
+               .clk_mask = BIT(0) | BIT(1),
+               .mipi_phy_rst_mask = BIT(17),
+       },
+       [IMX8MN_DISPBLK_PD_MIPI_CSI] = {
+               .name = "dispblk-mipi-csi",
+               .clk_names = (const char *[]){ "csi-aclk", "csi-pclk" },
+               .num_clks = 2,
+               .gpc_name = "mipi-csi",
+               .rst_mask = BIT(2) | BIT(3),
+               .clk_mask = BIT(2) | BIT(3),
+               .mipi_phy_rst_mask = BIT(16),
+       },
+       [IMX8MN_DISPBLK_PD_LCDIF] = {
+               .name = "dispblk-lcdif",
+               .clk_names = (const char *[]){ "lcdif-axi", "lcdif-apb", "lcdif-pix", },
+               .num_clks = 3,
+               .gpc_name = "lcdif",
+               .rst_mask = BIT(4) | BIT(5),
+               .clk_mask = BIT(4) | BIT(5),
+       },
+       [IMX8MN_DISPBLK_PD_ISI] = {
+               .name = "dispblk-isi",
+               .clk_names = (const char *[]){ "disp_axi", "disp_apb", "disp_axi_root",
+                                               "disp_apb_root"},
+               .num_clks = 4,
+               .gpc_name = "isi",
+               .rst_mask = BIT(6) | BIT(7),
+               .clk_mask = BIT(6) | BIT(7),
+       },
+ };
+ static const struct imx8m_blk_ctrl_data imx8mn_disp_blk_ctl_dev_data = {
+       .max_reg = 0x84,
+       .power_notifier_fn = imx8mn_disp_power_notifier,
+       .domains = imx8mn_disp_blk_ctl_domain_data,
+       .num_domains = ARRAY_SIZE(imx8mn_disp_blk_ctl_domain_data),
+ };
  static const struct of_device_id imx8m_blk_ctrl_of_match[] = {
        {
                .compatible = "fsl,imx8mm-vpu-blk-ctrl",
        }, {
                .compatible = "fsl,imx8mm-disp-blk-ctrl",
                .data = &imx8mm_disp_blk_ctl_dev_data
-       } ,{
+       }, {
+               .compatible = "fsl,imx8mn-disp-blk-ctrl",
+               .data = &imx8mn_disp_blk_ctl_dev_data
+       }, {
                /* Sentinel */
        }
  };
index e714ed3b61bc368a7100869253657bef32da25e7,fe4f935ce73ad4450f19252aada5539918566f72..913103ee54328713056bab7b17976ec0dec8950b
@@@ -14,6 -14,7 +14,7 @@@
  #include <linux/of_address.h>
  #include <linux/platform_device.h>
  #include <linux/pm_runtime.h>
+ #include <linux/reset.h>
  #include <linux/slab.h>
  #include <linux/sys_soc.h>
  
@@@ -181,6 -182,12 +182,12 @@@ static const struct nvmem_cell_info teg
        },
  };
  
+ static void tegra_fuse_restore(void *base)
+ {
+       fuse->clk = NULL;
+       fuse->base = base;
+ }
  static int tegra_fuse_probe(struct platform_device *pdev)
  {
        void __iomem *base = fuse->base;
        struct resource *res;
        int err;
  
+       err = devm_add_action(&pdev->dev, tegra_fuse_restore, base);
+       if (err)
+               return err;
        /* take over the memory region from the early initialization */
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        fuse->phys = res->start;
        fuse->base = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(fuse->base)) {
                err = PTR_ERR(fuse->base);
-               fuse->base = base;
                return err;
        }
  
                        dev_err(&pdev->dev, "failed to get FUSE clock: %ld",
                                PTR_ERR(fuse->clk));
  
-               fuse->base = base;
                return PTR_ERR(fuse->clk);
        }
  
        platform_set_drvdata(pdev, fuse);
        fuse->dev = &pdev->dev;
  
-       pm_runtime_enable(&pdev->dev);
+       err = devm_pm_runtime_enable(&pdev->dev);
+       if (err)
+               return err;
  
        if (fuse->soc->probe) {
                err = fuse->soc->probe(fuse);
                if (err < 0)
-                       goto restore;
+                       return err;
        }
  
        memset(&nvmem, 0, sizeof(nvmem));
                err = PTR_ERR(fuse->nvmem);
                dev_err(&pdev->dev, "failed to register NVMEM device: %d\n",
                        err);
-               goto restore;
+               return err;
+       }
+       fuse->rst = devm_reset_control_get_optional(&pdev->dev, "fuse");
+       if (IS_ERR(fuse->rst)) {
+               err = PTR_ERR(fuse->rst);
+               dev_err(&pdev->dev, "failed to get FUSE reset: %pe\n",
+                       fuse->rst);
+               return err;
+       }
+       /*
+        * FUSE clock is enabled at a boot time, hence this resume/suspend
+        * disables the clock besides the h/w resetting.
+        */
+       err = pm_runtime_resume_and_get(&pdev->dev);
+       if (err)
+               return err;
+       err = reset_control_reset(fuse->rst);
+       pm_runtime_put(&pdev->dev);
+       if (err < 0) {
+               dev_err(&pdev->dev, "failed to reset FUSE: %d\n", err);
+               return err;
        }
  
        /* release the early I/O memory mapping */
        iounmap(base);
  
        return 0;
- restore:
-       fuse->clk = NULL;
-       fuse->base = base;
-       pm_runtime_disable(&pdev->dev);
-       return err;
  }
  
  static int __maybe_unused tegra_fuse_runtime_resume(struct device *dev)
@@@ -320,7 -349,7 +349,7 @@@ static struct platform_driver tegra_fus
  };
  builtin_platform_driver(tegra_fuse_driver);
  
 -bool __init tegra_fuse_read_spare(unsigned int spare)
 +u32 __init tegra_fuse_read_spare(unsigned int spare)
  {
        unsigned int offset = fuse->soc->info->spare + spare * 4;
  
index ecff0c08e9595ace7f69deb0d99183d4ba0a6235,1b719d85bd045f3f8616c9fee981d16ea7e9f4a5..2bb1f9d6a6e6d3489193fb6b3de59c1f4c73987e
@@@ -43,6 -43,7 +43,7 @@@ struct tegra_fuse 
        void __iomem *base;
        phys_addr_t phys;
        struct clk *clk;
+       struct reset_control *rst;
  
        u32 (*read_early)(struct tegra_fuse *fuse, unsigned int offset);
        u32 (*read)(struct tegra_fuse *fuse, unsigned int offset);
@@@ -65,7 -66,7 +66,7 @@@
  void tegra_init_revision(void);
  void tegra_init_apbmisc(void);
  
 -bool __init tegra_fuse_read_spare(unsigned int spare);
 +u32 __init tegra_fuse_read_spare(unsigned int spare);
  u32 __init tegra_fuse_read_early(unsigned int offset);
  
  u8 tegra_get_major_rev(void);
diff --combined drivers/tee/optee/core.c
index 2a66a5203d2fad30b8943d0f5ade421ec76dbc7f,ba7300ca9ddf996a3da7984c499009291a74b2e2..1ca320885fad77ad9cbc3d3b4ac1cffe652d6fd4
@@@ -48,8 -48,10 +48,8 @@@ int optee_pool_op_alloc_helper(struct t
                        goto err;
                }
  
 -              for (i = 0; i < nr_pages; i++) {
 -                      pages[i] = page;
 -                      page++;
 -              }
 +              for (i = 0; i < nr_pages; i++)
 +                      pages[i] = page + i;
  
                shm->flags |= TEE_SHM_REGISTER;
                rc = shm_register(shm->ctx, shm, pages, nr_pages,
@@@ -157,6 -159,7 +157,7 @@@ void optee_remove_common(struct optee *
        /* Unregister OP-TEE specific client devices on TEE bus */
        optee_unregister_devices();
  
+       optee_notif_uninit(optee);
        /*
         * The two devices have to be unregistered before we can free the
         * other resources.
        tee_device_unregister(optee->teedev);
  
        tee_shm_pool_free(optee->pool);
-       optee_wait_queue_exit(&optee->wait_queue);
        optee_supp_uninit(&optee->supp);
        mutex_destroy(&optee->call_queue.mutex);
  }
index d8c8683863aa06bb9bb7edc83ea8e2cae2ecd5ee,3577781e5df77ccaec9921d360dc2d804dfffb1a..20a1b1a3d96527bffa67a6832fab1d09aa6d40cd
@@@ -810,9 -810,10 +810,9 @@@ static int optee_ffa_probe(struct ffa_d
                return -EINVAL;
  
        optee = kzalloc(sizeof(*optee), GFP_KERNEL);
 -      if (!optee) {
 -              rc = -ENOMEM;
 -              goto err;
 -      }
 +      if (!optee)
 +              return -ENOMEM;
 +
        optee->pool = optee_ffa_config_dyn_shm();
        if (IS_ERR(optee->pool)) {
                rc = PTR_ERR(optee->pool);
        mutex_init(&optee->ffa.mutex);
        mutex_init(&optee->call_queue.mutex);
        INIT_LIST_HEAD(&optee->call_queue.waiters);
-       optee_wait_queue_init(&optee->wait_queue);
        optee_supp_init(&optee->supp);
        ffa_dev_set_drvdata(ffa_dev, optee);
+       rc = optee_notif_init(optee, OPTEE_DEFAULT_MAX_NOTIF_VALUE);
+       if (rc) {
+               optee_ffa_remove(ffa_dev);
+               return rc;
+       }
  
        rc = optee_enumerate_devices(PTA_CMD_GET_DEVICES);
        if (rc) {
index cf2e3293567d92e7ab69af5e33e400f057607061,d7c8235c1c42036922b7fe3f30c38d97b9489680..449d6a72d289b3ec126d29d6bc833138660d5eb6
@@@ -8,13 -8,16 +8,16 @@@
  
  #include <linux/arm-smccc.h>
  #include <linux/errno.h>
+ #include <linux/interrupt.h>
  #include <linux/io.h>
- #include <linux/sched.h>
+ #include <linux/irqdomain.h>
  #include <linux/mm.h>
  #include <linux/module.h>
  #include <linux/of.h>
+ #include <linux/of_irq.h>
  #include <linux/of_platform.h>
  #include <linux/platform_device.h>
+ #include <linux/sched.h>
  #include <linux/slab.h>
  #include <linux/string.h>
  #include <linux/tee_drv.h>
@@@ -23,7 -26,6 +26,7 @@@
  #include "optee_private.h"
  #include "optee_smc.h"
  #include "optee_rpc_cmd.h"
 +#include <linux/kmemleak.h>
  #define CREATE_TRACE_POINTS
  #include "optee_trace.h"
  
@@@ -35,7 -37,8 +38,8 @@@
   * 2. Low level support functions to register shared memory in secure world
   * 3. Dynamic shared memory pool based on alloc_pages()
   * 4. Do a normal scheduled call into secure world
-  * 5. Driver initialization.
+  * 5. Asynchronous notification
+  * 6. Driver initialization.
   */
  
  #define OPTEE_SHM_NUM_PRIV_PAGES      CONFIG_OPTEE_SHM_NUM_PRIV_PAGES
@@@ -784,7 -787,6 +788,7 @@@ static void optee_handle_rpc(struct tee
                        param->a4 = 0;
                        param->a5 = 0;
                }
 +              kmemleak_not_leak(shm);
                break;
        case OPTEE_SMC_RPC_FUNC_FREE:
                shm = reg_pair_to_ptr(param->a1, param->a2);
@@@ -877,10 -879,137 +881,137 @@@ static int optee_smc_do_call_with_arg(s
        return rc;
  }
  
+ static int simple_call_with_arg(struct tee_context *ctx, u32 cmd)
+ {
+       struct optee_msg_arg *msg_arg;
+       struct tee_shm *shm;
+       shm = optee_get_msg_arg(ctx, 0, &msg_arg);
+       if (IS_ERR(shm))
+               return PTR_ERR(shm);
+       msg_arg->cmd = cmd;
+       optee_smc_do_call_with_arg(ctx, shm);
+       tee_shm_free(shm);
+       return 0;
+ }
+ static int optee_smc_do_bottom_half(struct tee_context *ctx)
+ {
+       return simple_call_with_arg(ctx, OPTEE_MSG_CMD_DO_BOTTOM_HALF);
+ }
+ static int optee_smc_stop_async_notif(struct tee_context *ctx)
+ {
+       return simple_call_with_arg(ctx, OPTEE_MSG_CMD_STOP_ASYNC_NOTIF);
+ }
  /*
-  * 5. Driver initialization
+  * 5. Asynchronous notification
+  */
+ static u32 get_async_notif_value(optee_invoke_fn *invoke_fn, bool *value_valid,
+                                bool *value_pending)
+ {
+       struct arm_smccc_res res;
+       invoke_fn(OPTEE_SMC_GET_ASYNC_NOTIF_VALUE, 0, 0, 0, 0, 0, 0, 0, &res);
+       if (res.a0)
+               return 0;
+       *value_valid = (res.a2 & OPTEE_SMC_ASYNC_NOTIF_VALUE_VALID);
+       *value_pending = (res.a2 & OPTEE_SMC_ASYNC_NOTIF_VALUE_PENDING);
+       return res.a1;
+ }
+ static irqreturn_t notif_irq_handler(int irq, void *dev_id)
+ {
+       struct optee *optee = dev_id;
+       bool do_bottom_half = false;
+       bool value_valid;
+       bool value_pending;
+       u32 value;
+       do {
+               value = get_async_notif_value(optee->smc.invoke_fn,
+                                             &value_valid, &value_pending);
+               if (!value_valid)
+                       break;
+               if (value == OPTEE_SMC_ASYNC_NOTIF_VALUE_DO_BOTTOM_HALF)
+                       do_bottom_half = true;
+               else
+                       optee_notif_send(optee, value);
+       } while (value_pending);
+       if (do_bottom_half)
+               return IRQ_WAKE_THREAD;
+       return IRQ_HANDLED;
+ }
+ static irqreturn_t notif_irq_thread_fn(int irq, void *dev_id)
+ {
+       struct optee *optee = dev_id;
+       optee_smc_do_bottom_half(optee->notif.ctx);
+       return IRQ_HANDLED;
+ }
+ static int optee_smc_notif_init_irq(struct optee *optee, u_int irq)
+ {
+       struct tee_context *ctx;
+       int rc;
+       ctx = teedev_open(optee->teedev);
+       if (IS_ERR(ctx))
+               return PTR_ERR(ctx);
+       optee->notif.ctx = ctx;
+       rc = request_threaded_irq(irq, notif_irq_handler,
+                                 notif_irq_thread_fn,
+                                 0, "optee_notification", optee);
+       if (rc)
+               goto err_close_ctx;
+       optee->smc.notif_irq = irq;
+       return 0;
+ err_close_ctx:
+       teedev_close_context(optee->notif.ctx);
+       optee->notif.ctx = NULL;
+       return rc;
+ }
+ static void optee_smc_notif_uninit_irq(struct optee *optee)
+ {
+       if (optee->notif.ctx) {
+               optee_smc_stop_async_notif(optee->notif.ctx);
+               if (optee->smc.notif_irq) {
+                       free_irq(optee->smc.notif_irq, optee);
+                       irq_dispose_mapping(optee->smc.notif_irq);
+               }
+               /*
+                * The thread normally working with optee->notif.ctx was
+                * stopped with free_irq() above.
+                *
+                * Note we're not using teedev_close_context() or
+                * tee_client_close_context() since we have already called
+                * tee_device_put() while initializing to avoid a circular
+                * reference counting.
+                */
+               teedev_close_context(optee->notif.ctx);
+       }
+ }
+ /*
+  * 6. Driver initialization
   *
-  * During driver inititialization is secure world probed to find out which
+  * During driver initialization is secure world probed to find out which
   * features it supports so the driver can be initialized with a matching
   * configuration. This involves for instance support for dynamic shared
   * memory instead of a static memory carvout.
@@@ -952,6 -1081,17 +1083,17 @@@ static const struct optee_ops optee_op
        .from_msg_param = optee_from_msg_param,
  };
  
+ static int enable_async_notif(optee_invoke_fn *invoke_fn)
+ {
+       struct arm_smccc_res res;
+       invoke_fn(OPTEE_SMC_ENABLE_ASYNC_NOTIF, 0, 0, 0, 0, 0, 0, 0, &res);
+       if (res.a0)
+               return -EINVAL;
+       return 0;
+ }
  static bool optee_msg_api_uid_is_optee_api(optee_invoke_fn *invoke_fn)
  {
        struct arm_smccc_res res;
@@@ -1001,7 -1141,7 +1143,7 @@@ static bool optee_msg_api_revision_is_c
  }
  
  static bool optee_msg_exchange_capabilities(optee_invoke_fn *invoke_fn,
-                                           u32 *sec_caps)
+                                           u32 *sec_caps, u32 *max_notif_value)
  {
        union {
                struct arm_smccc_res smccc;
                return false;
  
        *sec_caps = res.result.capabilities;
+       if (*sec_caps & OPTEE_SMC_SEC_CAP_ASYNC_NOTIF)
+               *max_notif_value = res.result.max_notif_value;
+       else
+               *max_notif_value = OPTEE_DEFAULT_MAX_NOTIF_VALUE;
        return true;
  }
  
@@@ -1188,6 -1333,8 +1335,8 @@@ static int optee_smc_remove(struct plat
         */
        optee_disable_shm_cache(optee);
  
+       optee_smc_notif_uninit_irq(optee);
        optee_remove_common(optee);
  
        if (optee->smc.memremaped_shm)
@@@ -1217,6 -1364,7 +1366,7 @@@ static int optee_probe(struct platform_
        struct optee *optee = NULL;
        void *memremaped_shm = NULL;
        struct tee_device *teedev;
+       u32 max_notif_value;
        u32 sec_caps;
        int rc;
  
                return -EINVAL;
        }
  
-       if (!optee_msg_exchange_capabilities(invoke_fn, &sec_caps)) {
+       if (!optee_msg_exchange_capabilities(invoke_fn, &sec_caps,
+                                            &max_notif_value)) {
                pr_warn("capabilities mismatch\n");
                return -EINVAL;
        }
        optee = kzalloc(sizeof(*optee), GFP_KERNEL);
        if (!optee) {
                rc = -ENOMEM;
-               goto err;
+               goto err_free_pool;
        }
  
        optee->ops = &optee_ops;
        teedev = tee_device_alloc(&optee_clnt_desc, NULL, pool, optee);
        if (IS_ERR(teedev)) {
                rc = PTR_ERR(teedev);
-               goto err;
+               goto err_free_optee;
        }
        optee->teedev = teedev;
  
        teedev = tee_device_alloc(&optee_supp_desc, NULL, pool, optee);
        if (IS_ERR(teedev)) {
                rc = PTR_ERR(teedev);
-               goto err;
+               goto err_unreg_teedev;
        }
        optee->supp_teedev = teedev;
  
        rc = tee_device_register(optee->teedev);
        if (rc)
-               goto err;
+               goto err_unreg_supp_teedev;
  
        rc = tee_device_register(optee->supp_teedev);
        if (rc)
-               goto err;
+               goto err_unreg_supp_teedev;
  
        mutex_init(&optee->call_queue.mutex);
        INIT_LIST_HEAD(&optee->call_queue.waiters);
-       optee_wait_queue_init(&optee->wait_queue);
        optee_supp_init(&optee->supp);
        optee->smc.memremaped_shm = memremaped_shm;
        optee->pool = pool;
  
+       platform_set_drvdata(pdev, optee);
+       rc = optee_notif_init(optee, max_notif_value);
+       if (rc)
+               goto err_supp_uninit;
+       if (sec_caps & OPTEE_SMC_SEC_CAP_ASYNC_NOTIF) {
+               unsigned int irq;
+               rc = platform_get_irq(pdev, 0);
+               if (rc < 0) {
+                       pr_err("platform_get_irq: ret %d\n", rc);
+                       goto err_notif_uninit;
+               }
+               irq = rc;
+               rc = optee_smc_notif_init_irq(optee, irq);
+               if (rc) {
+                       irq_dispose_mapping(irq);
+                       goto err_notif_uninit;
+               }
+               enable_async_notif(optee->smc.invoke_fn);
+               pr_info("Asynchronous notifications enabled\n");
+       }
        /*
         * Ensure that there are no pre-existing shm objects before enabling
         * the shm cache so that there's no chance of receiving an invalid
        if (optee->smc.sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM)
                pr_info("dynamic shared memory is enabled\n");
  
-       platform_set_drvdata(pdev, optee);
        rc = optee_enumerate_devices(PTA_CMD_GET_DEVICES);
-       if (rc) {
-               optee_smc_remove(pdev);
-               return rc;
-       }
+       if (rc)
+               goto err_disable_shm_cache;
  
        pr_info("initialized driver\n");
        return 0;
- err:
-       if (optee) {
-               /*
-                * tee_device_unregister() is safe to call even if the
-                * devices hasn't been registered with
-                * tee_device_register() yet.
-                */
-               tee_device_unregister(optee->supp_teedev);
-               tee_device_unregister(optee->teedev);
-               kfree(optee);
-       }
-       if (pool)
-               tee_shm_pool_free(pool);
+ err_disable_shm_cache:
+       optee_disable_shm_cache(optee);
+       optee_smc_notif_uninit_irq(optee);
+       optee_unregister_devices();
+ err_notif_uninit:
+       optee_notif_uninit(optee);
+ err_supp_uninit:
+       optee_supp_uninit(&optee->supp);
+       mutex_destroy(&optee->call_queue.mutex);
+ err_unreg_supp_teedev:
+       tee_device_unregister(optee->supp_teedev);
+ err_unreg_teedev:
+       tee_device_unregister(optee->teedev);
+ err_free_optee:
+       kfree(optee);
+ err_free_pool:
+       tee_shm_pool_free(pool);
        if (memremaped_shm)
                memunmap(memremaped_shm);
        return rc;
diff --combined include/linux/tee_drv.h
index cf5999626e28d9df3d5f6508f84550995590f7eb,468a7d83dc6c20ee92feff39cf62b18d0ad4c34d..5e1533ee3785bcc02fc3cb6afbe96b2d3c4ab008
@@@ -195,7 -195,7 +195,7 @@@ int tee_session_calc_client_uuid(uuid_
   * @offset:   offset of buffer in user space
   * @pages:    locked pages from userspace
   * @num_pages:        number of locked pages
 - * @dmabuf:   dmabuf used to for exporting to user space
 + * @refcount: reference counter
   * @flags:    defined by TEE_SHM_* in tee_drv.h
   * @id:               unique id of a shared memory object on this device, shared
   *            with user space
@@@ -214,7 -214,7 +214,7 @@@ struct tee_shm 
        unsigned int offset;
        struct page **pages;
        size_t num_pages;
 -      struct dma_buf *dmabuf;
 +      refcount_t refcount;
        u32 flags;
        int id;
        u64 sec_world_id;
@@@ -587,4 -587,18 +587,18 @@@ struct tee_client_driver 
  #define to_tee_client_driver(d) \
                container_of(d, struct tee_client_driver, driver)
  
+ /**
+  * teedev_open() - Open a struct tee_device
+  * @teedev:   Device to open
+  *
+  * @return a pointer to struct tee_context on success or an ERR_PTR on failure.
+  */
+ struct tee_context *teedev_open(struct tee_device *teedev);
+ /**
+  * teedev_close_context() - closes a struct tee_context
+  * @ctx:      The struct tee_context to close
+  */
+ void teedev_close_context(struct tee_context *ctx);
  #endif /*__TEE_DRV_H*/
This page took 0.158354 seconds and 4 git commands to generate.