From: Linus Torvalds Date: Mon, 10 Jan 2022 16:13:52 +0000 (-0800) Subject: Merge tag 'drivers-5.17' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc X-Git-Url: https://repo.jachan.dev/J-linux.git/commitdiff_plain/e85195d5bf8979f6db3f12cf8f1294887bf6b037?hp=-c Merge tag 'drivers-5.17' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc 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 ... --- e85195d5bf8979f6db3f12cf8f1294887bf6b037 diff --combined MAINTAINERS index 2a737156f4c5,e2d6a021126f..ebd992e69c52 --- a/MAINTAINERS +++ b/MAINTAINERS @@@ -2263,15 -2263,6 +2263,15 @@@ L: linux-iio@vger.kernel.or S: Maintained F: drivers/counter/microchip-tcb-capture.c +ARM/MILBEAUT ARCHITECTURE +M: Taichi Sugaya +M: Takao Orito +L: linux-arm-kernel@lists.infradead.org (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 L: linux-arm-kernel@lists.infradead.org (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 M: Santosh Shilimkar L: linux-arm-kernel@lists.infradead.org (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 +M: Kalle Valo L: linux-wireless@vger.kernel.org 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 +M: Kalle Valo L: linux-wireless@vger.kernel.org S: Supported W: https://wireless.wiki.kernel.org/en/users/Drivers/ath6kl @@@ -3580,14 -3571,13 +3581,14 @@@ L: netdev@vger.kernel.or S: Supported F: drivers/net/ethernet/broadcom/b44.* -BROADCOM B53 ETHERNET SWITCH DRIVER +BROADCOM B53/SF2 ETHERNET SWITCH DRIVER M: Florian Fainelli L: netdev@vger.kernel.org L: openwrt-devel@lists.openwrt.org (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 M: Hauke Mehrtens M: Rafał Miłecki M: bcm-kernel-feedback-list@broadcom.com @@@ -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 M: Rafał Miłecki L: bcm-kernel-feedback-list@broadcom.com L: linux-arm-kernel@lists.infradead.org (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 +M: Doug Berger +M: Florian Fainelli L: bcm-kernel-feedback-list@broadcom.com 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 M: Jason Gunthorpe L: linux-rdma@vger.kernel.org S: Supported @@@ -10282,9 -10270,9 +10283,9 @@@ F: lib/Kconfig.kcsa F: scripts/Makefile.kcsan KDUMP -M: Dave Young M: Baoquan He R: Vivek Goyal +R: Dave Young L: kexec@lists.infradead.org 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 M: Ido Schimmel +M: Petr Machata L: netdev@vger.kernel.org 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 +M: Kalle Valo L: linux-wireless@vger.kernel.org S: Maintained Q: http://patchwork.kernel.org/project/linux-wireless/list/ @@@ -14848,7 -14836,7 +14849,7 @@@ PCIE DRIVER FOR MEDIATE M: Ryder Lee M: Jianjun Wang L: linux-pci@vger.kernel.org -L: linux-mediatek@lists.infradead.org +L: linux-mediatek@lists.infradead.org (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 +M: Kalle Valo L: ath10k@lists.infradead.org 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 +M: Kalle Valo L: ath11k@lists.infradead.org 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 +M: Amol Maheshwari +L: linux-arm-msm@vger.kernel.org +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 M: Mukesh Savaliya @@@ -15888,7 -15867,7 +15889,7 @@@ F: Documentation/devicetree/bindings/me F: drivers/media/platform/qcom/venus/ QUALCOMM WCN36XX WIRELESS DRIVER -M: Kalle Valo +M: Kalle Valo L: wcn36xx@lists.infradead.org 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" +M: Jason A. Donenfeld 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 +L: linux-remoteproc@vger.kernel.org +S: Maintained +F: drivers/tty/rpmsg_tty.c + RTL2830 MEDIA DRIVER M: Antti Palosaari L: linux-media@vger.kernel.org @@@ -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 -M: Karsten Graul +M: Alexandra Winter +M: Wenjia Zhang L: linux-s390@vger.kernel.org L: netdev@vger.kernel.org S: Supported @@@ -16651,8 -16623,8 +16652,8 @@@ F: include/net/iucv F: net/iucv/ S390 NETWORK DRIVERS -M: Julian Wiedmann -M: Karsten Graul +M: Alexandra Winter +M: Wenjia Zhang L: linux-s390@vger.kernel.org L: netdev@vger.kernel.org S: Supported @@@ -17426,7 -17398,7 +17427,7 @@@ F: drivers/video/fbdev/sm712 SILVACO I3C DUAL-ROLE MASTER M: Miquel Raynal M: Conor Culhane -L: linux-i3c@lists.infradead.org +L: linux-i3c@lists.infradead.org (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 @@@ -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 M: Santosh Shilimkar L: linux-kernel@vger.kernel.org L: linux-arm-kernel@lists.infradead.org (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 +M: Damien Le Moal M: Naohiro Aota R: Johannes Thumshirn L: linux-fsdevel@vger.kernel.org diff --combined drivers/mmc/host/sdhci-tegra.c index 9762ffab2e23,6435a75142a6..35ebba067e87 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c @@@ -15,6 -15,8 +15,8 @@@ #include #include #include + #include + #include #include #include #include @@@ -24,6 -26,8 +26,8 @@@ #include #include + #include + #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); @@@ -761,7 -784,12 +767,12 @@@ * 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; @@@ -776,32 -804,6 +787,32 @@@ } } +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, @@@ -1725,15 -1726,24 +1735,24 @@@ 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); @@@ -1745,8 -1755,11 +1764,11 @@@ 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) { @@@ -1792,17 -1824,22 +1833,22 @@@ 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; @@@ -1821,13 -1858,16 +1867,16 @@@ 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 = { diff --combined drivers/soc/imx/imx8m-blk-ctrl.c index c2f076b56e24,58a7f11e7e08..511e74f0db8a --- a/drivers/soc/imx/imx8m-blk-ctrl.c +++ b/drivers/soc/imx/imx8m-blk-ctrl.c @@@ -14,10 -14,10 +14,11 @@@ #include #include + #include #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); @@@ -111,8 -100,6 +112,8 @@@ /* 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", @@@ -506,7 -489,6 +507,7 @@@ .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", @@@ -524,7 -577,10 +596,10 @@@ }, { .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 */ } }; diff --combined drivers/soc/tegra/fuse/fuse-tegra.c index e714ed3b61bc,fe4f935ce73a..913103ee5432 --- a/drivers/soc/tegra/fuse/fuse-tegra.c +++ b/drivers/soc/tegra/fuse/fuse-tegra.c @@@ -14,6 -14,7 +14,7 @@@ #include #include #include + #include #include #include @@@ -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; @@@ -188,13 -195,16 +195,16 @@@ 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; } @@@ -204,19 -214,20 +214,20 @@@ 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)); @@@ -240,19 -251,37 +251,37 @@@ 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; diff --combined drivers/soc/tegra/fuse/fuse.h index ecff0c08e959,1b719d85bd04..2bb1f9d6a6e6 --- a/drivers/soc/tegra/fuse/fuse.h +++ b/drivers/soc/tegra/fuse/fuse.h @@@ -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 2a66a5203d2f,ba7300ca9ddf..1ca320885fad --- a/drivers/tee/optee/core.c +++ b/drivers/tee/optee/core.c @@@ -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. @@@ -165,7 -168,6 +166,6 @@@ 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); } diff --combined drivers/tee/optee/ffa_abi.c index d8c8683863aa,3577781e5df7..20a1b1a3d965 --- a/drivers/tee/optee/ffa_abi.c +++ b/drivers/tee/optee/ffa_abi.c @@@ -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); @@@ -855,9 -856,13 +855,13 @@@ 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) { diff --combined drivers/tee/optee/smc_abi.c index cf2e3293567d,d7c8235c1c42..449d6a72d289 --- a/drivers/tee/optee/smc_abi.c +++ b/drivers/tee/optee/smc_abi.c @@@ -8,13 -8,16 +8,16 @@@ #include #include + #include #include - #include + #include #include #include #include + #include #include #include + #include #include #include #include @@@ -23,7 -26,6 +26,7 @@@ #include "optee_private.h" #include "optee_smc.h" #include "optee_rpc_cmd.h" +#include #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; @@@ -1024,6 -1164,11 +1166,11 @@@ 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; @@@ -1236,7 -1384,8 +1386,8 @@@ 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; } @@@ -1259,7 -1408,7 +1410,7 @@@ optee = kzalloc(sizeof(*optee), GFP_KERNEL); if (!optee) { rc = -ENOMEM; - goto err; + goto err_free_pool; } optee->ops = &optee_ops; @@@ -1269,32 -1418,55 +1420,55 @@@ 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 @@@ -1309,29 -1481,30 +1483,30 @@@ 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 cf5999626e28,468a7d83dc6c..5e1533ee3785 --- a/include/linux/tee_drv.h +++ b/include/linux/tee_drv.h @@@ -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*/