mirror of
https://github.com/armbian/linux-cix.git
synced 2026-01-06 12:30:45 -08:00
Merge tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc
Pull ARM SoC-related driver updates from Olof Johansson:
"Various driver updates for platforms and a couple of the small driver
subsystems we merge through our tree:
Among the larger pieces:
- Power management improvements for TI am335x and am437x (RTC
suspend/wake)
- Misc new additions for Amlogic (socinfo updates)
- ZynqMP FPGA manager
- Nvidia improvements for reset/powergate handling
- PMIC wrapper for Mediatek MT8516
- Misc fixes/improvements for ARM SCMI, TEE, NXP i.MX SCU drivers"
* tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (57 commits)
soc: aspeed: fix Kconfig
soc: add aspeed folder and misc drivers
spi: zynqmp: Fix build break
soc: imx: Add generic i.MX8 SoC driver
MAINTAINERS: Update email for Qualcomm SoC maintainer
memory: tegra: Fix a typos for "fdcdwr2" mc client
Revert "ARM: tegra: Restore memory arbitration on resume from LP1 on Tegra30+"
memory: tegra: Replace readl-writel with mc_readl-mc_writel
memory: tegra: Fix integer overflow on tick value calculation
memory: tegra: Fix missed registers values latching
ARM: tegra: cpuidle: Handle tick broadcasting within cpuidle core on Tegra20/30
optee: allow to work without static shared memory
soc/tegra: pmc: Move powergate initialisation to probe
soc/tegra: pmc: Remove reset sysfs entries on error
soc/tegra: pmc: Fix reset sources and levels
soc: amlogic: meson-gx-pwrc-vpu: Add support for G12A
soc: amlogic: meson-gx-pwrc-vpu: Fix power on/off register bitmask
fpga manager: Adding FPGA Manager support for Xilinx zynqmp
dt-bindings: fpga: Add bindings for ZynqMP fpga driver
firmware: xilinx: Add fpga API's
...
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
Devicetree bindings for Zynq Ultrascale MPSoC FPGA Manager.
|
||||
The ZynqMP SoC uses the PCAP (Processor configuration Port) to configure the
|
||||
Programmable Logic (PL). The configuration uses the firmware interface.
|
||||
|
||||
Required properties:
|
||||
- compatible: should contain "xlnx,zynqmp-pcap-fpga"
|
||||
|
||||
Example for full FPGA configuration:
|
||||
|
||||
fpga-region0 {
|
||||
compatible = "fpga-region";
|
||||
fpga-mgr = <&zynqmp_pcap>;
|
||||
#address-cells = <0x1>;
|
||||
#size-cells = <0x1>;
|
||||
};
|
||||
|
||||
firmware {
|
||||
zynqmp_firmware: zynqmp-firmware {
|
||||
compatible = "xlnx,zynqmp-firmware";
|
||||
method = "smc";
|
||||
zynqmp_pcap: pcap {
|
||||
compatible = "xlnx,zynqmp-pcap-fpga";
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -25,6 +25,7 @@ Required properties in pwrap device node.
|
||||
"mediatek,mt8135-pwrap" for MT8135 SoCs
|
||||
"mediatek,mt8173-pwrap" for MT8173 SoCs
|
||||
"mediatek,mt8183-pwrap" for MT8183 SoCs
|
||||
"mediatek,mt8516-pwrap" for MT8516 SoCs
|
||||
- interrupts: IRQ for pwrap in SOC
|
||||
- reg-names: Must include the following entries:
|
||||
"pwrap": Main registers base
|
||||
|
||||
@@ -41,8 +41,8 @@ Example of EEMI ops usage:
|
||||
int ret;
|
||||
|
||||
eemi_ops = zynqmp_pm_get_eemi_ops();
|
||||
if (!eemi_ops)
|
||||
return -ENXIO;
|
||||
if (IS_ERR(eemi_ops))
|
||||
return PTR_ERR(eemi_ops);
|
||||
|
||||
ret = eemi_ops->query_data(qdata, ret_payload);
|
||||
|
||||
|
||||
@@ -2043,7 +2043,7 @@ W: http://www.armlinux.org.uk/
|
||||
S: Maintained
|
||||
|
||||
ARM/QUALCOMM SUPPORT
|
||||
M: Andy Gross <andy.gross@linaro.org>
|
||||
M: Andy Gross <agross@kernel.org>
|
||||
M: David Brown <david.brown@linaro.org>
|
||||
L: linux-arm-msm@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
@@ -10,6 +10,12 @@
|
||||
#include <asm/suspend.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/platform_data/pm33xx.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/platform_data/gpio-omap.h>
|
||||
#include <linux/pinctrl/pinmux.h>
|
||||
#include <linux/wkup_m3_ipc.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/rtc.h>
|
||||
|
||||
#include "cm33xx.h"
|
||||
#include "common.h"
|
||||
@@ -38,6 +44,29 @@ static int am43xx_map_scu(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int am33xx_check_off_mode_enable(void)
|
||||
{
|
||||
if (enable_off_mode)
|
||||
pr_warn("WARNING: This platform does not support off-mode, entering DeepSleep suspend.\n");
|
||||
|
||||
/* off mode not supported on am335x so return 0 always */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int am43xx_check_off_mode_enable(void)
|
||||
{
|
||||
/*
|
||||
* Check for am437x-gp-evm which has the right Hardware design to
|
||||
* support this mode reliably.
|
||||
*/
|
||||
if (of_machine_is_compatible("ti,am437x-gp-evm") && enable_off_mode)
|
||||
return enable_off_mode;
|
||||
else if (enable_off_mode)
|
||||
pr_warn("WARNING: This platform does not support off-mode, entering DeepSleep suspend.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amx3_common_init(void)
|
||||
{
|
||||
gfx_pwrdm = pwrdm_lookup("gfx_pwrdm");
|
||||
@@ -141,7 +170,9 @@ static int am43xx_suspend(unsigned int state, int (*fn)(unsigned long),
|
||||
scu_power_mode(scu_base, SCU_PM_POWEROFF);
|
||||
ret = cpu_suspend(args, fn);
|
||||
scu_power_mode(scu_base, SCU_PM_NORMAL);
|
||||
amx3_post_suspend_common();
|
||||
|
||||
if (!am43xx_check_off_mode_enable())
|
||||
amx3_post_suspend_common();
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -163,10 +194,48 @@ void __iomem *am43xx_get_rtc_base_addr(void)
|
||||
return omap_hwmod_get_mpu_rt_va(rtc_oh);
|
||||
}
|
||||
|
||||
static void am43xx_save_context(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void am33xx_save_context(void)
|
||||
{
|
||||
omap_intc_save_context();
|
||||
}
|
||||
|
||||
static void am33xx_restore_context(void)
|
||||
{
|
||||
omap_intc_restore_context();
|
||||
}
|
||||
|
||||
static void am43xx_restore_context(void)
|
||||
{
|
||||
/*
|
||||
* HACK: restore dpll_per_clkdcoldo register contents, to avoid
|
||||
* breaking suspend-resume
|
||||
*/
|
||||
writel_relaxed(0x0, AM33XX_L4_WK_IO_ADDRESS(0x44df2e14));
|
||||
}
|
||||
|
||||
static void am43xx_prepare_rtc_suspend(void)
|
||||
{
|
||||
omap_hwmod_enable(rtc_oh);
|
||||
}
|
||||
|
||||
static void am43xx_prepare_rtc_resume(void)
|
||||
{
|
||||
omap_hwmod_idle(rtc_oh);
|
||||
}
|
||||
|
||||
static struct am33xx_pm_platform_data am33xx_ops = {
|
||||
.init = am33xx_suspend_init,
|
||||
.soc_suspend = am33xx_suspend,
|
||||
.get_sram_addrs = amx3_get_sram_addrs,
|
||||
.save_context = am33xx_save_context,
|
||||
.restore_context = am33xx_restore_context,
|
||||
.prepare_rtc_suspend = am43xx_prepare_rtc_suspend,
|
||||
.prepare_rtc_resume = am43xx_prepare_rtc_resume,
|
||||
.check_off_mode_enable = am33xx_check_off_mode_enable,
|
||||
.get_rtc_base_addr = am43xx_get_rtc_base_addr,
|
||||
};
|
||||
|
||||
@@ -174,6 +243,11 @@ static struct am33xx_pm_platform_data am43xx_ops = {
|
||||
.init = am43xx_suspend_init,
|
||||
.soc_suspend = am43xx_suspend,
|
||||
.get_sram_addrs = amx3_get_sram_addrs,
|
||||
.save_context = am43xx_save_context,
|
||||
.restore_context = am43xx_restore_context,
|
||||
.prepare_rtc_suspend = am43xx_prepare_rtc_suspend,
|
||||
.prepare_rtc_resume = am43xx_prepare_rtc_resume,
|
||||
.check_off_mode_enable = am43xx_check_off_mode_enable,
|
||||
.get_rtc_base_addr = am43xx_get_rtc_base_addr,
|
||||
};
|
||||
|
||||
|
||||
@@ -368,6 +368,9 @@ wait_emif_enable1:
|
||||
mov r1, #AM43XX_EMIF_POWEROFF_DISABLE
|
||||
str r1, [r2, #0x0]
|
||||
|
||||
ldr r1, [r9, #EMIF_PM_RUN_HW_LEVELING]
|
||||
blx r1
|
||||
|
||||
#ifdef CONFIG_CACHE_L2X0
|
||||
ldr r2, l2_cache_base
|
||||
ldr r0, [r2, #L2X0_CTRL]
|
||||
|
||||
@@ -10,6 +10,7 @@ menuconfig ARCH_TEGRA
|
||||
select HAVE_ARM_SCU if SMP
|
||||
select HAVE_ARM_TWD if SMP
|
||||
select PINCTRL
|
||||
select PM
|
||||
select PM_OPP
|
||||
select RESET_CONTROLLER
|
||||
select SOC_BUS
|
||||
|
||||
@@ -61,7 +61,8 @@ static struct cpuidle_driver tegra_idle_driver = {
|
||||
.exit_latency = 5000,
|
||||
.target_residency = 10000,
|
||||
.power_usage = 0,
|
||||
.flags = CPUIDLE_FLAG_COUPLED,
|
||||
.flags = CPUIDLE_FLAG_COUPLED |
|
||||
CPUIDLE_FLAG_TIMER_STOP,
|
||||
.name = "powered-down",
|
||||
.desc = "CPU power gated",
|
||||
},
|
||||
@@ -136,12 +137,8 @@ static bool tegra20_cpu_cluster_power_down(struct cpuidle_device *dev,
|
||||
if (tegra20_reset_cpu_1() || !tegra_cpu_rail_off_ready())
|
||||
return false;
|
||||
|
||||
tick_broadcast_enter();
|
||||
|
||||
tegra_idle_lp2_last();
|
||||
|
||||
tick_broadcast_exit();
|
||||
|
||||
if (cpu_online(1))
|
||||
tegra20_wake_cpu1_from_reset();
|
||||
|
||||
@@ -153,14 +150,10 @@ static bool tegra20_idle_enter_lp2_cpu_1(struct cpuidle_device *dev,
|
||||
struct cpuidle_driver *drv,
|
||||
int index)
|
||||
{
|
||||
tick_broadcast_enter();
|
||||
|
||||
cpu_suspend(0, tegra20_sleep_cpu_secondary_finish);
|
||||
|
||||
tegra20_cpu_clear_resettable();
|
||||
|
||||
tick_broadcast_exit();
|
||||
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
|
||||
@@ -56,6 +56,7 @@ static struct cpuidle_driver tegra_idle_driver = {
|
||||
.exit_latency = 2000,
|
||||
.target_residency = 2200,
|
||||
.power_usage = 0,
|
||||
.flags = CPUIDLE_FLAG_TIMER_STOP,
|
||||
.name = "powered-down",
|
||||
.desc = "CPU power gated",
|
||||
},
|
||||
@@ -76,12 +77,8 @@ static bool tegra30_cpu_cluster_power_down(struct cpuidle_device *dev,
|
||||
return false;
|
||||
}
|
||||
|
||||
tick_broadcast_enter();
|
||||
|
||||
tegra_idle_lp2_last();
|
||||
|
||||
tick_broadcast_exit();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -90,14 +87,10 @@ static bool tegra30_cpu_core_power_down(struct cpuidle_device *dev,
|
||||
struct cpuidle_driver *drv,
|
||||
int index)
|
||||
{
|
||||
tick_broadcast_enter();
|
||||
|
||||
smp_wmb();
|
||||
|
||||
cpu_suspend(0, tegra30_sleep_cpu_secondary_finish);
|
||||
|
||||
tick_broadcast_exit();
|
||||
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
|
||||
@@ -79,24 +79,15 @@
|
||||
#define TEGRA_PMC_BASE 0x7000E400
|
||||
#define TEGRA_PMC_SIZE SZ_256
|
||||
|
||||
#define TEGRA_MC_BASE 0x7000F000
|
||||
#define TEGRA_MC_SIZE SZ_1K
|
||||
|
||||
#define TEGRA_EMC_BASE 0x7000F400
|
||||
#define TEGRA_EMC_SIZE SZ_1K
|
||||
|
||||
#define TEGRA114_MC_BASE 0x70019000
|
||||
#define TEGRA114_MC_SIZE SZ_4K
|
||||
|
||||
#define TEGRA_EMC0_BASE 0x7001A000
|
||||
#define TEGRA_EMC0_SIZE SZ_2K
|
||||
|
||||
#define TEGRA_EMC1_BASE 0x7001A800
|
||||
#define TEGRA_EMC1_SIZE SZ_2K
|
||||
|
||||
#define TEGRA124_MC_BASE 0x70019000
|
||||
#define TEGRA124_MC_SIZE SZ_4K
|
||||
|
||||
#define TEGRA124_EMC_BASE 0x7001B000
|
||||
#define TEGRA124_EMC_SIZE SZ_2K
|
||||
|
||||
|
||||
@@ -44,8 +44,6 @@
|
||||
#define EMC_XM2VTTGENPADCTRL 0x310
|
||||
#define EMC_XM2VTTGENPADCTRL2 0x314
|
||||
|
||||
#define MC_EMEM_ARB_CFG 0x90
|
||||
|
||||
#define PMC_CTRL 0x0
|
||||
#define PMC_CTRL_SIDE_EFFECT_LP0 (1 << 14) /* enter LP0 when CPU pwr gated */
|
||||
|
||||
@@ -420,22 +418,6 @@ _pll_m_c_x_done:
|
||||
movweq r0, #:lower16:TEGRA124_EMC_BASE
|
||||
movteq r0, #:upper16:TEGRA124_EMC_BASE
|
||||
|
||||
cmp r10, #TEGRA30
|
||||
moveq r2, #0x20
|
||||
movweq r4, #:lower16:TEGRA_MC_BASE
|
||||
movteq r4, #:upper16:TEGRA_MC_BASE
|
||||
cmp r10, #TEGRA114
|
||||
moveq r2, #0x34
|
||||
movweq r4, #:lower16:TEGRA114_MC_BASE
|
||||
movteq r4, #:upper16:TEGRA114_MC_BASE
|
||||
cmp r10, #TEGRA124
|
||||
moveq r2, #0x20
|
||||
movweq r4, #:lower16:TEGRA124_MC_BASE
|
||||
movteq r4, #:upper16:TEGRA124_MC_BASE
|
||||
|
||||
ldr r1, [r5, r2] @ restore MC_EMEM_ARB_CFG
|
||||
str r1, [r4, #MC_EMEM_ARB_CFG]
|
||||
|
||||
exit_self_refresh:
|
||||
ldr r1, [r5, #0xC] @ restore EMC_XM2VTTGENPADCTRL
|
||||
str r1, [r0, #EMC_XM2VTTGENPADCTRL]
|
||||
@@ -564,7 +546,6 @@ tegra30_sdram_pad_address:
|
||||
.word TEGRA_PMC_BASE + PMC_IO_DPD_STATUS @0x14
|
||||
.word TEGRA_CLK_RESET_BASE + CLK_RESET_CLK_SOURCE_MSELECT @0x18
|
||||
.word TEGRA_CLK_RESET_BASE + CLK_RESET_SCLK_BURST @0x1c
|
||||
.word TEGRA_MC_BASE + MC_EMEM_ARB_CFG @0x20
|
||||
tegra30_sdram_pad_address_end:
|
||||
|
||||
tegra114_sdram_pad_address:
|
||||
@@ -581,7 +562,6 @@ tegra114_sdram_pad_address:
|
||||
.word TEGRA_EMC1_BASE + EMC_AUTO_CAL_INTERVAL @0x28
|
||||
.word TEGRA_EMC1_BASE + EMC_XM2VTTGENPADCTRL @0x2c
|
||||
.word TEGRA_EMC1_BASE + EMC_XM2VTTGENPADCTRL2 @0x30
|
||||
.word TEGRA114_MC_BASE + MC_EMEM_ARB_CFG @0x34
|
||||
tegra114_sdram_pad_adress_end:
|
||||
|
||||
tegra124_sdram_pad_address:
|
||||
@@ -593,7 +573,6 @@ tegra124_sdram_pad_address:
|
||||
.word TEGRA_PMC_BASE + PMC_IO_DPD_STATUS @0x14
|
||||
.word TEGRA_CLK_RESET_BASE + CLK_RESET_CLK_SOURCE_MSELECT @0x18
|
||||
.word TEGRA_CLK_RESET_BASE + CLK_RESET_SCLK_BURST @0x1c
|
||||
.word TEGRA124_MC_BASE + MC_EMEM_ARB_CFG @0x20
|
||||
tegra124_sdram_pad_address_end:
|
||||
|
||||
tegra30_sdram_pad_size:
|
||||
|
||||
@@ -12,28 +12,38 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_clock.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
struct tegra_aconnect {
|
||||
struct clk *ape_clk;
|
||||
struct clk *apb2ape_clk;
|
||||
};
|
||||
|
||||
static int tegra_aconnect_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
struct tegra_aconnect *aconnect;
|
||||
|
||||
if (!pdev->dev.of_node)
|
||||
return -EINVAL;
|
||||
|
||||
ret = pm_clk_create(&pdev->dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
aconnect = devm_kzalloc(&pdev->dev, sizeof(struct tegra_aconnect),
|
||||
GFP_KERNEL);
|
||||
if (!aconnect)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = of_pm_clk_add_clk(&pdev->dev, "ape");
|
||||
if (ret)
|
||||
goto clk_destroy;
|
||||
aconnect->ape_clk = devm_clk_get(&pdev->dev, "ape");
|
||||
if (IS_ERR(aconnect->ape_clk)) {
|
||||
dev_err(&pdev->dev, "Can't retrieve ape clock\n");
|
||||
return PTR_ERR(aconnect->ape_clk);
|
||||
}
|
||||
|
||||
ret = of_pm_clk_add_clk(&pdev->dev, "apb2ape");
|
||||
if (ret)
|
||||
goto clk_destroy;
|
||||
aconnect->apb2ape_clk = devm_clk_get(&pdev->dev, "apb2ape");
|
||||
if (IS_ERR(aconnect->apb2ape_clk)) {
|
||||
dev_err(&pdev->dev, "Can't retrieve apb2ape clock\n");
|
||||
return PTR_ERR(aconnect->apb2ape_clk);
|
||||
}
|
||||
|
||||
dev_set_drvdata(&pdev->dev, aconnect);
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
|
||||
@@ -41,35 +51,51 @@ static int tegra_aconnect_probe(struct platform_device *pdev)
|
||||
dev_info(&pdev->dev, "Tegra ACONNECT bus registered\n");
|
||||
|
||||
return 0;
|
||||
|
||||
clk_destroy:
|
||||
pm_clk_destroy(&pdev->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tegra_aconnect_remove(struct platform_device *pdev)
|
||||
{
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
pm_clk_destroy(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_aconnect_runtime_resume(struct device *dev)
|
||||
{
|
||||
return pm_clk_resume(dev);
|
||||
struct tegra_aconnect *aconnect = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(aconnect->ape_clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "ape clk_enable failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(aconnect->apb2ape_clk);
|
||||
if (ret) {
|
||||
clk_disable_unprepare(aconnect->ape_clk);
|
||||
dev_err(dev, "apb2ape clk_enable failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_aconnect_runtime_suspend(struct device *dev)
|
||||
{
|
||||
return pm_clk_suspend(dev);
|
||||
struct tegra_aconnect *aconnect = dev_get_drvdata(dev);
|
||||
|
||||
clk_disable_unprepare(aconnect->ape_clk);
|
||||
clk_disable_unprepare(aconnect->apb2ape_clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops tegra_aconnect_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(tegra_aconnect_runtime_suspend,
|
||||
tegra_aconnect_runtime_resume, NULL)
|
||||
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
|
||||
pm_runtime_force_resume)
|
||||
};
|
||||
|
||||
static const struct of_device_id tegra_aconnect_of_match[] = {
|
||||
|
||||
@@ -739,8 +739,8 @@ static int zynqmp_clock_probe(struct platform_device *pdev)
|
||||
struct device *dev = &pdev->dev;
|
||||
|
||||
eemi_ops = zynqmp_pm_get_eemi_ops();
|
||||
if (!eemi_ops)
|
||||
return -ENXIO;
|
||||
if (IS_ERR(eemi_ops))
|
||||
return PTR_ERR(eemi_ops);
|
||||
|
||||
ret = zynqmp_clk_setup(dev->of_node);
|
||||
|
||||
|
||||
@@ -654,9 +654,7 @@ static int scmi_xfer_info_init(struct scmi_info *sinfo)
|
||||
|
||||
static int scmi_mailbox_check(struct device_node *np)
|
||||
{
|
||||
struct of_phandle_args arg;
|
||||
|
||||
return of_parse_phandle_with_args(np, "mboxes", "#mbox-cells", 0, &arg);
|
||||
return of_parse_phandle_with_args(np, "mboxes", "#mbox-cells", 0, NULL);
|
||||
}
|
||||
|
||||
static int scmi_mbox_free_channel(int id, void *p, void *data)
|
||||
@@ -798,7 +796,9 @@ static int scmi_probe(struct platform_device *pdev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
desc = of_match_device(scmi_of_match, dev)->data;
|
||||
desc = of_device_get_match_data(dev);
|
||||
if (!desc)
|
||||
return -EINVAL;
|
||||
|
||||
info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
|
||||
if (!info)
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
obj-$(CONFIG_IMX_SCU) += imx-scu.o misc.o
|
||||
obj-$(CONFIG_IMX_SCU) += imx-scu.o misc.o imx-scu-irq.o
|
||||
obj-$(CONFIG_IMX_SCU_PD) += scu-pd.o
|
||||
|
||||
168
drivers/firmware/imx/imx-scu-irq.c
Normal file
168
drivers/firmware/imx/imx-scu-irq.c
Normal file
@@ -0,0 +1,168 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2019 NXP
|
||||
*
|
||||
* Implementation of the SCU IRQ functions using MU.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <dt-bindings/firmware/imx/rsrc.h>
|
||||
#include <linux/firmware/imx/ipc.h>
|
||||
#include <linux/mailbox_client.h>
|
||||
|
||||
#define IMX_SC_IRQ_FUNC_ENABLE 1
|
||||
#define IMX_SC_IRQ_FUNC_STATUS 2
|
||||
#define IMX_SC_IRQ_NUM_GROUP 4
|
||||
|
||||
static u32 mu_resource_id;
|
||||
|
||||
struct imx_sc_msg_irq_get_status {
|
||||
struct imx_sc_rpc_msg hdr;
|
||||
union {
|
||||
struct {
|
||||
u16 resource;
|
||||
u8 group;
|
||||
u8 reserved;
|
||||
} __packed req;
|
||||
struct {
|
||||
u32 status;
|
||||
} resp;
|
||||
} data;
|
||||
};
|
||||
|
||||
struct imx_sc_msg_irq_enable {
|
||||
struct imx_sc_rpc_msg hdr;
|
||||
u32 mask;
|
||||
u16 resource;
|
||||
u8 group;
|
||||
u8 enable;
|
||||
} __packed;
|
||||
|
||||
static struct imx_sc_ipc *imx_sc_irq_ipc_handle;
|
||||
static struct work_struct imx_sc_irq_work;
|
||||
static ATOMIC_NOTIFIER_HEAD(imx_scu_irq_notifier_chain);
|
||||
|
||||
int imx_scu_irq_register_notifier(struct notifier_block *nb)
|
||||
{
|
||||
return atomic_notifier_chain_register(
|
||||
&imx_scu_irq_notifier_chain, nb);
|
||||
}
|
||||
EXPORT_SYMBOL(imx_scu_irq_register_notifier);
|
||||
|
||||
int imx_scu_irq_unregister_notifier(struct notifier_block *nb)
|
||||
{
|
||||
return atomic_notifier_chain_unregister(
|
||||
&imx_scu_irq_notifier_chain, nb);
|
||||
}
|
||||
EXPORT_SYMBOL(imx_scu_irq_unregister_notifier);
|
||||
|
||||
static int imx_scu_irq_notifier_call_chain(unsigned long status, u8 *group)
|
||||
{
|
||||
return atomic_notifier_call_chain(&imx_scu_irq_notifier_chain,
|
||||
status, (void *)group);
|
||||
}
|
||||
|
||||
static void imx_scu_irq_work_handler(struct work_struct *work)
|
||||
{
|
||||
struct imx_sc_msg_irq_get_status msg;
|
||||
struct imx_sc_rpc_msg *hdr = &msg.hdr;
|
||||
u32 irq_status;
|
||||
int ret;
|
||||
u8 i;
|
||||
|
||||
for (i = 0; i < IMX_SC_IRQ_NUM_GROUP; i++) {
|
||||
hdr->ver = IMX_SC_RPC_VERSION;
|
||||
hdr->svc = IMX_SC_RPC_SVC_IRQ;
|
||||
hdr->func = IMX_SC_IRQ_FUNC_STATUS;
|
||||
hdr->size = 2;
|
||||
|
||||
msg.data.req.resource = mu_resource_id;
|
||||
msg.data.req.group = i;
|
||||
|
||||
ret = imx_scu_call_rpc(imx_sc_irq_ipc_handle, &msg, true);
|
||||
if (ret) {
|
||||
pr_err("get irq group %d status failed, ret %d\n",
|
||||
i, ret);
|
||||
return;
|
||||
}
|
||||
|
||||
irq_status = msg.data.resp.status;
|
||||
if (!irq_status)
|
||||
continue;
|
||||
|
||||
imx_scu_irq_notifier_call_chain(irq_status, &i);
|
||||
}
|
||||
}
|
||||
|
||||
int imx_scu_irq_group_enable(u8 group, u32 mask, u8 enable)
|
||||
{
|
||||
struct imx_sc_msg_irq_enable msg;
|
||||
struct imx_sc_rpc_msg *hdr = &msg.hdr;
|
||||
int ret;
|
||||
|
||||
hdr->ver = IMX_SC_RPC_VERSION;
|
||||
hdr->svc = IMX_SC_RPC_SVC_IRQ;
|
||||
hdr->func = IMX_SC_IRQ_FUNC_ENABLE;
|
||||
hdr->size = 3;
|
||||
|
||||
msg.resource = mu_resource_id;
|
||||
msg.group = group;
|
||||
msg.mask = mask;
|
||||
msg.enable = enable;
|
||||
|
||||
ret = imx_scu_call_rpc(imx_sc_irq_ipc_handle, &msg, true);
|
||||
if (ret)
|
||||
pr_err("enable irq failed, group %d, mask %d, ret %d\n",
|
||||
group, mask, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(imx_scu_irq_group_enable);
|
||||
|
||||
static void imx_scu_irq_callback(struct mbox_client *c, void *msg)
|
||||
{
|
||||
schedule_work(&imx_sc_irq_work);
|
||||
}
|
||||
|
||||
int imx_scu_enable_general_irq_channel(struct device *dev)
|
||||
{
|
||||
struct of_phandle_args spec;
|
||||
struct mbox_client *cl;
|
||||
struct mbox_chan *ch;
|
||||
int ret = 0, i = 0;
|
||||
|
||||
ret = imx_scu_get_handle(&imx_sc_irq_ipc_handle);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
cl = devm_kzalloc(dev, sizeof(*cl), GFP_KERNEL);
|
||||
if (!cl)
|
||||
return -ENOMEM;
|
||||
|
||||
cl->dev = dev;
|
||||
cl->rx_callback = imx_scu_irq_callback;
|
||||
|
||||
/* SCU general IRQ uses general interrupt channel 3 */
|
||||
ch = mbox_request_channel_byname(cl, "gip3");
|
||||
if (IS_ERR(ch)) {
|
||||
ret = PTR_ERR(ch);
|
||||
dev_err(dev, "failed to request mbox chan gip3, ret %d\n", ret);
|
||||
devm_kfree(dev, cl);
|
||||
return ret;
|
||||
}
|
||||
|
||||
INIT_WORK(&imx_sc_irq_work, imx_scu_irq_work_handler);
|
||||
|
||||
if (!of_parse_phandle_with_args(dev->of_node, "mboxes",
|
||||
"#mbox-cells", 0, &spec))
|
||||
i = of_alias_get_id(spec.np, "mu");
|
||||
|
||||
/* use mu1 as general mu irq channel if failed */
|
||||
if (i < 0)
|
||||
i = 1;
|
||||
|
||||
mu_resource_id = IMX_SC_R_MU_0A + i;
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(imx_scu_enable_general_irq_channel);
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/firmware/imx/types.h>
|
||||
#include <linux/firmware/imx/ipc.h>
|
||||
#include <linux/firmware/imx/sci.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/kernel.h>
|
||||
@@ -246,6 +247,11 @@ static int imx_scu_probe(struct platform_device *pdev)
|
||||
|
||||
imx_sc_ipc_handle = sc_ipc;
|
||||
|
||||
ret = imx_scu_enable_general_irq_channel(dev);
|
||||
if (ret)
|
||||
dev_warn(dev,
|
||||
"failed to enable general irq channel: %d\n", ret);
|
||||
|
||||
dev_info(dev, "NXP i.MX SCU Initialized\n");
|
||||
|
||||
return devm_of_platform_populate(dev);
|
||||
|
||||
@@ -74,7 +74,10 @@ struct imx_sc_pd_range {
|
||||
char *name;
|
||||
u32 rsrc;
|
||||
u8 num;
|
||||
|
||||
/* add domain index */
|
||||
bool postfix;
|
||||
u8 start_from;
|
||||
};
|
||||
|
||||
struct imx_sc_pd_soc {
|
||||
@@ -84,71 +87,75 @@ struct imx_sc_pd_soc {
|
||||
|
||||
static const struct imx_sc_pd_range imx8qxp_scu_pd_ranges[] = {
|
||||
/* LSIO SS */
|
||||
{ "lsio-pwm", IMX_SC_R_PWM_0, 8, 1 },
|
||||
{ "lsio-gpio", IMX_SC_R_GPIO_0, 8, 1 },
|
||||
{ "lsio-gpt", IMX_SC_R_GPT_0, 5, 1 },
|
||||
{ "lsio-kpp", IMX_SC_R_KPP, 1, 0 },
|
||||
{ "lsio-fspi", IMX_SC_R_FSPI_0, 2, 1 },
|
||||
{ "lsio-mu", IMX_SC_R_MU_0A, 14, 1 },
|
||||
{ "pwm", IMX_SC_R_PWM_0, 8, true, 0 },
|
||||
{ "gpio", IMX_SC_R_GPIO_0, 8, true, 0 },
|
||||
{ "gpt", IMX_SC_R_GPT_0, 5, true, 0 },
|
||||
{ "kpp", IMX_SC_R_KPP, 1, false, 0 },
|
||||
{ "fspi", IMX_SC_R_FSPI_0, 2, true, 0 },
|
||||
{ "mu", IMX_SC_R_MU_0A, 14, true, 0 },
|
||||
|
||||
/* CONN SS */
|
||||
{ "con-usb", IMX_SC_R_USB_0, 2, 1 },
|
||||
{ "con-usb0phy", IMX_SC_R_USB_0_PHY, 1, 0 },
|
||||
{ "con-usb2", IMX_SC_R_USB_2, 1, 0 },
|
||||
{ "con-usb2phy", IMX_SC_R_USB_2_PHY, 1, 0 },
|
||||
{ "con-sdhc", IMX_SC_R_SDHC_0, 3, 1 },
|
||||
{ "con-enet", IMX_SC_R_ENET_0, 2, 1 },
|
||||
{ "con-nand", IMX_SC_R_NAND, 1, 0 },
|
||||
{ "con-mlb", IMX_SC_R_MLB_0, 1, 1 },
|
||||
{ "usb", IMX_SC_R_USB_0, 2, true, 0 },
|
||||
{ "usb0phy", IMX_SC_R_USB_0_PHY, 1, false, 0 },
|
||||
{ "usb2", IMX_SC_R_USB_2, 1, false, 0 },
|
||||
{ "usb2phy", IMX_SC_R_USB_2_PHY, 1, false, 0 },
|
||||
{ "sdhc", IMX_SC_R_SDHC_0, 3, true, 0 },
|
||||
{ "enet", IMX_SC_R_ENET_0, 2, true, 0 },
|
||||
{ "nand", IMX_SC_R_NAND, 1, false, 0 },
|
||||
{ "mlb", IMX_SC_R_MLB_0, 1, true, 0 },
|
||||
|
||||
/* Audio DMA SS */
|
||||
{ "adma-audio-pll0", IMX_SC_R_AUDIO_PLL_0, 1, 0 },
|
||||
{ "adma-audio-pll1", IMX_SC_R_AUDIO_PLL_1, 1, 0 },
|
||||
{ "adma-audio-clk-0", IMX_SC_R_AUDIO_CLK_0, 1, 0 },
|
||||
{ "adma-dma0-ch", IMX_SC_R_DMA_0_CH0, 16, 1 },
|
||||
{ "adma-dma1-ch", IMX_SC_R_DMA_1_CH0, 16, 1 },
|
||||
{ "adma-dma2-ch", IMX_SC_R_DMA_2_CH0, 5, 1 },
|
||||
{ "adma-asrc0", IMX_SC_R_ASRC_0, 1, 0 },
|
||||
{ "adma-asrc1", IMX_SC_R_ASRC_1, 1, 0 },
|
||||
{ "adma-esai0", IMX_SC_R_ESAI_0, 1, 0 },
|
||||
{ "adma-spdif0", IMX_SC_R_SPDIF_0, 1, 0 },
|
||||
{ "adma-sai", IMX_SC_R_SAI_0, 3, 1 },
|
||||
{ "adma-amix", IMX_SC_R_AMIX, 1, 0 },
|
||||
{ "adma-mqs0", IMX_SC_R_MQS_0, 1, 0 },
|
||||
{ "adma-dsp", IMX_SC_R_DSP, 1, 0 },
|
||||
{ "adma-dsp-ram", IMX_SC_R_DSP_RAM, 1, 0 },
|
||||
{ "adma-can", IMX_SC_R_CAN_0, 3, 1 },
|
||||
{ "adma-ftm", IMX_SC_R_FTM_0, 2, 1 },
|
||||
{ "adma-lpi2c", IMX_SC_R_I2C_0, 4, 1 },
|
||||
{ "adma-adc", IMX_SC_R_ADC_0, 1, 1 },
|
||||
{ "adma-lcd", IMX_SC_R_LCD_0, 1, 1 },
|
||||
{ "adma-lcd0-pwm", IMX_SC_R_LCD_0_PWM_0, 1, 1 },
|
||||
{ "adma-lpuart", IMX_SC_R_UART_0, 4, 1 },
|
||||
{ "adma-lpspi", IMX_SC_R_SPI_0, 4, 1 },
|
||||
/* AUDIO SS */
|
||||
{ "audio-pll0", IMX_SC_R_AUDIO_PLL_0, 1, false, 0 },
|
||||
{ "audio-pll1", IMX_SC_R_AUDIO_PLL_1, 1, false, 0 },
|
||||
{ "audio-clk-0", IMX_SC_R_AUDIO_CLK_0, 1, false, 0 },
|
||||
{ "dma0-ch", IMX_SC_R_DMA_0_CH0, 16, true, 0 },
|
||||
{ "dma1-ch", IMX_SC_R_DMA_1_CH0, 16, true, 0 },
|
||||
{ "dma2-ch", IMX_SC_R_DMA_2_CH0, 5, true, 0 },
|
||||
{ "asrc0", IMX_SC_R_ASRC_0, 1, false, 0 },
|
||||
{ "asrc1", IMX_SC_R_ASRC_1, 1, false, 0 },
|
||||
{ "esai0", IMX_SC_R_ESAI_0, 1, false, 0 },
|
||||
{ "spdif0", IMX_SC_R_SPDIF_0, 1, false, 0 },
|
||||
{ "sai", IMX_SC_R_SAI_0, 3, true, 0 },
|
||||
{ "amix", IMX_SC_R_AMIX, 1, false, 0 },
|
||||
{ "mqs0", IMX_SC_R_MQS_0, 1, false, 0 },
|
||||
{ "dsp", IMX_SC_R_DSP, 1, false, 0 },
|
||||
{ "dsp-ram", IMX_SC_R_DSP_RAM, 1, false, 0 },
|
||||
|
||||
/* VPU SS */
|
||||
{ "vpu", IMX_SC_R_VPU, 1, 0 },
|
||||
{ "vpu-pid", IMX_SC_R_VPU_PID0, 8, 1 },
|
||||
{ "vpu-dec0", IMX_SC_R_VPU_DEC_0, 1, 0 },
|
||||
{ "vpu-enc0", IMX_SC_R_VPU_ENC_0, 1, 0 },
|
||||
/* DMA SS */
|
||||
{ "can", IMX_SC_R_CAN_0, 3, true, 0 },
|
||||
{ "ftm", IMX_SC_R_FTM_0, 2, true, 0 },
|
||||
{ "lpi2c", IMX_SC_R_I2C_0, 4, true, 0 },
|
||||
{ "adc", IMX_SC_R_ADC_0, 1, true, 0 },
|
||||
{ "lcd", IMX_SC_R_LCD_0, 1, true, 0 },
|
||||
{ "lcd0-pwm", IMX_SC_R_LCD_0_PWM_0, 1, true, 0 },
|
||||
{ "lpuart", IMX_SC_R_UART_0, 4, true, 0 },
|
||||
{ "lpspi", IMX_SC_R_SPI_0, 4, true, 0 },
|
||||
|
||||
/* VPU SS */
|
||||
{ "vpu", IMX_SC_R_VPU, 1, false, 0 },
|
||||
{ "vpu-pid", IMX_SC_R_VPU_PID0, 8, true, 0 },
|
||||
{ "vpu-dec0", IMX_SC_R_VPU_DEC_0, 1, false, 0 },
|
||||
{ "vpu-enc0", IMX_SC_R_VPU_ENC_0, 1, false, 0 },
|
||||
|
||||
/* GPU SS */
|
||||
{ "gpu0-pid", IMX_SC_R_GPU_0_PID0, 4, 1 },
|
||||
{ "gpu0-pid", IMX_SC_R_GPU_0_PID0, 4, true, 0 },
|
||||
|
||||
/* HSIO SS */
|
||||
{ "hsio-pcie-b", IMX_SC_R_PCIE_B, 1, 0 },
|
||||
{ "hsio-serdes-1", IMX_SC_R_SERDES_1, 1, 0 },
|
||||
{ "hsio-gpio", IMX_SC_R_HSIO_GPIO, 1, 0 },
|
||||
{ "pcie-b", IMX_SC_R_PCIE_B, 1, false, 0 },
|
||||
{ "serdes-1", IMX_SC_R_SERDES_1, 1, false, 0 },
|
||||
{ "hsio-gpio", IMX_SC_R_HSIO_GPIO, 1, false, 0 },
|
||||
|
||||
/* MIPI/LVDS SS */
|
||||
{ "mipi0", IMX_SC_R_MIPI_0, 1, 0 },
|
||||
{ "mipi0-pwm0", IMX_SC_R_MIPI_0_PWM_0, 1, 0 },
|
||||
{ "mipi0-i2c", IMX_SC_R_MIPI_0_I2C_0, 2, 1 },
|
||||
{ "lvds0", IMX_SC_R_LVDS_0, 1, 0 },
|
||||
/* MIPI SS */
|
||||
{ "mipi0", IMX_SC_R_MIPI_0, 1, false, 0 },
|
||||
{ "mipi0-pwm0", IMX_SC_R_MIPI_0_PWM_0, 1, false, 0 },
|
||||
{ "mipi0-i2c", IMX_SC_R_MIPI_0_I2C_0, 2, true, 0 },
|
||||
|
||||
/* LVDS SS */
|
||||
{ "lvds0", IMX_SC_R_LVDS_0, 1, false, 0 },
|
||||
|
||||
/* DC SS */
|
||||
{ "dc0", IMX_SC_R_DC_0, 1, 0 },
|
||||
{ "dc0-pll", IMX_SC_R_DC_0_PLL_0, 2, 1 },
|
||||
{ "dc0", IMX_SC_R_DC_0, 1, false, 0 },
|
||||
{ "dc0-pll", IMX_SC_R_DC_0_PLL_0, 2, true, 0 },
|
||||
};
|
||||
|
||||
static const struct imx_sc_pd_soc imx8qxp_scu_pd = {
|
||||
@@ -236,7 +243,7 @@ imx_scu_add_pm_domain(struct device *dev, int idx,
|
||||
|
||||
if (pd_ranges->postfix)
|
||||
snprintf(sc_pd->name, sizeof(sc_pd->name),
|
||||
"%s%i", pd_ranges->name, idx);
|
||||
"%s%i", pd_ranges->name, pd_ranges->start_from + idx);
|
||||
else
|
||||
snprintf(sc_pd->name, sizeof(sc_pd->name),
|
||||
"%s", pd_ranges->name);
|
||||
|
||||
@@ -90,9 +90,6 @@ static int process_api_request(u32 pm_id, u64 *pm_api_arg, u32 *pm_api_ret)
|
||||
int ret;
|
||||
struct zynqmp_pm_query_data qdata = {0};
|
||||
|
||||
if (!eemi_ops)
|
||||
return -ENXIO;
|
||||
|
||||
switch (pm_id) {
|
||||
case PM_GET_API_VERSION:
|
||||
ret = eemi_ops->get_api_version(&pm_api_version);
|
||||
@@ -163,21 +160,14 @@ static ssize_t zynqmp_pm_debugfs_api_write(struct file *file,
|
||||
|
||||
strcpy(debugfs_buf, "");
|
||||
|
||||
if (*off != 0 || len == 0)
|
||||
if (*off != 0 || len <= 1 || len > PAGE_SIZE - 1)
|
||||
return -EINVAL;
|
||||
|
||||
kern_buff = kzalloc(len, GFP_KERNEL);
|
||||
if (!kern_buff)
|
||||
return -ENOMEM;
|
||||
|
||||
kern_buff = memdup_user_nul(ptr, len);
|
||||
if (IS_ERR(kern_buff))
|
||||
return PTR_ERR(kern_buff);
|
||||
tmp_buff = kern_buff;
|
||||
|
||||
ret = strncpy_from_user(kern_buff, ptr, len);
|
||||
if (ret < 0) {
|
||||
ret = -EFAULT;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Read the API name from a user request */
|
||||
pm_api_req = strsep(&kern_buff, " ");
|
||||
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#include <linux/firmware/xlnx-zynqmp.h>
|
||||
#include "zynqmp-debug.h"
|
||||
|
||||
static const struct zynqmp_eemi_ops *eemi_ops_tbl;
|
||||
|
||||
static const struct mfd_cell firmware_devs[] = {
|
||||
{
|
||||
.name = "zynqmp_power_controller",
|
||||
@@ -537,6 +539,49 @@ static int zynqmp_pm_reset_get_status(const enum zynqmp_pm_reset reset,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* zynqmp_pm_fpga_load - Perform the fpga load
|
||||
* @address: Address to write to
|
||||
* @size: pl bitstream size
|
||||
* @flags: Bitstream type
|
||||
* -XILINX_ZYNQMP_PM_FPGA_FULL: FPGA full reconfiguration
|
||||
* -XILINX_ZYNQMP_PM_FPGA_PARTIAL: FPGA partial reconfiguration
|
||||
*
|
||||
* This function provides access to pmufw. To transfer
|
||||
* the required bitstream into PL.
|
||||
*
|
||||
* Return: Returns status, either success or error+reason
|
||||
*/
|
||||
static int zynqmp_pm_fpga_load(const u64 address, const u32 size,
|
||||
const u32 flags)
|
||||
{
|
||||
return zynqmp_pm_invoke_fn(PM_FPGA_LOAD, lower_32_bits(address),
|
||||
upper_32_bits(address), size, flags, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* zynqmp_pm_fpga_get_status - Read value from PCAP status register
|
||||
* @value: Value to read
|
||||
*
|
||||
* This function provides access to the pmufw to get the PCAP
|
||||
* status
|
||||
*
|
||||
* Return: Returns status, either success or error+reason
|
||||
*/
|
||||
static int zynqmp_pm_fpga_get_status(u32 *value)
|
||||
{
|
||||
u32 ret_payload[PAYLOAD_ARG_CNT];
|
||||
int ret;
|
||||
|
||||
if (!value)
|
||||
return -EINVAL;
|
||||
|
||||
ret = zynqmp_pm_invoke_fn(PM_FPGA_GET_STATUS, 0, 0, 0, 0, ret_payload);
|
||||
*value = ret_payload[1];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* zynqmp_pm_init_finalize() - PM call to inform firmware that the caller
|
||||
* master has initialized its own power management
|
||||
@@ -640,6 +685,8 @@ static const struct zynqmp_eemi_ops eemi_ops = {
|
||||
.request_node = zynqmp_pm_request_node,
|
||||
.release_node = zynqmp_pm_release_node,
|
||||
.set_requirement = zynqmp_pm_set_requirement,
|
||||
.fpga_load = zynqmp_pm_fpga_load,
|
||||
.fpga_get_status = zynqmp_pm_fpga_get_status,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -649,7 +696,11 @@ static const struct zynqmp_eemi_ops eemi_ops = {
|
||||
*/
|
||||
const struct zynqmp_eemi_ops *zynqmp_pm_get_eemi_ops(void)
|
||||
{
|
||||
return &eemi_ops;
|
||||
if (eemi_ops_tbl)
|
||||
return eemi_ops_tbl;
|
||||
else
|
||||
return ERR_PTR(-EPROBE_DEFER);
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_get_eemi_ops);
|
||||
|
||||
@@ -694,6 +745,9 @@ static int zynqmp_firmware_probe(struct platform_device *pdev)
|
||||
pr_info("%s Trustzone version v%d.%d\n", __func__,
|
||||
pm_tz_version >> 16, pm_tz_version & 0xFFFF);
|
||||
|
||||
/* Assign eemi_ops_table */
|
||||
eemi_ops_tbl = &eemi_ops;
|
||||
|
||||
zynqmp_pm_api_debugfs_init();
|
||||
|
||||
ret = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, firmware_devs,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user