Skip to content
Snippets Groups Projects
Commit 0f875ba8 authored by Sebastian Reichel's avatar Sebastian Reichel Committed by Sebastian Reichel
Browse files

[HACK] arm64: dts: imx95: switch mali to panthor


Use Panthor to handle the Mali GPU. This also adds some changes
to the panthor driver to handle i.MX95 specific power management:

1. There is a clock APB. Somehow this only exists in the Variscite
   tree. The i.MX95 kernel tree from NXP itself does not have it.
   But the vendor kernel instead has a second power domain, which
   does not exist in the Variscite tree. I'm not sure if the APB
   clock requires any frequency changes from devfreq, so for now
   I disabled any OPP entries except the default one.

2. The i.MX95 has a second IO memory range related to the GPU,
   which is needed to power it on. It's unnamed in the Variscite
   kernel tree, but the NXP kernel has a name: "gpumix_blk_ctrl".
   It is absolutely mandatory to write a 1 at offset 0x8 in that
   memory range to get the GPU powered on. Otherwise acessing the
   GPU IO memory range will stall the full system. I'm not sure
   if this write needs to be done on any runtime resume, or just
   once during system powerup. For now this gets the driver
   probing.

Signed-off-by: default avatarSebastian Reichel <sebastian.reichel@collabora.com>
parent 6b1ab9ed
No related branches found
No related tags found
No related merge requests found
...@@ -641,23 +641,22 @@ gpu_opp_table: opp_table { ...@@ -641,23 +641,22 @@ gpu_opp_table: opp_table {
opp-1000000000 { opp-1000000000 {
opp-hz = /bits/ 64 <1000000000>; opp-hz = /bits/ 64 <1000000000>;
opp-hz-real = /bits/ 64 <1000000000>, /bits/ 64 <500000000>;
}; };
/* TODO: need to check handling of APB clock before enabling devfreq */
/*
opp-800000000 { opp-800000000 {
opp-hz = /bits/ 64 <800000000>; opp-hz = /bits/ 64 <800000000>;
opp-hz-real = /bits/ 64 <800000000>, /bits/ 64 <500000000>;
}; };
opp-667000000 { opp-667000000 {
opp-hz = /bits/ 64 <667000000>; opp-hz = /bits/ 64 <667000000>;
opp-hz-real = /bits/ 64 <667000000>, /bits/ 64 <400000000>;
}; };
opp-400000000 { opp-400000000 {
opp-hz = /bits/ 64 <400000000>; opp-hz = /bits/ 64 <400000000>;
opp-hz-real = /bits/ 64 <400000000>, /bits/ 64 <250000000>;
}; };
*/
}; };
usbphynop: usbphynop { usbphynop: usbphynop {
...@@ -2930,14 +2929,14 @@ vpu_blk_ctrl: syscon@4c410000 { ...@@ -2930,14 +2929,14 @@ vpu_blk_ctrl: syscon@4c410000 {
}; };
mali: gpu@4d900000 { mali: gpu@4d900000 {
compatible = "arm,mali-valhall"; compatible = "nxp,imx95-mali", "arm,mali-valhall-csf";
reg = <0 0x4d900000 0 0x700000>, <0 0x4d810000 0 0x10000>; reg = <0 0x4d900000 0 0x700000>, <0 0x4d810000 0 0x10000>;
interrupts = <GIC_SPI 288 IRQ_TYPE_LEVEL_HIGH>, interrupts = <GIC_SPI 288 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 289 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 289 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 290 IRQ_TYPE_LEVEL_HIGH>; <GIC_SPI 290 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "GPU", "JOB", "MMU"; interrupt-names = "gpu", "job", "mmu";
clocks = <&scmi_clk IMX95_CLK_GPU>, <&scmi_clk IMX95_CLK_GPUAPB>; clocks = <&scmi_clk IMX95_CLK_GPU>, <&scmi_clk IMX95_CLK_GPUAPB>;
clock-names = "gpu", "gpu_apb"; clock-names = "core", "apb";
power-domains = <&scmi_devpd IMX95_PD_GPU>; power-domains = <&scmi_devpd IMX95_PD_GPU>;
operating-points-v2 = <&gpu_opp_table>; operating-points-v2 = <&gpu_opp_table>;
#cooling-cells = <2>; #cooling-cells = <2>;
......
...@@ -42,6 +42,12 @@ static int panthor_clk_init(struct panthor_device *ptdev) ...@@ -42,6 +42,12 @@ static int panthor_clk_init(struct panthor_device *ptdev)
PTR_ERR(ptdev->clks.coregroup), PTR_ERR(ptdev->clks.coregroup),
"get 'coregroup' clock failed"); "get 'coregroup' clock failed");
ptdev->clks.apb = devm_clk_get_optional(ptdev->base.dev, "apb");
if (IS_ERR(ptdev->clks.apb))
return dev_err_probe(ptdev->base.dev,
PTR_ERR(ptdev->clks.apb),
"get 'apb' clock failed");
drm_info(&ptdev->base, "clock rate = %lu\n", clk_get_rate(ptdev->clks.core)); drm_info(&ptdev->base, "clock rate = %lu\n", clk_get_rate(ptdev->clks.core));
return 0; return 0;
} }
...@@ -211,6 +217,8 @@ int panthor_device_init(struct panthor_device *ptdev) ...@@ -211,6 +217,8 @@ int panthor_device_init(struct panthor_device *ptdev)
ptdev->phys_addr = res->start; ptdev->phys_addr = res->start;
ptdev->imx_blk_ctrl = devm_platform_ioremap_resource(to_platform_device(ptdev->base.dev), 1);
ret = devm_pm_runtime_enable(ptdev->base.dev); ret = devm_pm_runtime_enable(ptdev->base.dev);
if (ret) if (ret)
return ret; return ret;
...@@ -413,11 +421,19 @@ int panthor_device_resume(struct device *dev) ...@@ -413,11 +421,19 @@ int panthor_device_resume(struct device *dev)
struct panthor_device *ptdev = dev_get_drvdata(dev); struct panthor_device *ptdev = dev_get_drvdata(dev);
int ret, cookie; int ret, cookie;
drm_info(&ptdev->base, "resuming device...\n");
if (atomic_read(&ptdev->pm.state) != PANTHOR_DEVICE_PM_STATE_SUSPENDED) if (atomic_read(&ptdev->pm.state) != PANTHOR_DEVICE_PM_STATE_SUSPENDED)
return -EINVAL; return -EINVAL;
atomic_set(&ptdev->pm.state, PANTHOR_DEVICE_PM_STATE_RESUMING); atomic_set(&ptdev->pm.state, PANTHOR_DEVICE_PM_STATE_RESUMING);
if(!IS_ERR_OR_NULL(ptdev->imx_blk_ctrl)) {
drm_info(&ptdev->base, "Enable BLK_CTRL...\n");
writel(0x1, ptdev->imx_blk_ctrl + 0x8);
drm_info(&ptdev->base, "Enabled BLK_CTRL\n");
}
ret = clk_prepare_enable(ptdev->clks.core); ret = clk_prepare_enable(ptdev->clks.core);
if (ret) if (ret)
goto err_set_suspended; goto err_set_suspended;
...@@ -430,10 +446,14 @@ int panthor_device_resume(struct device *dev) ...@@ -430,10 +446,14 @@ int panthor_device_resume(struct device *dev)
if (ret) if (ret)
goto err_disable_stacks_clk; goto err_disable_stacks_clk;
ret = panthor_devfreq_resume(ptdev); ret = clk_prepare_enable(ptdev->clks.apb);
if (ret) if (ret)
goto err_disable_coregroup_clk; goto err_disable_coregroup_clk;
ret = panthor_devfreq_resume(ptdev);
if (ret)
goto err_disable_apb_clk;
if (panthor_device_is_initialized(ptdev) && if (panthor_device_is_initialized(ptdev) &&
drm_dev_enter(&ptdev->base, &cookie)) { drm_dev_enter(&ptdev->base, &cookie)) {
panthor_gpu_resume(ptdev); panthor_gpu_resume(ptdev);
...@@ -465,11 +485,17 @@ int panthor_device_resume(struct device *dev) ...@@ -465,11 +485,17 @@ int panthor_device_resume(struct device *dev)
DRM_PANTHOR_USER_MMIO_OFFSET, 0, 1); DRM_PANTHOR_USER_MMIO_OFFSET, 0, 1);
atomic_set(&ptdev->pm.state, PANTHOR_DEVICE_PM_STATE_ACTIVE); atomic_set(&ptdev->pm.state, PANTHOR_DEVICE_PM_STATE_ACTIVE);
mutex_unlock(&ptdev->pm.mmio_lock); mutex_unlock(&ptdev->pm.mmio_lock);
drm_info(&ptdev->base, "device resumed\n");
return 0; return 0;
err_suspend_devfreq: err_suspend_devfreq:
panthor_devfreq_suspend(ptdev); panthor_devfreq_suspend(ptdev);
err_disable_apb_clk:
clk_disable_unprepare(ptdev->clks.apb);
err_disable_coregroup_clk: err_disable_coregroup_clk:
clk_disable_unprepare(ptdev->clks.coregroup); clk_disable_unprepare(ptdev->clks.coregroup);
...@@ -489,6 +515,8 @@ int panthor_device_suspend(struct device *dev) ...@@ -489,6 +515,8 @@ int panthor_device_suspend(struct device *dev)
struct panthor_device *ptdev = dev_get_drvdata(dev); struct panthor_device *ptdev = dev_get_drvdata(dev);
int ret, cookie; int ret, cookie;
drm_info(&ptdev->base, "suspending device...\n");
if (atomic_read(&ptdev->pm.state) != PANTHOR_DEVICE_PM_STATE_ACTIVE) if (atomic_read(&ptdev->pm.state) != PANTHOR_DEVICE_PM_STATE_ACTIVE)
return -EINVAL; return -EINVAL;
...@@ -533,10 +561,12 @@ int panthor_device_suspend(struct device *dev) ...@@ -533,10 +561,12 @@ int panthor_device_suspend(struct device *dev)
goto err_set_active; goto err_set_active;
} }
clk_disable_unprepare(ptdev->clks.apb);
clk_disable_unprepare(ptdev->clks.coregroup); clk_disable_unprepare(ptdev->clks.coregroup);
clk_disable_unprepare(ptdev->clks.stacks); clk_disable_unprepare(ptdev->clks.stacks);
clk_disable_unprepare(ptdev->clks.core); clk_disable_unprepare(ptdev->clks.core);
atomic_set(&ptdev->pm.state, PANTHOR_DEVICE_PM_STATE_SUSPENDED); atomic_set(&ptdev->pm.state, PANTHOR_DEVICE_PM_STATE_SUSPENDED);
drm_info(&ptdev->base, "device suspended\n");
return 0; return 0;
err_set_active: err_set_active:
......
...@@ -78,6 +78,9 @@ struct panthor_device { ...@@ -78,6 +78,9 @@ struct panthor_device {
/** @iomem: CPU mapping of the IOMEM region. */ /** @iomem: CPU mapping of the IOMEM region. */
void __iomem *iomem; void __iomem *iomem;
/** @imx_blk_ctrl: CPU mapping of the i.MX BLK_CTRL region. */
void __iomem *imx_blk_ctrl;
/** @clks: GPU clocks. */ /** @clks: GPU clocks. */
struct { struct {
/** @core: Core clock. */ /** @core: Core clock. */
...@@ -88,6 +91,9 @@ struct panthor_device { ...@@ -88,6 +91,9 @@ struct panthor_device {
/** @coregroup: Core group clock. This clock is optional. */ /** @coregroup: Core group clock. This clock is optional. */
struct clk *coregroup; struct clk *coregroup;
/** @apb: Bus clock. This clock is optional. */
struct clk *apb;
} clks; } clks;
/** @coherent: True if the CPU/GPU are memory coherent. */ /** @coherent: True if the CPU/GPU are memory coherent. */
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment