drm/msm/mdp4: only use lut_clk on mdp4.2+
Subsystems (4)
PATCH 1/9 drm/msm/mdp4: only use lut_clk on mdp4.2+
--- drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-)
drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c +13 -9
@@ -206,7 +206,8 @@ int mdp4_disable(struct mdp4_kms *mdp4_kms)clk_disable_unprepare (mdp4_kms->clk);if (mdp4_kms->pclk)clk_disable_unprepare (mdp4_kms->pclk); -clk_disable_unprepare (mdp4_kms->lut_clk); +if (mdp4_kms->lut_clk) +clk_disable_unprepare (mdp4_kms->lut_clk);if (mdp4_kms->axi_clk)clk_disable_unprepare (mdp4_kms->axi_clk);
@@ -220,7 +221,8 @@ int mdp4_enable(struct mdp4_kms *mdp4_kms)clk_prepare_enable (mdp4_kms->clk);if (mdp4_kms->pclk)clk_prepare_enable (mdp4_kms->pclk); -clk_prepare_enable (mdp4_kms->lut_clk); +if (mdp4_kms->lut_clk) +clk_prepare_enable (mdp4_kms->lut_clk);if (mdp4_kms->axi_clk)clk_prepare_enable (mdp4_kms->axi_clk);
@@ -472,12 +474,13 @@ struct msm_kms *mdp4_kms_init(struct drm_device *dev)if (IS_ERR (mdp4_kms->pclk)) mdp4_kms->pclk =NULL ; -// XXX if (rev >= MDP_REV_42) { ??? - mdp4_kms->lut_clk =devm_clk_get (&pdev->dev,"lut_clk" ); -if (IS_ERR (mdp4_kms->lut_clk)) { -dev_err (dev->dev,"failed to get lut_clk\n" ); - ret =PTR_ERR (mdp4_kms->lut_clk); - goto fail; +if (mdp4_kms->rev >=2 ) { + mdp4_kms->lut_clk =devm_clk_get (&pdev->dev,"lut_clk" ); +if (IS_ERR (mdp4_kms->lut_clk)) { +dev_err (dev->dev,"failed to get lut_clk\n" ); + ret =PTR_ERR (mdp4_kms->lut_clk); + goto fail; + } } mdp4_kms->axi_clk =devm_clk_get (&pdev->dev,"bus_clk" );
@@ -488,7 +491,8 @@ struct msm_kms *mdp4_kms_init(struct drm_device *dev) }clk_set_rate (mdp4_kms->clk, config->max_clk); -clk_set_rate (mdp4_kms->lut_clk, config->max_clk); +if (mdp4_kms->lut_clk) +clk_set_rate (mdp4_kms->lut_clk, config->max_clk);pm_runtime_enable (dev->dev); mdp4_kms->rpm_enabled = true;
Signature · 1 line
2.17.1
PATCH 2/9 drm/msm/mdp4: allocate blank_cursor_no with MSM_BO_SCANOUT flag
For allocation in contiguous memory when the GPU has MMU but not mdp4.
--- drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c +1 -1
@@ -534,7 +534,7 @@ struct msm_kms *mdp4_kms_init(struct drm_device *dev) goto fail; } - mdp4_kms->blank_cursor_bo =msm_gem_new (dev,SZ_16K ,MSM_BO_WC ); + mdp4_kms->blank_cursor_bo =msm_gem_new (dev,SZ_16K ,MSM_BO_WC |MSM_BO_SCANOUT );if (IS_ERR (mdp4_kms->blank_cursor_bo)) { ret =PTR_ERR (mdp4_kms->blank_cursor_bo);dev_err (dev->dev,"could not allocate blank-cursor bo: %d\n" , ret);
Signature · 1 line
2.17.1
PATCH 3/9 drm/msm/mdp4: add lcdc-align-lsb flag to control lane alignment
In reply to Jonathan MarekControls which of the 8 lanes are used for 6 bit color.
--- .../gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-)
drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c +14 -8
@@ -377,20 +377,26 @@ static void mdp4_lcdc_encoder_enable(struct drm_encoder *encoder)unsigned long pc = mdp4_lcdc_encoder->pixclock;struct mdp4_kms *mdp4_kms =get_kms (encoder);struct drm_panel *panel; +uint32_t config;int i, ret;if (WARN_ON (mdp4_lcdc_encoder->enabled))return ;/* TODO: hard-coded for 18bpp: */ -mdp4_crtc_set_config (encoder->crtc, -MDP4_DMA_CONFIG_R_BPC (BPC6 ) | -MDP4_DMA_CONFIG_G_BPC (BPC6 ) | -MDP4_DMA_CONFIG_B_BPC (BPC6 ) | -MDP4_DMA_CONFIG_PACK_ALIGN_MSB | -MDP4_DMA_CONFIG_PACK (0x21 ) | -MDP4_DMA_CONFIG_DEFLKR_EN | -MDP4_DMA_CONFIG_DITHER_EN ); + config = +MDP4_DMA_CONFIG_R_BPC (BPC6 ) | +MDP4_DMA_CONFIG_G_BPC (BPC6 ) | +MDP4_DMA_CONFIG_B_BPC (BPC6 ) | +MDP4_DMA_CONFIG_PACK (0x21 ) | +MDP4_DMA_CONFIG_DEFLKR_EN | +MDP4_DMA_CONFIG_DITHER_EN ; + +if (!of_find_property (dev->dev->of_node,"lcdc-align-lsb" ,NULL )) + config |=MDP4_DMA_CONFIG_PACK_ALIGN_MSB ; + + +mdp4_crtc_set_config (encoder->crtc, config);mdp4_crtc_set_intf (encoder->crtc,INTF_LCDC_DTV ,0 );bs_set (mdp4_lcdc_encoder,1 );
Signature · 1 line
2.17.1
PATCH 4/9 drm/msm: use contiguous vram for MSM_BO_SCANOUT when possible
In reply to Jonathan MarekMakes it possible to have MMU for GPU but not display.
--- drivers/gpu/drm/msm/msm_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/msm/msm_gem.c +1 -1
@@ -914,7 +914,7 @@ static struct drm_gem_object *_msm_gem_new(struct drm_device *dev,if (!iommu_present (&platform_bus_type)) use_vram = true; -else if ((flags &MSM_BO_STOLEN ) && priv->vram.size) +else if ((flags & (MSM_BO_STOLEN |MSM_BO_SCANOUT )) && priv->vram.size) use_vram = true;printk ("_msm_gem_new %u bytes use_vram=%u\n" , size, use_vram);
Signature · 1 line
2.17.1
PATCH 5/9 drm/msm: add headless gpu device (for imx5)
In reply to Jonathan Marek--- drivers/gpu/drm/msm/Kconfig | 4 ++-- drivers/gpu/drm/msm/msm_debugfs.c | 2 +- drivers/gpu/drm/msm/msm_drv.c | 15 +++++++++++---- include/linux/qcom_scm.h | 3 +++ 4 files changed, 17 insertions(+), 7 deletions(-)
drivers/gpu/drm/msm/Kconfig +2 -2
@@ -2,7 +2,7 @@ config DRM_MSM tristate "MSM DRM" depends on DRM - depends on ARCH_QCOM || (ARM && COMPILE_TEST) + depends on ARCH_QCOM || SOC_IMX5 || (ARM && COMPILE_TEST) depends on OF && COMMON_CLK depends on MMU select QCOM_MDT_LOADER if ARCH_QCOM
@@ -11,7 +11,7 @@ config DRM_MSM select DRM_PANEL select SHMEM select TMPFS - select QCOM_SCM + select QCOM_SCM if ARCH_QCOM select WANT_DEV_COREDUMP select SND_SOC_HDMI_CODEC if SND_SOC select SYNC_FILE
drivers/gpu/drm/msm/msm_debugfs.c +1 -1
@@ -235,7 +235,7 @@ int msm_debugfs_init(struct drm_minor *minor)debugfs_create_file ("gpu" ,S_IRUSR , minor->debugfs_root, dev, &msm_gpu_fops); -if (priv->kms->funcs->debugfs_init) { +if (priv->kms && priv->kms->funcs->debugfs_init) { ret = priv->kms->funcs->debugfs_init (priv->kms, minor);if (ret)return ret;
drivers/gpu/drm/msm/msm_drv.c +11 -4
@@ -344,6 +344,7 @@ static int msm_drm_uninit(struct device *dev)return 0 ; } +#define KMS_HEADLESS 1#define KMS_MDP4 4#define KMS_MDP5 5#define KMS_DPU 3
@@ -495,6 +496,9 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)msm_gem_shrinker_init (ddev);switch (get_mdp_ver (pdev)) { +case KMS_HEADLESS : + priv->kms = kms =NULL ; +break ;case KMS_MDP4 : kms =mdp4_kms_init (ddev); priv->kms = kms;
@@ -633,7 +637,7 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)drm_mode_config_reset (ddev);#ifdef CONFIG_DRM_FBDEV_EMULATION -if (fbdev) +if (kms && fbdev) priv->fbdev =msm_fbdev_init (ddev);#endif
@@ -1315,9 +1319,11 @@ static int msm_pdev_probe(struct platform_device *pdev)struct component_match *match =NULL ;int ret; - ret =add_display_components (&pdev->dev, &match); -if (ret) -return ret; +if (get_mdp_ver (pdev) !=KMS_HEADLESS ) { + ret =add_display_components (&pdev->dev, &match); +if (ret) +return ret; + } ret =add_gpu_components (&pdev->dev, &match);if (ret)
@@ -1342,6 +1348,7 @@ static int msm_pdev_remove(struct platform_device *pdev) }static const struct of_device_id dt_match[] = { + { .compatible ="qcom,adreno-headless" , .data = (void *)KMS_HEADLESS }, { .compatible ="qcom,mdp4" , .data = (void *)KMS_MDP4 }, { .compatible ="qcom,mdss" , .data = (void *)KMS_MDP5 }, { .compatible ="qcom,sdm845-mdss" , .data = (void *)KMS_DPU },
include/linux/qcom_scm.h +3 -0
@@ -67,6 +67,9 @@ extern int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare);extern int qcom_scm_io_readl (phys_addr_t addr,unsigned int *val);extern int qcom_scm_io_writel (phys_addr_t addr,unsigned int val);#else + +#include <linux/errno.h> +static inline int qcom_scm_set_cold_boot_addr (void *entry,const cpumask_t *cpus) {
Signature · 1 line
2.17.1
Re: [PATCH 5/9] drm/msm: add headless gpu device (for imx5)
Thanks for the patch. Perhaps a small blurb here for the commit log to let folks know what your intent was.
Quoted 56 lines · Jonathan Marek
Signed-off-by Jonathan Marek <[email protected]>--- drivers/gpu/drm/msm/Kconfig | 4 ++-- drivers/gpu/drm/msm/msm_debugfs.c | 2 +- drivers/gpu/drm/msm/msm_drv.c | 15 +++++++++++---- include/linux/qcom_scm.h | 3 +++ 4 files changed, 17 insertions(+), 7 deletions(-)drivers/gpu/drm/msm/Kconfig +2
-2@@ -2,7 +2,7 @@ config DRM_MSM tristate "MSM DRM" depends on DRM - depends on ARCH_QCOM || (ARM && COMPILE_TEST) + depends on ARCH_QCOM || SOC_IMX5 || (ARM && COMPILE_TEST) depends on OF && COMMON_CLK depends on MMU select QCOM_MDT_LOADER if ARCH_QCOM@@ -11,7 +11,7 @@ config DRM_MSM select DRM_PANEL select SHMEM select TMPFS - select QCOM_SCM + select QCOM_SCM if ARCH_QCOM select WANT_DEV_COREDUMP select SND_SOC_HDMI_CODEC if SND_SOC select SYNC_FILEdrivers/gpu/drm/msm/msm_debugfs.c +1
-1@@ -235,7 +235,7 @@ int msm_debugfs_init(struct drm_minor *minor)debugfs_create_file ("gpu" ,S_IRUSR , minor->debugfs_root, dev, &msm_gpu_fops); -if (priv->kms->funcs->debugfs_init) { +if (priv->kms && priv->kms->funcs->debugfs_init) { ret = priv->kms->funcs->debugfs_init (priv->kms, minor);if (ret)return ret;drivers/gpu/drm/msm/msm_drv.c +1
-0@@ -344,6 +344,7 @@ static int msm_drm_uninit(struct device *dev)return 0 ; } +#define KMS_HEADLESS 1#define KMS_MDP4 4#define KMS_MDP5 5#define KMS_DPU 3
drivers/gpu/drm/msm/msm_drv.c static int msm_drm_init(struct device *dev, struct drm_driver *drv) · line 500
Quoted 5 lines
drivers/gpu/drm/msm/msm_drv.c +2
-0@@ -495,6 +496,9 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)msm_gem_shrinker_init (ddev);switch (get_mdp_ver (pdev)) { +case KMS_HEADLESS : + priv->kms = kms =NULL ;
I don't think you need to set priv->kms, it should come in as NULL. I would normally say that you should set kms to NULL when it is declared, but I kind of like pointing it out to the user.
Quoted 41 lines
drivers/gpu/drm/msm/msm_drv.c +8
-4+break ;case KMS_MDP4 : kms =mdp4_kms_init (ddev); priv->kms = kms;@@ -633,7 +637,7 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)drm_mode_config_reset (ddev);#ifdef CONFIG_DRM_FBDEV_EMULATION -if (fbdev) +if (kms && fbdev) priv->fbdev =msm_fbdev_init (ddev);#endif @@ -1315,9 +1319,11 @@ static int msm_pdev_probe(struct platform_device *pdev)struct component_match *match =NULL ;int ret; - ret =add_display_components (&pdev->dev, &match); -if (ret) -return ret; +if (get_mdp_ver (pdev) !=KMS_HEADLESS ) { + ret =add_display_components (&pdev->dev, &match); +if (ret) +return ret; + } ret =add_gpu_components (&pdev->dev, &match);if (ret)@@ -1342,6 +1348,7 @@ static int msm_pdev_remove(struct platform_device *pdev) }static const struct of_device_id dt_match[] = { + { .compatible ="qcom,adreno-headless" , .data = (void *)KMS_HEADLESS }, { .compatible ="qcom,mdp4" , .data = (void *)KMS_MDP4 }, { .compatible ="qcom,mdss" , .data = (void *)KMS_MDP5 }, { .compatible ="qcom,sdm845-mdss" , .data = (void *)KMS_DPU },include/linux/qcom_scm.h +0
-0
include/linux/qcom_scm.h extern int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare); · line 72
Quoted 6 lines
include/linux/qcom_scm.h +3
-0@@ -67,6 +67,9 @@ extern int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare);extern int qcom_scm_io_readl (phys_addr_t addr,unsigned int *val);extern int qcom_scm_io_writel (phys_addr_t addr,unsigned int val);#else + +#include <linux/errno.h> +
This looks like a separate patch, albeit a useful one.
include/linux/qcom_scm.h extern int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare); · line 75
Quoted 3 lines
include/linux/qcom_scm.h +0
-0static inline int qcom_scm_set_cold_boot_addr (void *entry,const cpumask_t *cpus) {
Jordan
Signature · 6 lines
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project _______________________________________________ Freedreno mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [PATCH 5/9] drm/msm: add headless gpu device (for imx5)
Quoted 3 lines · Jordan Crouse
Thanks for the patch. Perhaps a small blurb here for the commit log to let folks know what your intent was.
I will add an explanation. The intent is clear to me from the commit message, but perhaps not for everyone.
Quoted 59 lines · Jonathan Marek
Quoted 58 lines
Signed-off-by Jonathan Marek <[email protected]>--- drivers/gpu/drm/msm/Kconfig | 4 ++-- drivers/gpu/drm/msm/msm_debugfs.c | 2 +- drivers/gpu/drm/msm/msm_drv.c | 15 +++++++++++---- include/linux/qcom_scm.h | 3 +++ 4 files changed, 17 insertions(+), 7 deletions(-)drivers/gpu/drm/msm/Kconfig +2
-2@@ -2,7 +2,7 @@ config DRM_MSM tristate "MSM DRM" depends on DRM - depends on ARCH_QCOM || (ARM && COMPILE_TEST) + depends on ARCH_QCOM || SOC_IMX5 || (ARM && COMPILE_TEST) depends on OF && COMMON_CLK depends on MMU select QCOM_MDT_LOADER if ARCH_QCOM@@ -11,7 +11,7 @@ config DRM_MSM select DRM_PANEL select SHMEM select TMPFS - select QCOM_SCM + select QCOM_SCM if ARCH_QCOM select WANT_DEV_COREDUMP select SND_SOC_HDMI_CODEC if SND_SOC select SYNC_FILEdrivers/gpu/drm/msm/msm_debugfs.c +1
-1@@ -235,7 +235,7 @@ int msm_debugfs_init(struct drm_minor *minor)debugfs_create_file ("gpu" ,S_IRUSR , minor->debugfs_root, dev, &msm_gpu_fops); -if (priv->kms->funcs->debugfs_init) { +if (priv->kms && priv->kms->funcs->debugfs_init) { ret = priv->kms->funcs->debugfs_init (priv->kms, minor);if (ret)return ret;drivers/gpu/drm/msm/msm_drv.c +1
-0@@ -344,6 +344,7 @@ static int msm_drm_uninit(struct device *dev)return 0 ; } +#define KMS_HEADLESS 1#define KMS_MDP4 4#define KMS_MDP5 5#define KMS_DPU 3@@ -495,6 +496,9 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)msm_gem_shrinker_init (ddev);
Quoted 8 lines
drivers/gpu/drm/msm/msm_drv.c static int msm_drm_init(struct device *dev, struct drm_driver *drv) · line 500
Quoted 3 lines
drivers/gpu/drm/msm/msm_drv.c +2
-0switch (get_mdp_ver (pdev)) { +case KMS_HEADLESS : + priv->kms = kms =NULL ;I don't think you need to set
priv->kms, it should come in as NULL. I would normally say that you should set kms to NULL when it is declared, but I kind of like pointing it out to the user.
It comes as NULL, but initializing it here matches the other cases in the switch (at the cost of 12 characters).
Quoted 41 lines
Quoted 41 lines
drivers/gpu/drm/msm/msm_drv.c +8
-4+break ;case KMS_MDP4 : kms =mdp4_kms_init (ddev); priv->kms = kms;@@ -633,7 +637,7 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)drm_mode_config_reset (ddev);#ifdef CONFIG_DRM_FBDEV_EMULATION -if (fbdev) +if (kms && fbdev) priv->fbdev =msm_fbdev_init (ddev);#endif @@ -1315,9 +1319,11 @@ static int msm_pdev_probe(struct platform_device *pdev)struct component_match *match =NULL ;int ret; - ret =add_display_components (&pdev->dev, &match); -if (ret) -return ret; +if (get_mdp_ver (pdev) !=KMS_HEADLESS ) { + ret =add_display_components (&pdev->dev, &match); +if (ret) +return ret; + } ret =add_gpu_components (&pdev->dev, &match);if (ret)@@ -1342,6 +1348,7 @@ static int msm_pdev_remove(struct platform_device *pdev) }static const struct of_device_id dt_match[] = { + { .compatible ="qcom,adreno-headless" , .data = (void *)KMS_HEADLESS }, { .compatible ="qcom,mdp4" , .data = (void *)KMS_MDP4 }, { .compatible ="qcom,mdss" , .data = (void *)KMS_MDP5 }, { .compatible ="qcom,sdm845-mdss" , .data = (void *)KMS_DPU },include/linux/qcom_scm.h +0
-0@@ -67,6 +67,9 @@ extern int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare);
Quoted 9 lines
include/linux/qcom_scm.h extern int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare); · line 72
Quoted 6 lines
include/linux/qcom_scm.h +3
-0extern int qcom_scm_io_readl (phys_addr_t addr,unsigned int *val);extern int qcom_scm_io_writel (phys_addr_t addr,unsigned int val);#else + +#include <linux/errno.h> +This looks like a separate patch, albeit a useful one.
Yes, that isn't part of this patch. Oops.
Quoted 6 lines
include/linux/qcom_scm.h extern int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare); · line 75
Quoted 3 lines
include/linux/qcom_scm.h +0
-0static inline int qcom_scm_set_cold_boot_addr (void *entry,const cpumask_t *cpus) {Jordan
Jonathan
_______________________________________________
Freedreno mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/freedreno
PATCH 6/9 drm/msm/adreno: add a2xx
In reply to Jonathan Marekderived from the a3xx driver and tested on the following hardware:
imx51-zii-rdu1 (a200 with 128kb gmem)
imx53-qsrb (a200)
msm8060-tenderloin (a220)
--- drivers/gpu/drm/msm/Makefile | 1 + drivers/gpu/drm/msm/adreno/a2xx_gpu.c | 445 +++++++++++++++++++++ drivers/gpu/drm/msm/adreno/a2xx_gpu.h | 21 + drivers/gpu/drm/msm/adreno/adreno_device.c | 33 ++ drivers/gpu/drm/msm/adreno/adreno_gpu.c | 27 +- drivers/gpu/drm/msm/adreno/adreno_gpu.h | 15 + 6 files changed, 534 insertions(+), 8 deletions(-) create mode 100644 drivers/gpu/drm/msm/adreno/a2xx_gpu.c create mode 100644 drivers/gpu/drm/msm/adreno/a2xx_gpu.h
drivers/gpu/drm/msm/Makefile +1 -0
@@ -6,6 +6,7 @@ ccflags-$(CONFIG_DRM_MSM_DSI) += -Idrivers/gpu/drm/msm/dsi msm-y := \ adreno/adreno_device.o \ adreno/adreno_gpu.o \ + adreno/a2xx_gpu.o \ adreno/a3xx_gpu.o \ adreno/a4xx_gpu.o \ adreno/a5xx_gpu.o \
drivers/gpu/drm/msm/adreno/a2xx_gpu.c new file +445 -0
445 lines not on this page · raw message
drivers/gpu/drm/msm/adreno/a2xx_gpu.h new file +21 -0
@@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2018 The Linux Foundation. All rights reserved. */ + +#ifndef __A2XX_GPU_H__ +#define __A2XX_GPU_H__ + +#include "adreno_gpu.h" + +/* arrg, somehow fb.h is getting pulled in: */ +#undef ROP_COPY +#undef ROP_XOR + +#include "a2xx.xml.h" + +struct a2xx_gpu { +struct adreno_gpu base; +bool pm_enabled; +}; +#define to_a2xx_gpu (x) container_of(x, struct a2xx_gpu, base) + +#endif /* __A2XX_GPU_H__ */
drivers/gpu/drm/msm/adreno/adreno_device.c +33 -0
@@ -27,6 +27,39 @@ module_param_named(hang_debug, hang_debug, bool, 0600);static const struct adreno_info gpulist[] = { { + .rev =ADRENO_REV (2 ,0 ,0 ,0 ), + .revn =200 , + .name ="A200" , + .fw = { + [ADRENO_FW_PM4 ] ="yamato_pm4.fw" , + [ADRENO_FW_PFP ] ="yamato_pfp.fw" , + }, + .gmem =SZ_256K , + .inactive_period =DRM_MSM_INACTIVE_PERIOD , + .init = a2xx_gpu_init, + }, {/* a200 on i.mx51 has only 128kib gmem */ + .rev =ADRENO_REV (2 ,0 ,0 ,1 ), + .revn =201 , + .name ="A200" , + .fw = { + [ADRENO_FW_PM4 ] ="yamato_pm4.fw" , + [ADRENO_FW_PFP ] ="yamato_pfp.fw" , + }, + .gmem =SZ_128K , + .inactive_period =DRM_MSM_INACTIVE_PERIOD , + .init = a2xx_gpu_init, + }, { + .rev =ADRENO_REV (2 ,2 ,0 ,ANY_ID ), + .revn =220 , + .name ="A220" , + .fw = { + [ADRENO_FW_PM4 ] ="leia_pm4_470.fw" , + [ADRENO_FW_PFP ] ="leia_pfp_470.fw" , + }, + .gmem =SZ_512K , + .inactive_period =DRM_MSM_INACTIVE_PERIOD , + .init = a2xx_gpu_init, + }, { .rev =ADRENO_REV (3 ,0 ,5 ,ANY_ID ), .revn =305 , .name ="A305" ,
drivers/gpu/drm/msm/adreno/adreno_gpu.c +19 -8
@@ -319,16 +319,27 @@ void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,*/ OUT_PKT3 (ring,CP_EVENT_WRITE ,1 );OUT_RING (ring,HLSQ_FLUSH ); - -OUT_PKT3 (ring,CP_WAIT_FOR_IDLE ,1 ); -OUT_RING (ring,0x00000000 ); } -/* BIT(31) of CACHE_FLUSH_TS triggers CACHE_FLUSH_TS IRQ from GPU */ -OUT_PKT3 (ring,CP_EVENT_WRITE ,3 ); -OUT_RING (ring,CACHE_FLUSH_TS |BIT (31 )); -OUT_RING (ring,rbmemptr (ring, fence)); -OUT_RING (ring, submit->seqno); +/* wait for idle before cache flush/interrupt */ +OUT_PKT3 (ring,CP_WAIT_FOR_IDLE ,1 ); +OUT_RING (ring,0x00000000 ); + +if (!adreno_is_a2xx (adreno_gpu)) { +/* BIT(31) of CACHE_FLUSH_TS triggers CACHE_FLUSH_TS IRQ from GPU */ +OUT_PKT3 (ring,CP_EVENT_WRITE ,3 ); +OUT_RING (ring,CACHE_FLUSH_TS |BIT (31 )); +OUT_RING (ring,rbmemptr (ring, fence)); +OUT_RING (ring, submit->seqno); + }else { +/* BIT(31) means something else on a2xx */ +OUT_PKT3 (ring,CP_EVENT_WRITE ,3 ); +OUT_RING (ring,CACHE_FLUSH_TS ); +OUT_RING (ring,rbmemptr (ring, fence)); +OUT_RING (ring, submit->seqno); +OUT_PKT3 (ring,CP_INTERRUPT ,1 ); +OUT_RING (ring,0x80000000 ); + }#if 0 if (adreno_is_a3xx (adreno_gpu)) {
drivers/gpu/drm/msm/adreno/adreno_gpu.h +15 -0
@@ -154,6 +154,20 @@ struct adreno_platform_config { __ret; \ }) +static inline bool adreno_is_a2xx (struct adreno_gpu *gpu) +{ +return (gpu->revn <300 ); +} + +static inline bool adreno_is_a20x (struct adreno_gpu *gpu) +{ +return (gpu->revn <210 ); +} + +static inline bool adreno_is_a225 (struct adreno_gpu *gpu) +{ +return gpu->revn ==225 ; +}static inline bool adreno_is_a3xx (struct adreno_gpu *gpu) {
@@ -334,6 +348,7 @@ static inline void adreno_gpu_write(struct adreno_gpu *gpu,gpu_write (&gpu->base, reg -1 , data); } +struct msm_gpu *a2xx_gpu_init (struct drm_device *dev);struct msm_gpu *a3xx_gpu_init (struct drm_device *dev);struct msm_gpu *a4xx_gpu_init (struct drm_device *dev);struct msm_gpu *a5xx_gpu_init (struct drm_device *dev);
Signature · 1 line
2.17.1
Re: [PATCH 6/9] drm/msm/adreno: add a2xx
Quoted 4 lines · Jonathan Marek
derived from the a3xx driver and tested on the following hardware:
imx51-zii-rdu1 (a200 with 128kb gmem)
imx53-qsrb (a200)
msm8060-tenderloin (a220)
This looks sane but it has been quite a while since I've thought about 2xx.
If this works on real world hardware thats is a pretty good endorsement.
Only nit - I would turn the /* XXX */ comments into real comments. Since KGSL dropped 2xx support some time in the 3.4 timeframe I think it is a good idea to record what the old code did for posterity.
With that:
Quoted 622 lines
Signed-off-by Jonathan Marek <[email protected]>--- drivers/gpu/drm/msm/Makefile | 1 + drivers/gpu/drm/msm/adreno/a2xx_gpu.c | 445 +++++++++++++++++++++ drivers/gpu/drm/msm/adreno/a2xx_gpu.h | 21 + drivers/gpu/drm/msm/adreno/adreno_device.c | 33 ++ drivers/gpu/drm/msm/adreno/adreno_gpu.c | 27 +- drivers/gpu/drm/msm/adreno/adreno_gpu.h | 15 + 6 files changed, 534 insertions(+), 8 deletions(-) create mode 100644 drivers/gpu/drm/msm/adreno/a2xx_gpu.c create mode 100644 drivers/gpu/drm/msm/adreno/a2xx_gpu.hdrivers/gpu/drm/msm/Makefile +1
-0@@ -6,6 +6,7 @@ ccflags-$(CONFIG_DRM_MSM_DSI) += -Idrivers/gpu/drm/msm/dsi msm-y := \ adreno/adreno_device.o \ adreno/adreno_gpu.o \ + adreno/a2xx_gpu.o \ adreno/a3xx_gpu.o \ adreno/a4xx_gpu.o \ adreno/a5xx_gpu.o \drivers/gpu/drm/msm/adreno/a2xx_gpu.c new file +445
-0@@ -0,0 +1,445 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2018 The Linux Foundation. All rights reserved. */ + +#include "a2xx_gpu.h" + +extern bool hang_debug; + +static void a2xx_dump (struct msm_gpu *gpu); +static bool a2xx_idle (struct msm_gpu *gpu); + +static bool a2xx_me_init (struct msm_gpu *gpu) +{ +struct msm_ringbuffer *ring = gpu->rb[0 ]; + +OUT_PKT3 (ring,CP_ME_INIT ,18 ); + +/* All fields present (bits 9:0) */ +OUT_RING (ring,0x000003ff ); +/* Disable/Enable Real-Time Stream processing (present but ignored) */ +OUT_RING (ring,0x00000000 ); +/* Enable (2D <-> 3D) implicit synchronization (present but ignored) */ +OUT_RING (ring,0x00000000 ); + +OUT_RING (ring,REG_A2XX_RB_SURFACE_INFO -0x2000 ); +OUT_RING (ring,REG_A2XX_PA_SC_WINDOW_OFFSET -0x2000 ); +OUT_RING (ring,REG_A2XX_VGT_MAX_VTX_INDX -0x2000 ); +OUT_RING (ring,REG_A2XX_SQ_PROGRAM_CNTL -0x2000 ); +OUT_RING (ring,REG_A2XX_RB_DEPTHCONTROL -0x2000 ); +OUT_RING (ring,REG_A2XX_PA_SU_POINT_SIZE -0x2000 ); +OUT_RING (ring,REG_A2XX_PA_SC_LINE_CNTL -0x2000 ); +OUT_RING (ring,REG_A2XX_PA_SU_POLY_OFFSET_FRONT_SCALE -0x2000 ); + +/* Vertex and Pixel Shader Start Addresses in instructions +* (3 DWORDS per instruction) */ +OUT_RING (ring,0x80000180 ); +/* Maximum Contexts */ +OUT_RING (ring,0x00000001 ); +/* Write Confirm Interval and The CP will wait the +* wait_interval * 16 clocks between polling */ +OUT_RING (ring,0x00000000 ); +/* NQ and External Memory Swap */ +OUT_RING (ring,0x00000000 ); +/* protected mode error checking (0x1f2 is REG_AXXX_CP_INT_CNTL) */ +OUT_RING (ring,0x200001f2 ); +/* Disable header dumping and Header dump address */ +OUT_RING (ring,0x00000000 ); +/* Header dump size */ +OUT_RING (ring,0x00000000 ); + +/* enable protected mode */ +OUT_PKT3 (ring,CP_SET_PROTECTED_MODE ,1 ); +OUT_RING (ring,1 ); + + gpu->funcs->flush (gpu, ring); +return a2xx_idle (gpu); +} + +static int a2xx_hw_init (struct msm_gpu *gpu) +{ +struct adreno_gpu *adreno_gpu =to_adreno_gpu (gpu); +uint32_t *ptr, len; +int i, ret; + +DBG ("%s" , gpu->name); + +gpu_write (gpu,REG_A2XX_RBBM_PM_OVERRIDE1 ,0xfffffffe ); +gpu_write (gpu,REG_A2XX_RBBM_PM_OVERRIDE2 ,0xffffffff ); + +/* XXX kgsl uses 0x00000001 after first reset on a22x */ +gpu_write (gpu,REG_A2XX_RBBM_SOFT_RESET ,0xffffffff ); +msleep (30 ); +gpu_write (gpu,REG_A2XX_RBBM_SOFT_RESET ,0x00000000 ); + +if (adreno_is_a225 (adreno_gpu)) +gpu_write (gpu,REG_A2XX_SQ_FLOW_CONTROL ,0x18000000 ); + +/* XXX kgsl uses 0x0000ffff for a20x */ +gpu_write (gpu,REG_A2XX_RBBM_CNTL ,0x00004442 ); + +gpu_write (gpu,REG_A2XX_MH_MMU_CONFIG ,0 ); +gpu_write (gpu,REG_A2XX_MH_MMU_MPU_BASE ,0 ); +gpu_write (gpu,REG_A2XX_MH_MMU_MPU_END ,0xfffff000 ); +gpu_write (gpu,REG_A2XX_MH_ARBITER_CONFIG , +A2XX_MH_ARBITER_CONFIG_SAME_PAGE_LIMIT (16 ) | +A2XX_MH_ARBITER_CONFIG_L1_ARB_ENABLE | +A2XX_MH_ARBITER_CONFIG_L1_ARB_HOLD_ENABLE | +A2XX_MH_ARBITER_CONFIG_PAGE_SIZE (1 ) | +A2XX_MH_ARBITER_CONFIG_TC_REORDER_ENABLE | +A2XX_MH_ARBITER_CONFIG_TC_ARB_HOLD_ENABLE | +A2XX_MH_ARBITER_CONFIG_IN_FLIGHT_LIMIT_ENABLE | +A2XX_MH_ARBITER_CONFIG_IN_FLIGHT_LIMIT (8 ) | +A2XX_MH_ARBITER_CONFIG_CP_CLNT_ENABLE | +A2XX_MH_ARBITER_CONFIG_VGT_CLNT_ENABLE | +A2XX_MH_ARBITER_CONFIG_TC_CLNT_ENABLE | +A2XX_MH_ARBITER_CONFIG_RB_CLNT_ENABLE | +A2XX_MH_ARBITER_CONFIG_PA_CLNT_ENABLE ); +if (!adreno_is_a20x (adreno_gpu)) +gpu_write (gpu,REG_A2XX_MH_CLNT_INTF_CTRL_CONFIG1 ,0x00032f07 ); + +gpu_write (gpu,REG_A2XX_SQ_VS_PROGRAM ,0x00000000 ); +gpu_write (gpu,REG_A2XX_SQ_PS_PROGRAM ,0x00000000 ); + +gpu_write (gpu,REG_A2XX_RBBM_PM_OVERRIDE1 ,0 );/* 0x200 for msm8960? */ +gpu_write (gpu,REG_A2XX_RBBM_PM_OVERRIDE2 ,0 );/* 0x80/0x1a0 for a22x? */ + +/* XXX gsl doesn't set this */ +gpu_write (gpu,REG_A2XX_RBBM_DEBUG ,0x00080000 ); + +gpu_write (gpu,REG_A2XX_RBBM_INT_CNTL ,0 ); +gpu_write (gpu,REG_AXXX_CP_INT_CNTL ,0x80000000 );/* RB INT */ +gpu_write (gpu,REG_A2XX_SQ_INT_CNTL ,0 ); + +for (i =3 ; i <=5 ; i++) +if ((SZ_16K << i) == adreno_gpu->gmem) +break ; +gpu_write (gpu,REG_A2XX_RB_EDRAM_INFO , i); + + ret =adreno_hw_init (gpu); +if (ret) +return ret; + +/* NOTE: PM4/micro-engine firmware registers look to be the same +* for a2xx and a3xx.. we could possibly push that part down to +* adreno_gpu base class. Or push both PM4 and PFP but +* parameterize the pfp ucode addr/data registers.. +*/ + +/* Load PM4: */ + ptr = (uint32_t *)(adreno_gpu->fw[ADRENO_FW_PM4 ]->data); + len = adreno_gpu->fw[ADRENO_FW_PM4 ]->size /4 ; +DBG ("loading PM4 ucode version: %x" , ptr[1 ]); + +gpu_write (gpu,REG_AXXX_CP_DEBUG ,0x02000000 ); +gpu_write (gpu,REG_AXXX_CP_ME_RAM_WADDR ,0 ); +for (i =1 ; i < len; i++) +gpu_write (gpu,REG_AXXX_CP_ME_RAM_DATA , ptr[i]); + +/* Load PFP: */ + ptr = (uint32_t *)(adreno_gpu->fw[ADRENO_FW_PFP ]->data); + len = adreno_gpu->fw[ADRENO_FW_PFP ]->size /4 ; +DBG ("loading PFP ucode version: %x" , ptr[5 ]); + +gpu_write (gpu,REG_A2XX_CP_PFP_UCODE_ADDR ,0 ); +for (i =1 ; i < len; i++) +gpu_write (gpu,REG_A2XX_CP_PFP_UCODE_DATA , ptr[i]); + +gpu_write (gpu,REG_AXXX_CP_QUEUE_THRESHOLDS ,0x000C0804 ); + +/* clear ME_HALT to start micro engine */ +gpu_write (gpu,REG_AXXX_CP_ME_CNTL ,0 ); + +return a2xx_me_init (gpu) ?0 : -EINVAL ; +} + +static void a2xx_recover (struct msm_gpu *gpu) +{ +int i; + +adreno_dump_info (gpu); + +for (i =0 ; i <8 ; i++) { +printk ("CP_SCRATCH_REG%d: %u\n" , i, +gpu_read (gpu,REG_AXXX_CP_SCRATCH_REG0 + i)); + } + +/* dump registers before resetting gpu, if enabled: */ +if (hang_debug) +a2xx_dump (gpu); + +gpu_write (gpu,REG_A2XX_RBBM_SOFT_RESET ,1 ); +gpu_read (gpu,REG_A2XX_RBBM_SOFT_RESET ); +gpu_write (gpu,REG_A2XX_RBBM_SOFT_RESET ,0 ); +adreno_recover (gpu); +} + +static void a2xx_destroy (struct msm_gpu *gpu) +{ +struct adreno_gpu *adreno_gpu =to_adreno_gpu (gpu); +struct a2xx_gpu *a2xx_gpu =to_a2xx_gpu (adreno_gpu); + +DBG ("%s" , gpu->name); + +adreno_gpu_cleanup (adreno_gpu); + +kfree (a2xx_gpu); +} + +static bool a2xx_idle (struct msm_gpu *gpu) +{ +/* wait for ringbuffer to drain: */ +if (!adreno_idle (gpu, gpu->rb[0 ])) +return false; + +/* then wait for GPU to finish: */ +if (spin_until (!(gpu_read (gpu,REG_A2XX_RBBM_STATUS ) & +A2XX_RBBM_STATUS_GUI_ACTIVE ))) { +DRM_ERROR ("%s: timeout waiting for GPU to idle!\n" , gpu->name); + +/* TODO maybe we need to reset GPU here to recover from hang? */ +return false; + } + +return true; +} + +static irqreturn_t a2xx_irq (struct msm_gpu *gpu) +{ + +uint32_t mstatus, status; + + mstatus =gpu_read (gpu,REG_A2XX_MASTER_INT_SIGNAL ); + +if (mstatus &A2XX_MASTER_INT_SIGNAL_MH_INT_STAT ) { + status =gpu_read (gpu,REG_A2XX_MH_INTERRUPT_STATUS ); + +dev_warn (gpu->dev->dev,"MH_INT: %08X\n" , status); +dev_warn (gpu->dev->dev,"MMU_PAGE_FAULT: %08X\n" , +gpu_read (gpu,REG_A2XX_MH_MMU_PAGE_FAULT )); +gpu_write (gpu,REG_A2XX_MH_INTERRUPT_CLEAR , status); + } + +if (mstatus &A2XX_MASTER_INT_SIGNAL_CP_INT_STAT ) { + status =gpu_read (gpu,REG_AXXX_CP_INT_STATUS ); + +/* only RB_INT is expected */ +if (status & ~AXXX_CP_INT_CNTL_RB_INT_MASK ) +dev_warn (gpu->dev->dev,"CP_INT: %08X\n" , status); + +gpu_write (gpu,REG_AXXX_CP_INT_ACK , status); + } + +if (mstatus &A2XX_MASTER_INT_SIGNAL_RBBM_INT_STAT ) { + status =gpu_read (gpu,REG_A2XX_RBBM_INT_STATUS ); + +dev_warn (gpu->dev->dev,"RBBM_INT: %08X\n" , status); + +gpu_write (gpu,REG_A2XX_RBBM_INT_ACK , status); + } + +msm_gpu_retire (gpu); + +return IRQ_HANDLED ; +} + +static const unsigned int a200_registers[] = { +0x0000 ,0x0002 ,0x0004 ,0x000B ,0x003B ,0x003D ,0x0040 ,0x0044 , +0x0046 ,0x0047 ,0x01C0 ,0x01C1 ,0x01C3 ,0x01C8 ,0x01D5 ,0x01D9 , +0x01DC ,0x01DD ,0x01EA ,0x01EA ,0x01EE ,0x01F3 ,0x01F6 ,0x01F7 , +0x01FC ,0x01FF ,0x0391 ,0x0392 ,0x039B ,0x039E ,0x03B2 ,0x03B5 , +0x03B7 ,0x03B7 ,0x03F8 ,0x03FB ,0x0440 ,0x0440 ,0x0443 ,0x0444 , +0x044B ,0x044B ,0x044D ,0x044F ,0x0452 ,0x0452 ,0x0454 ,0x045B , +0x047F ,0x047F ,0x0578 ,0x0587 ,0x05C9 ,0x05C9 ,0x05D0 ,0x05D0 , +0x0601 ,0x0604 ,0x0606 ,0x0609 ,0x060B ,0x060E ,0x0613 ,0x0614 , +0x0A29 ,0x0A2B ,0x0A2F ,0x0A31 ,0x0A40 ,0x0A43 ,0x0A45 ,0x0A45 , +0x0A4E ,0x0A4F ,0x0C2C ,0x0C2C ,0x0C30 ,0x0C30 ,0x0C38 ,0x0C3C , +0x0C40 ,0x0C40 ,0x0C44 ,0x0C44 ,0x0C80 ,0x0C86 ,0x0C88 ,0x0C94 , +0x0C99 ,0x0C9A ,0x0CA4 ,0x0CA5 ,0x0D00 ,0x0D03 ,0x0D06 ,0x0D06 , +0x0D08 ,0x0D0B ,0x0D34 ,0x0D35 ,0x0DAE ,0x0DC1 ,0x0DC8 ,0x0DD4 , +0x0DD8 ,0x0DD9 ,0x0E00 ,0x0E00 ,0x0E02 ,0x0E04 ,0x0E17 ,0x0E1E , +0x0EC0 ,0x0EC9 ,0x0ECB ,0x0ECC ,0x0ED0 ,0x0ED0 ,0x0ED4 ,0x0ED7 , +0x0EE0 ,0x0EE2 ,0x0F01 ,0x0F02 ,0x0F0C ,0x0F0C ,0x0F0E ,0x0F12 , +0x0F26 ,0x0F2A ,0x0F2C ,0x0F2C ,0x2000 ,0x2002 ,0x2006 ,0x200F , +0x2080 ,0x2082 ,0x2100 ,0x2109 ,0x210C ,0x2114 ,0x2180 ,0x2184 , +0x21F5 ,0x21F7 ,0x2200 ,0x2208 ,0x2280 ,0x2283 ,0x2293 ,0x2294 , +0x2300 ,0x2308 ,0x2312 ,0x2312 ,0x2316 ,0x231D ,0x2324 ,0x2326 , +0x2380 ,0x2383 ,0x2400 ,0x2402 ,0x2406 ,0x240F ,0x2480 ,0x2482 , +0x2500 ,0x2509 ,0x250C ,0x2514 ,0x2580 ,0x2584 ,0x25F5 ,0x25F7 , +0x2600 ,0x2608 ,0x2680 ,0x2683 ,0x2693 ,0x2694 ,0x2700 ,0x2708 , +0x2712 ,0x2712 ,0x2716 ,0x271D ,0x2724 ,0x2726 ,0x2780 ,0x2783 , +0x4000 ,0x4003 ,0x4800 ,0x4805 ,0x4900 ,0x4900 ,0x4908 ,0x4908 , + ~0 /* sentinel */ +}; + +static const unsigned int a220_registers[] = { +0x0000 ,0x0002 ,0x0004 ,0x000B ,0x003B ,0x003D ,0x0040 ,0x0044 , +0x0046 ,0x0047 ,0x01C0 ,0x01C1 ,0x01C3 ,0x01C8 ,0x01D5 ,0x01D9 , +0x01DC ,0x01DD ,0x01EA ,0x01EA ,0x01EE ,0x01F3 ,0x01F6 ,0x01F7 , +0x01FC ,0x01FF ,0x0391 ,0x0392 ,0x039B ,0x039E ,0x03B2 ,0x03B5 , +0x03B7 ,0x03B7 ,0x03F8 ,0x03FB ,0x0440 ,0x0440 ,0x0443 ,0x0444 , +0x044B ,0x044B ,0x044D ,0x044F ,0x0452 ,0x0452 ,0x0454 ,0x045B , +0x047F ,0x047F ,0x0578 ,0x0587 ,0x05C9 ,0x05C9 ,0x05D0 ,0x05D0 , +0x0601 ,0x0604 ,0x0606 ,0x0609 ,0x060B ,0x060E ,0x0613 ,0x0614 , +0x0A29 ,0x0A2B ,0x0A2F ,0x0A31 ,0x0A40 ,0x0A40 ,0x0A42 ,0x0A43 , +0x0A45 ,0x0A45 ,0x0A4E ,0x0A4F ,0x0C30 ,0x0C30 ,0x0C38 ,0x0C39 , +0x0C3C ,0x0C3C ,0x0C80 ,0x0C81 ,0x0C88 ,0x0C93 ,0x0D00 ,0x0D03 , +0x0D05 ,0x0D06 ,0x0D08 ,0x0D0B ,0x0D34 ,0x0D35 ,0x0DAE ,0x0DC1 , +0x0DC8 ,0x0DD4 ,0x0DD8 ,0x0DD9 ,0x0E00 ,0x0E00 ,0x0E02 ,0x0E04 , +0x0E17 ,0x0E1E ,0x0EC0 ,0x0EC9 ,0x0ECB ,0x0ECC ,0x0ED0 ,0x0ED0 , +0x0ED4 ,0x0ED7 ,0x0EE0 ,0x0EE2 ,0x0F01 ,0x0F02 ,0x2000 ,0x2002 , +0x2006 ,0x200F ,0x2080 ,0x2082 ,0x2100 ,0x2102 ,0x2104 ,0x2109 , +0x210C ,0x2114 ,0x2180 ,0x2184 ,0x21F5 ,0x21F7 ,0x2200 ,0x2202 , +0x2204 ,0x2204 ,0x2208 ,0x2208 ,0x2280 ,0x2282 ,0x2294 ,0x2294 , +0x2300 ,0x2308 ,0x2309 ,0x230A ,0x2312 ,0x2312 ,0x2316 ,0x2316 , +0x2318 ,0x231D ,0x2324 ,0x2326 ,0x2380 ,0x2383 ,0x2400 ,0x2402 , +0x2406 ,0x240F ,0x2480 ,0x2482 ,0x2500 ,0x2502 ,0x2504 ,0x2509 , +0x250C ,0x2514 ,0x2580 ,0x2584 ,0x25F5 ,0x25F7 ,0x2600 ,0x2602 , +0x2604 ,0x2606 ,0x2608 ,0x2608 ,0x2680 ,0x2682 ,0x2694 ,0x2694 , +0x2700 ,0x2708 ,0x2712 ,0x2712 ,0x2716 ,0x2716 ,0x2718 ,0x271D , +0x2724 ,0x2726 ,0x2780 ,0x2783 ,0x4000 ,0x4003 ,0x4800 ,0x4805 , +0x4900 ,0x4900 ,0x4908 ,0x4908 , + ~0 /* sentinel */ +}; + +static const unsigned int a225_registers[] = { +0x0000 ,0x0002 ,0x0004 ,0x000B ,0x003B ,0x003D ,0x0040 ,0x0044 , +0x0046 ,0x0047 ,0x013C ,0x013C ,0x0140 ,0x014F ,0x01C0 ,0x01C1 , +0x01C3 ,0x01C8 ,0x01D5 ,0x01D9 ,0x01DC ,0x01DD ,0x01EA ,0x01EA , +0x01EE ,0x01F3 ,0x01F6 ,0x01F7 ,0x01FC ,0x01FF ,0x0391 ,0x0392 , +0x039B ,0x039E ,0x03B2 ,0x03B5 ,0x03B7 ,0x03B7 ,0x03F8 ,0x03FB , +0x0440 ,0x0440 ,0x0443 ,0x0444 ,0x044B ,0x044B ,0x044D ,0x044F , +0x0452 ,0x0452 ,0x0454 ,0x045B ,0x047F ,0x047F ,0x0578 ,0x0587 , +0x05C9 ,0x05C9 ,0x05D0 ,0x05D0 ,0x0601 ,0x0604 ,0x0606 ,0x0609 , +0x060B ,0x060E ,0x0613 ,0x0614 ,0x0A29 ,0x0A2B ,0x0A2F ,0x0A31 , +0x0A40 ,0x0A40 ,0x0A42 ,0x0A43 ,0x0A45 ,0x0A45 ,0x0A4E ,0x0A4F , +0x0C01 ,0x0C1D ,0x0C30 ,0x0C30 ,0x0C38 ,0x0C39 ,0x0C3C ,0x0C3C , +0x0C80 ,0x0C81 ,0x0C88 ,0x0C93 ,0x0D00 ,0x0D03 ,0x0D05 ,0x0D06 , +0x0D08 ,0x0D0B ,0x0D34 ,0x0D35 ,0x0DAE ,0x0DC1 ,0x0DC8 ,0x0DD4 , +0x0DD8 ,0x0DD9 ,0x0E00 ,0x0E00 ,0x0E02 ,0x0E04 ,0x0E17 ,0x0E1E , +0x0EC0 ,0x0EC9 ,0x0ECB ,0x0ECC ,0x0ED0 ,0x0ED0 ,0x0ED4 ,0x0ED7 , +0x0EE0 ,0x0EE2 ,0x0F01 ,0x0F02 ,0x2000 ,0x200F ,0x2080 ,0x2082 , +0x2100 ,0x2109 ,0x210C ,0x2114 ,0x2180 ,0x2184 ,0x21F5 ,0x21F7 , +0x2200 ,0x2202 ,0x2204 ,0x2206 ,0x2208 ,0x2210 ,0x2220 ,0x2222 , +0x2280 ,0x2282 ,0x2294 ,0x2294 ,0x2297 ,0x2297 ,0x2300 ,0x230A , +0x2312 ,0x2312 ,0x2315 ,0x2316 ,0x2318 ,0x231D ,0x2324 ,0x2326 , +0x2340 ,0x2357 ,0x2360 ,0x2360 ,0x2380 ,0x2383 ,0x2400 ,0x240F , +0x2480 ,0x2482 ,0x2500 ,0x2509 ,0x250C ,0x2514 ,0x2580 ,0x2584 , +0x25F5 ,0x25F7 ,0x2600 ,0x2602 ,0x2604 ,0x2606 ,0x2608 ,0x2610 , +0x2620 ,0x2622 ,0x2680 ,0x2682 ,0x2694 ,0x2694 ,0x2697 ,0x2697 , +0x2700 ,0x270A ,0x2712 ,0x2712 ,0x2715 ,0x2716 ,0x2718 ,0x271D , +0x2724 ,0x2726 ,0x2740 ,0x2757 ,0x2760 ,0x2760 ,0x2780 ,0x2783 , +0x4000 ,0x4003 ,0x4800 ,0x4806 ,0x4808 ,0x4808 ,0x4900 ,0x4900 , +0x4908 ,0x4908 , + ~0 /* sentinel */ +}; + +/* would be nice to not have to duplicate the _show() stuff with printk(): */ +static void a2xx_dump (struct msm_gpu *gpu) +{ +printk ("status: %08x\n" , +gpu_read (gpu,REG_A2XX_RBBM_STATUS )); +adreno_dump (gpu); +} + +static struct msm_gpu_state *a2xx_gpu_state_get (struct msm_gpu *gpu) +{ +struct msm_gpu_state *state =kzalloc (sizeof (*state),GFP_KERNEL ); + +if (!state) +return ERR_PTR (-ENOMEM ); + +adreno_gpu_state_get (gpu, state); + + state->rbbm_status =gpu_read (gpu,REG_A2XX_RBBM_STATUS ); + +return state; +} + +/* Register offset defines for A2XX - copy of A3XX */ +static const unsigned int a2xx_register_offsets[REG_ADRENO_REGISTER_MAX ] = { +REG_ADRENO_DEFINE (REG_ADRENO_CP_RB_BASE ,REG_AXXX_CP_RB_BASE ), +REG_ADRENO_SKIP (REG_ADRENO_CP_RB_BASE_HI ), +REG_ADRENO_DEFINE (REG_ADRENO_CP_RB_RPTR_ADDR ,REG_AXXX_CP_RB_RPTR_ADDR ), +REG_ADRENO_SKIP (REG_ADRENO_CP_RB_RPTR_ADDR_HI ), +REG_ADRENO_DEFINE (REG_ADRENO_CP_RB_RPTR ,REG_AXXX_CP_RB_RPTR ), +REG_ADRENO_DEFINE (REG_ADRENO_CP_RB_WPTR ,REG_AXXX_CP_RB_WPTR ), +REG_ADRENO_DEFINE (REG_ADRENO_CP_RB_CNTL ,REG_AXXX_CP_RB_CNTL ), +}; + +static const struct adreno_gpu_funcs funcs = { + .base = { + .get_param = adreno_get_param, + .hw_init = a2xx_hw_init, + .pm_suspend = msm_gpu_pm_suspend, + .pm_resume = msm_gpu_pm_resume, + .recover = a2xx_recover, + .submit = adreno_submit, + .flush = adreno_flush, + .active_ring = adreno_active_ring, + .irq = a2xx_irq, + .destroy = a2xx_destroy, +#if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEV_COREDUMP) + .show = adreno_show, +#endif + .gpu_state_get = a2xx_gpu_state_get, + .gpu_state_put = adreno_gpu_state_put, + }, +}; + +static const struct msm_gpu_perfcntr perfcntrs[] = { +/* TODO */ +}; + +struct msm_gpu *a2xx_gpu_init (struct drm_device *dev) +{ +struct a2xx_gpu *a2xx_gpu =NULL ; +struct adreno_gpu *adreno_gpu; +struct msm_gpu *gpu; +struct msm_drm_private *priv = dev->dev_private; +struct platform_device *pdev = priv->gpu_pdev; +int ret; + +if (!pdev) { +dev_err (dev->dev,"no a2xx device\n" ); + ret = -ENXIO ; + goto fail; + } + + a2xx_gpu =kzalloc (sizeof (*a2xx_gpu),GFP_KERNEL ); +if (!a2xx_gpu) { + ret = -ENOMEM ; + goto fail; + } + + adreno_gpu = &a2xx_gpu->base; + gpu = &adreno_gpu->base; + + gpu->perfcntrs = perfcntrs; + gpu->num_perfcntrs =ARRAY_SIZE (perfcntrs); + +if (adreno_is_a20x (adreno_gpu)) + adreno_gpu->registers = a200_registers; +else if (adreno_is_a225 (adreno_gpu)) + adreno_gpu->registers = a225_registers; +else + adreno_gpu->registers = a220_registers; + + adreno_gpu->reg_offsets = a2xx_register_offsets; + + ret =adreno_gpu_init (dev, pdev, adreno_gpu, &funcs,1 ); +if (ret) + goto fail; + +if (!gpu->aspace) { +/* MMU is not implemented... */ +dev_err (dev->dev,"No memory protection without MMU\n" ); + } + +return gpu; + +fail: +if (a2xx_gpu) +a2xx_destroy (&a2xx_gpu->base.base); + +return ERR_PTR (ret); +}drivers/gpu/drm/msm/adreno/a2xx_gpu.h new file +21
-0@@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2018 The Linux Foundation. All rights reserved. */ + +#ifndef __A2XX_GPU_H__ +#define __A2XX_GPU_H__ + +#include "adreno_gpu.h" + +/* arrg, somehow fb.h is getting pulled in: */ +#undef ROP_COPY +#undef ROP_XOR + +#include "a2xx.xml.h" + +struct a2xx_gpu { +struct adreno_gpu base; +bool pm_enabled; +}; +#define to_a2xx_gpu (x) container_of(x, struct a2xx_gpu, base) + +#endif /* __A2XX_GPU_H__ */ drivers/gpu/drm/msm/adreno/adreno_device.c +33
-0@@ -27,6 +27,39 @@ module_param_named(hang_debug, hang_debug, bool, 0600);static const struct adreno_info gpulist[] = { { + .rev =ADRENO_REV (2 ,0 ,0 ,0 ), + .revn =200 , + .name ="A200" , + .fw = { + [ADRENO_FW_PM4 ] ="yamato_pm4.fw" , + [ADRENO_FW_PFP ] ="yamato_pfp.fw" , + }, + .gmem =SZ_256K , + .inactive_period =DRM_MSM_INACTIVE_PERIOD , + .init = a2xx_gpu_init, + }, {/* a200 on i.mx51 has only 128kib gmem */ + .rev =ADRENO_REV (2 ,0 ,0 ,1 ), + .revn =201 , + .name ="A200" , + .fw = { + [ADRENO_FW_PM4 ] ="yamato_pm4.fw" , + [ADRENO_FW_PFP ] ="yamato_pfp.fw" , + }, + .gmem =SZ_128K , + .inactive_period =DRM_MSM_INACTIVE_PERIOD , + .init = a2xx_gpu_init, + }, { + .rev =ADRENO_REV (2 ,2 ,0 ,ANY_ID ), + .revn =220 , + .name ="A220" , + .fw = { + [ADRENO_FW_PM4 ] ="leia_pm4_470.fw" , + [ADRENO_FW_PFP ] ="leia_pfp_470.fw" , + }, + .gmem =SZ_512K , + .inactive_period =DRM_MSM_INACTIVE_PERIOD , + .init = a2xx_gpu_init, + }, { .rev =ADRENO_REV (3 ,0 ,5 ,ANY_ID ), .revn =305 , .name ="A305" ,drivers/gpu/drm/msm/adreno/adreno_gpu.c +19
-8@@ -319,16 +319,27 @@ void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,*/ OUT_PKT3 (ring,CP_EVENT_WRITE ,1 );OUT_RING (ring,HLSQ_FLUSH ); - -OUT_PKT3 (ring,CP_WAIT_FOR_IDLE ,1 ); -OUT_RING (ring,0x00000000 ); } -/* BIT(31) of CACHE_FLUSH_TS triggers CACHE_FLUSH_TS IRQ from GPU */ -OUT_PKT3 (ring,CP_EVENT_WRITE ,3 ); -OUT_RING (ring,CACHE_FLUSH_TS |BIT (31 )); -OUT_RING (ring,rbmemptr (ring, fence)); -OUT_RING (ring, submit->seqno); +/* wait for idle before cache flush/interrupt */ +OUT_PKT3 (ring,CP_WAIT_FOR_IDLE ,1 ); +OUT_RING (ring,0x00000000 ); + +if (!adreno_is_a2xx (adreno_gpu)) { +/* BIT(31) of CACHE_FLUSH_TS triggers CACHE_FLUSH_TS IRQ from GPU */ +OUT_PKT3 (ring,CP_EVENT_WRITE ,3 ); +OUT_RING (ring,CACHE_FLUSH_TS |BIT (31 )); +OUT_RING (ring,rbmemptr (ring, fence)); +OUT_RING (ring, submit->seqno); + }else { +/* BIT(31) means something else on a2xx */ +OUT_PKT3 (ring,CP_EVENT_WRITE ,3 ); +OUT_RING (ring,CACHE_FLUSH_TS ); +OUT_RING (ring,rbmemptr (ring, fence)); +OUT_RING (ring, submit->seqno); +OUT_PKT3 (ring,CP_INTERRUPT ,1 ); +OUT_RING (ring,0x80000000 ); + }#if 0 if (adreno_is_a3xx (adreno_gpu)) {drivers/gpu/drm/msm/adreno/adreno_gpu.h +15
-0@@ -154,6 +154,20 @@ struct adreno_platform_config { __ret; \ }) +static inline bool adreno_is_a2xx (struct adreno_gpu *gpu) +{ +return (gpu->revn <300 ); +} + +static inline bool adreno_is_a20x (struct adreno_gpu *gpu) +{ +return (gpu->revn <210 ); +} + +static inline bool adreno_is_a225 (struct adreno_gpu *gpu) +{ +return gpu->revn ==225 ; +}static inline bool adreno_is_a3xx (struct adreno_gpu *gpu) {@@ -334,6 +348,7 @@ static inline void adreno_gpu_write(struct adreno_gpu *gpu,gpu_write (&gpu->base, reg -1 , data); } +struct msm_gpu *a2xx_gpu_init (struct drm_device *dev);struct msm_gpu *a3xx_gpu_init (struct drm_device *dev);struct msm_gpu *a4xx_gpu_init (struct drm_device *dev);struct msm_gpu *a5xx_gpu_init (struct drm_device *dev);Signature · 1 line
2.17.1
Signature · 6 lines
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project _______________________________________________ Freedreno mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/freedreno
PATCH 7/9 drm/msm: implement a2xx mmu
In reply to Jonathan MarekA2XX has its own very simple MMU.
Added a msm_use_mmu() function because we can't rely on iommu_present to decide to use MMU or not.
--- drivers/gpu/drm/msm/Makefile | 3 +- drivers/gpu/drm/msm/adreno/a2xx_gpu.c | 57 +++++++++-- drivers/gpu/drm/msm/adreno/adreno_device.c | 3 + drivers/gpu/drm/msm/adreno/adreno_gpu.c | 15 +++ drivers/gpu/drm/msm/msm_drv.c | 11 +- drivers/gpu/drm/msm/msm_drv.h | 8 ++ drivers/gpu/drm/msm/msm_gem.c | 4 +- drivers/gpu/drm/msm/msm_gem_vma.c | 23 +++++ drivers/gpu/drm/msm/msm_gpu.c | 26 +++-- drivers/gpu/drm/msm/msm_gpummu.c | 113 +++++++++++++++++++++ drivers/gpu/drm/msm/msm_mmu.h | 3 + 11 files changed, 243 insertions(+), 23 deletions(-) create mode 100644 drivers/gpu/drm/msm/msm_gpummu.c
drivers/gpu/drm/msm/Makefile +2 -1
@@ -91,7 +91,8 @@ msm-y := \ msm_perf.o \ msm_rd.o \ msm_ringbuffer.o \ - msm_submitqueue.o + msm_submitqueue.o \ + msm_gpummu.o msm-$(CONFIG_DEBUG_FS) += adreno/a5xx_debugfs.o \ disp/dpu1/dpu_dbg.o
drivers/gpu/drm/msm/adreno/a2xx_gpu.c +47 -10
104 lines not on this page · raw message
drivers/gpu/drm/msm/adreno/adreno_device.c +3 -0
@@ -307,6 +307,7 @@ static int adreno_bind(struct device *dev, struct device *master, void *data)static struct adreno_platform_config config = {};const struct adreno_info *info;struct drm_device *drm =dev_get_drvdata (master); +struct msm_drm_private *priv = drm->dev_private;struct msm_gpu *gpu;int ret;
@@ -337,6 +338,8 @@ static int adreno_bind(struct device *dev, struct device *master, void *data)dev_set_drvdata (dev, gpu); + priv->is_a2xx = config.rev.core ==2 ; +return 0 ; }
drivers/gpu/drm/msm/adreno/adreno_gpu.c +15 -0
@@ -24,6 +24,7 @@#include "adreno_gpu.h" #include "msm_gem.h" #include "msm_mmu.h" +#include "a2xx_gpu.h" int adreno_get_param (struct msm_gpu *gpu,uint32_t param,uint64_t *value) {
@@ -290,6 +291,17 @@ void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,struct msm_ringbuffer *ring = submit->ring;unsigned i; +if (adreno_is_a2xx (adreno_gpu)) { +/* tlb flush for a2xx MMU. TODO: only do this when required */ +OUT_PKT3 (ring,CP_SET_PROTECTED_MODE ,1 ); +OUT_RING (ring,0 ); +OUT_PKT0 (ring,REG_A2XX_MH_MMU_INVALIDATE ,1 ); +OUT_RING (ring,A2XX_MH_MMU_INVALIDATE_INVALIDATE_ALL | +A2XX_MH_MMU_INVALIDATE_INVALIDATE_TC ); +OUT_PKT3 (ring,CP_SET_PROTECTED_MODE ,1 ); +OUT_RING (ring,1 ); + } +for (i =0 ; i < submit->nr_cmds; i++) {switch (submit->cmd[i].type) {case MSM_SUBMIT_CMD_IB_TARGET_BUF :
@@ -728,6 +740,9 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, adreno_gpu_config.va_start =SZ_16M ; adreno_gpu_config.va_end =0xffffffff ; +/* maximum range of a2xx mmu */ +if (adreno_is_a2xx (adreno_gpu)) + adreno_gpu_config.va_end =SZ_16M +0xfff *SZ_64K ; adreno_gpu_config.nr_rings = nr_rings;
drivers/gpu/drm/msm/msm_drv.c +10 -1
@@ -25,6 +25,7 @@#include "msm_fence.h" #include "msm_gpu.h" #include "msm_kms.h" +#include "adreno/adreno_gpu.h" /*
@@ -358,6 +359,14 @@ static int get_mdp_ver(struct platform_device *pdev)#include <linux/of_address.h> +bool msm_use_mmu (struct drm_device *dev) +{ +struct msm_drm_private *priv = dev->dev_private; + +/* a2xx comes with its own MMU */ +return priv->is_a2xx ||iommu_present (&platform_bus_type); +} +static int msm_init_vram (struct drm_device *dev) {struct msm_drm_private *priv = dev->dev_private;
@@ -396,7 +405,7 @@ static int msm_init_vram(struct drm_device *dev)* Grab the entire CMA chunk carved out in early startup in * mach-msm: */ - }else if (!iommu_present (&platform_bus_type)) { + }else if (!msm_use_mmu (dev)) {DRM_INFO ("using %s VRAM carveout\n" , vram); size =memparse (vram,NULL ); }
drivers/gpu/drm/msm/msm_drv.h +8 -0
@@ -179,6 +179,8 @@ struct msm_drm_private {/* when we have more than one 'msm_gpu' these need to be an array: */ struct msm_gpu *gpu;struct msm_file_private *lastctx; +/* gpu is only set on open(), but we need this info earlier */ +bool is_a2xx;struct drm_fb_helper *fbdev;
@@ -252,9 +254,15 @@ struct msm_gem_address_space * msm_gem_address_space_create(struct device *dev, struct iommu_domain *domain, const char *name); +struct msm_gem_address_space * +msm_gem_address_space_create_a2xx (struct device *dev,struct msm_gpu *gpu, +const char *name,uint64_t va_start,uint64_t va_end); +int msm_register_mmu (struct drm_device *dev,struct msm_mmu *mmu);void msm_unregister_mmu (struct drm_device *dev,struct msm_mmu *mmu); +bool msm_use_mmu (struct drm_device *dev); +void msm_gem_submit_free (struct msm_gem_submit *submit);int msm_ioctl_gem_submit (struct drm_device *dev,void *data,struct drm_file *file);
drivers/gpu/drm/msm/msm_gem.c +2 -2
@@ -912,7 +912,7 @@ static struct drm_gem_object *_msm_gem_new(struct drm_device *dev, size =PAGE_ALIGN (size); -if (!iommu_present (&platform_bus_type)) +if (!msm_use_mmu (dev)) use_vram = true;else if ((flags & (MSM_BO_STOLEN |MSM_BO_SCANOUT )) && priv->vram.size) use_vram = true;
@@ -991,7 +991,7 @@ struct drm_gem_object *msm_gem_import(struct drm_device *dev,int ret, npages;/* if we don't have IOMMU, don't bother pretending we can import: */ -if (!iommu_present (&platform_bus_type)) { +if (!msm_use_mmu (dev)) {dev_err (dev->dev,"cannot import without IOMMU\n" );return ERR_PTR (-EINVAL ); }
drivers/gpu/drm/msm/msm_gem_vma.c +23 -0
@@ -114,3 +114,26 @@ msm_gem_address_space_create(struct device *dev, struct iommu_domain *domain,return aspace; } + +struct msm_gem_address_space * +msm_gem_address_space_create_a2xx (struct device *dev,struct msm_gpu *gpu, +const char *name,uint64_t va_start,uint64_t va_end) +{ +struct msm_gem_address_space *aspace; +u64 size = va_end - va_start; + + aspace =kzalloc (sizeof (*aspace),GFP_KERNEL ); +if (!aspace) +return ERR_PTR (-ENOMEM ); + +spin_lock_init (&aspace->lock); + aspace->name = name; + aspace->mmu =msm_gpummu_new (dev, gpu); + +drm_mm_init (&aspace->mm, (va_start >>PAGE_SHIFT ), + size >>PAGE_SHIFT ); + +kref_init (&aspace->kref); + +return aspace; +}
drivers/gpu/drm/msm/msm_gpu.c +17 -9
@@ -19,6 +19,7 @@#include "msm_gem.h" #include "msm_mmu.h" #include "msm_fence.h" +#include "adreno/adreno_gpu.h" #include <generated/utsrelease.h> #include <linux/string_helpers.h>
@@ -800,7 +801,7 @@ static struct msm_gem_address_space * msm_gpu_create_address_space(struct msm_gpu *gpu, struct platform_device *pdev, uint64_t va_start, uint64_t va_end) { - struct iommu_domain *iommu; + struct iommu_domain *iommu = NULL;struct msm_gem_address_space *aspace;int ret;
@@ -809,20 +810,27 @@ msm_gpu_create_address_space(struct msm_gpu *gpu, struct platform_device *pdev,* and have separate page tables per context. For now, to keep things * simple and to get something working, just use a single address space: */ - iommu =iommu_domain_alloc (&platform_bus_type); -if (!iommu) -return NULL ; +if (!adreno_is_a2xx (to_adreno_gpu (gpu))) { + iommu =iommu_domain_alloc (&platform_bus_type); +if (!iommu) +return NULL ; - iommu->geometry.aperture_start = va_start; - iommu->geometry.aperture_end = va_end; + iommu->geometry.aperture_start = va_start; + iommu->geometry.aperture_end = va_end; -dev_info (gpu->dev->dev,"%s: using IOMMU\n" , gpu->name); +dev_info (gpu->dev->dev,"%s: using IOMMU\n" , gpu->name); + + aspace =msm_gem_address_space_create (&pdev->dev, iommu,"gpu" ); + }else { + aspace =msm_gem_address_space_create_a2xx (&pdev->dev, gpu,"gpu" , + va_start, va_end); + } - aspace =msm_gem_address_space_create (&pdev->dev, iommu,"gpu" );if (IS_ERR (aspace)) {dev_err (gpu->dev->dev,"failed to init iommu: %ld\n" ,PTR_ERR (aspace)); -iommu_domain_free (iommu); +if (iommu) +iommu_domain_free (iommu);return ERR_CAST (aspace); }
drivers/gpu/drm/msm/msm_gpummu.c new file +113 -0
113 lines not on this page · raw message
drivers/gpu/drm/msm/msm_mmu.h +3 -0
@@ -54,4 +54,7 @@ static inline void msm_mmu_set_fault_handler(struct msm_mmu *mmu, void *arg, mmu->handler = handler; } +void msm_gpummu_params (struct msm_mmu *mmu,dma_addr_t *pt_base, +dma_addr_t *tran_error); +#endif /* __MSM_MMU_H__ */
Signature · 1 line
2.17.1
Re: [PATCH 7/9] drm/msm: implement a2xx mmu
thanks, it's nice to see a2xx getting some attention upstream.. few comments inline..
Quoted 124 lines · Jonathan Marek
A2XX has its own very simple MMU.
Added a
msm_use_mmu()function because we can't rely oniommu_presentto decide to use MMU or not.Signed-off-by Jonathan Marek <[email protected]>--- drivers/gpu/drm/msm/Makefile | 3 +- drivers/gpu/drm/msm/adreno/a2xx_gpu.c | 57 +++++++++-- drivers/gpu/drm/msm/adreno/adreno_device.c | 3 + drivers/gpu/drm/msm/adreno/adreno_gpu.c | 15 +++ drivers/gpu/drm/msm/msm_drv.c | 11 +- drivers/gpu/drm/msm/msm_drv.h | 8 ++ drivers/gpu/drm/msm/msm_gem.c | 4 +- drivers/gpu/drm/msm/msm_gem_vma.c | 23 +++++ drivers/gpu/drm/msm/msm_gpu.c | 26 +++-- drivers/gpu/drm/msm/msm_gpummu.c | 113 +++++++++++++++++++++ drivers/gpu/drm/msm/msm_mmu.h | 3 + 11 files changed, 243 insertions(+), 23 deletions(-) create mode 100644 drivers/gpu/drm/msm/msm_gpummu.cdrivers/gpu/drm/msm/Makefile +2
-1@@ -91,7 +91,8 @@ msm-y := \ msm_perf.o \ msm_rd.o \ msm_ringbuffer.o \ - msm_submitqueue.o + msm_submitqueue.o \ + msm_gpummu.o msm-$(CONFIG_DEBUG_FS) += adreno/a5xx_debugfs.o \ disp/dpu1/dpu_dbg.odrivers/gpu/drm/msm/adreno/a2xx_gpu.c +46
-4@@ -2,6 +2,8 @@/* Copyright (c) 2018 The Linux Foundation. All rights reserved. */ #include "a2xx_gpu.h" +#include "msm_gem.h" +#include "msm_mmu.h" extern bool hang_debug;@@ -58,9 +60,12 @@ static bool a2xx_me_init(struct msm_gpu *gpu)static int a2xx_hw_init (struct msm_gpu *gpu) {struct adreno_gpu *adreno_gpu =to_adreno_gpu (gpu); +dma_addr_t pt_base, tran_error;uint32_t *ptr, len;int i, ret; +msm_gpummu_params (gpu->aspace->mmu, &pt_base, &tran_error); +DBG ("%s" , gpu->name);gpu_write (gpu,REG_A2XX_RBBM_PM_OVERRIDE1 ,0xfffffffe );@@ -77,9 +82,34 @@ static int a2xx_hw_init(struct msm_gpu *gpu)/* XXX kgsl uses 0x0000ffff for a20x */ gpu_write (gpu,REG_A2XX_RBBM_CNTL ,0x00004442 ); -gpu_write (gpu,REG_A2XX_MH_MMU_CONFIG ,0 ); -gpu_write (gpu,REG_A2XX_MH_MMU_MPU_BASE ,0 ); +/* MPU: physical range */ +gpu_write (gpu,REG_A2XX_MH_MMU_MPU_BASE ,0x00000000 );gpu_write (gpu,REG_A2XX_MH_MMU_MPU_END ,0xfffff000 ); + +gpu_write (gpu,REG_A2XX_MH_MMU_CONFIG ,A2XX_MH_MMU_CONFIG_MMU_ENABLE | +A2XX_MH_MMU_CONFIG_RB_W_CLNT_BEHAVIOR (BEH_TRAN_RNG ) | +A2XX_MH_MMU_CONFIG_CP_W_CLNT_BEHAVIOR (BEH_TRAN_RNG ) | +A2XX_MH_MMU_CONFIG_CP_R0_CLNT_BEHAVIOR (BEH_TRAN_RNG ) | +A2XX_MH_MMU_CONFIG_CP_R1_CLNT_BEHAVIOR (BEH_TRAN_RNG ) | +A2XX_MH_MMU_CONFIG_CP_R2_CLNT_BEHAVIOR (BEH_TRAN_RNG ) | +A2XX_MH_MMU_CONFIG_CP_R3_CLNT_BEHAVIOR (BEH_TRAN_RNG ) | +A2XX_MH_MMU_CONFIG_CP_R4_CLNT_BEHAVIOR (BEH_TRAN_RNG ) | +A2XX_MH_MMU_CONFIG_VGT_R0_CLNT_BEHAVIOR (BEH_TRAN_RNG ) | +A2XX_MH_MMU_CONFIG_VGT_R1_CLNT_BEHAVIOR (BEH_TRAN_RNG ) | +A2XX_MH_MMU_CONFIG_TC_R_CLNT_BEHAVIOR (BEH_TRAN_RNG ) | +A2XX_MH_MMU_CONFIG_PA_W_CLNT_BEHAVIOR (BEH_TRAN_RNG )); + +/* same as parameters in adreno_gpu */ +gpu_write (gpu,REG_A2XX_MH_MMU_VA_RANGE ,SZ_16M | +A2XX_MH_MMU_VA_RANGE_NUM_64KB_REGIONS (0xfff )); + +gpu_write (gpu,REG_A2XX_MH_MMU_PT_BASE , pt_base); +gpu_write (gpu,REG_A2XX_MH_MMU_TRAN_ERROR , tran_error); + +gpu_write (gpu,REG_A2XX_MH_MMU_INVALIDATE , +A2XX_MH_MMU_INVALIDATE_INVALIDATE_ALL | +A2XX_MH_MMU_INVALIDATE_INVALIDATE_TC ); + gpu_write(gpu, REG_A2XX_MH_ARBITER_CONFIG, A2XX_MH_ARBITER_CONFIG_SAME_PAGE_LIMIT(16) | A2XX_MH_ARBITER_CONFIG_L1_ARB_ENABLE |@@ -106,9 +136,21 @@ static int a2xx_hw_init(struct msm_gpu *gpu)/* XXX gsl doesn't set this */ gpu_write (gpu,REG_A2XX_RBBM_DEBUG ,0x00080000 ); -gpu_write (gpu,REG_A2XX_RBBM_INT_CNTL ,0 ); -gpu_write (gpu,REG_AXXX_CP_INT_CNTL ,0x80000000 );/* RB INT */ +gpu_write (gpu,REG_A2XX_RBBM_INT_CNTL , +A2XX_RBBM_INT_CNTL_RDERR_INT_MASK ); +gpu_write (gpu,REG_AXXX_CP_INT_CNTL , +AXXX_CP_INT_CNTL_T0_PACKET_IN_IB_MASK | +AXXX_CP_INT_CNTL_OPCODE_ERROR_MASK | +AXXX_CP_INT_CNTL_PROTECTED_MODE_ERROR_MASK | +AXXX_CP_INT_CNTL_RESERVED_BIT_ERROR_MASK | +AXXX_CP_INT_CNTL_IB_ERROR_MASK | +AXXX_CP_INT_CNTL_IB1_INT_MASK | +AXXX_CP_INT_CNTL_RB_INT_MASK );gpu_write (gpu,REG_A2XX_SQ_INT_CNTL ,0 ); +gpu_write (gpu,REG_A2XX_MH_INTERRUPT_MASK , +A2XX_MH_INTERRUPT_MASK_AXI_READ_ERROR | +A2XX_MH_INTERRUPT_MASK_AXI_WRITE_ERROR | +A2XX_MH_INTERRUPT_MASK_MMU_PAGE_FAULT );for (i =3 ; i <=5 ; i++)if ((SZ_16K << i) == adreno_gpu->gmem)
drivers/gpu/drm/msm/adreno/a2xx_gpu.c static bool a2xx_idle(struct msm_gpu *gpu) · line 208
Quoted 4 lines
drivers/gpu/drm/msm/adreno/a2xx_gpu.c +0
-1@@ -205,7 +247,6 @@ static bool a2xx_idle(struct msm_gpu *gpu)static irqreturn_t a2xx_irq (struct msm_gpu *gpu) { -
could you fold this whitespace change back into the patch that adds this?
Quoted 12 lines
drivers/gpu/drm/msm/adreno/a2xx_gpu.c +1
-0uint32_t mstatus, status; mstatus =gpu_read (gpu,REG_A2XX_MASTER_INT_SIGNAL );@@ -216,6 +257,7 @@ static irqreturn_t a2xx_irq(struct msm_gpu *gpu)dev_warn (gpu->dev->dev,"MH_INT: %08X\n" , status);dev_warn (gpu->dev->dev,"MMU_PAGE_FAULT: %08X\n" ,gpu_read (gpu,REG_A2XX_MH_MMU_PAGE_FAULT )); +gpu_write (gpu,REG_A2XX_MH_INTERRUPT_CLEAR , status); }
drivers/gpu/drm/msm/adreno/a2xx_gpu.c struct msm_gpu *a2xx_gpu_init(struct drm_device *dev) · line 437
Quoted 8 lines
drivers/gpu/drm/msm/adreno/a2xx_gpu.c +0
-5@@ -430,11 +472,6 @@ struct msm_gpu *a2xx_gpu_init(struct drm_device *dev)if (ret) goto fail; -if (!gpu->aspace) { -/* MMU is not implemented... */ -dev_err (dev->dev,"No memory protection without MMU\n" ); - } -
hmm, could mmu init still fail? I guess it looks like it does not need to request any additional clks/etc. And hopefully there is nothing out there with a non-functional gpummu?
Quoted 39 lines
drivers/gpu/drm/msm/adreno/a2xx_gpu.c +0
-0return gpu; fail:drivers/gpu/drm/msm/adreno/adreno_device.c +3
-0@@ -307,6 +307,7 @@ static int adreno_bind(struct device *dev, struct device *master, void *data)static struct adreno_platform_config config = {};const struct adreno_info *info;struct drm_device *drm =dev_get_drvdata (master); +struct msm_drm_private *priv = drm->dev_private;struct msm_gpu *gpu;int ret;@@ -337,6 +338,8 @@ static int adreno_bind(struct device *dev, struct device *master, void *data)dev_set_drvdata (dev, gpu); + priv->is_a2xx = config.rev.core ==2 ; +return 0 ; }drivers/gpu/drm/msm/adreno/adreno_gpu.c +1
-0@@ -24,6 +24,7 @@#include "adreno_gpu.h" #include "msm_gem.h" #include "msm_mmu.h" +#include "a2xx_gpu.h" int adreno_get_param (struct msm_gpu *gpu,uint32_t param,uint64_t *value) {@@ -290,6 +291,17 @@ void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,struct msm_ringbuffer *ring = submit->ring;unsigned i;
drivers/gpu/drm/msm/adreno/adreno_gpu.c void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, · line 302
Quoted 10 lines
drivers/gpu/drm/msm/adreno/adreno_gpu.c +9
-0+if (adreno_is_a2xx (adreno_gpu)) { +/* tlb flush for a2xx MMU. TODO: only do this when required */ +OUT_PKT3 (ring,CP_SET_PROTECTED_MODE ,1 ); +OUT_RING (ring,0 ); +OUT_PKT0 (ring,REG_A2XX_MH_MMU_INVALIDATE ,1 ); +OUT_RING (ring,A2XX_MH_MMU_INVALIDATE_INVALIDATE_ALL | +A2XX_MH_MMU_INVALIDATE_INVALIDATE_TC ); +OUT_PKT3 (ring,CP_SET_PROTECTED_MODE ,1 ); +OUT_RING (ring,1 );
can we only invalidate from the ring? If so, defn keeping a flag about whether inv needed would be a good idea. Userspace tries to use a bo_cache[1] to re-use already mapped buffers, so I'd expect in steady-state this wouldn't be needed on every submit.
[1] actually two of them, a separate bo cache is used for things that get vmap'd on kernel side
Quoted 28 lines
drivers/gpu/drm/msm/adreno/adreno_gpu.c +5
-0+ } +for (i =0 ; i < submit->nr_cmds; i++) {switch (submit->cmd[i].type) {case MSM_SUBMIT_CMD_IB_TARGET_BUF :@@ -728,6 +740,9 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, adreno_gpu_config.va_start =SZ_16M ; adreno_gpu_config.va_end =0xffffffff ; +/* maximum range of a2xx mmu */ +if (adreno_is_a2xx (adreno_gpu)) + adreno_gpu_config.va_end =SZ_16M +0xfff *SZ_64K ; adreno_gpu_config.nr_rings = nr_rings;drivers/gpu/drm/msm/msm_drv.c +1
-0@@ -25,6 +25,7 @@#include "msm_fence.h" #include "msm_gpu.h" #include "msm_kms.h" +#include "adreno/adreno_gpu.h" /*
drivers/gpu/drm/msm/msm_drv.c static int get_mdp_ver(struct platform_device *pdev) · line 367
Quoted 9 lines
drivers/gpu/drm/msm/msm_drv.c +6
-0@@ -358,6 +359,14 @@ static int get_mdp_ver(struct platform_device *pdev)#include <linux/of_address.h> +bool msm_use_mmu (struct drm_device *dev) +{ +struct msm_drm_private *priv = dev->dev_private; + +/* a2xx comes with its own MMU */ +return priv->is_a2xx ||iommu_present (&platform_bus_type);
tbh, iommu_present(bus) is not even really sufficient for other devices where some platform devices have iommu and other do not but I guess this is the best we can do at this point :-(
Quoted 140 lines
drivers/gpu/drm/msm/msm_drv.c +3
-1+} +static int msm_init_vram (struct drm_device *dev) {struct msm_drm_private *priv = dev->dev_private;@@ -396,7 +405,7 @@ static int msm_init_vram(struct drm_device *dev)* Grab the entire CMA chunk carved out in early startup in * mach-msm: */ - }else if (!iommu_present (&platform_bus_type)) { + }else if (!msm_use_mmu (dev)) {DRM_INFO ("using %s VRAM carveout\n" , vram); size =memparse (vram,NULL ); }drivers/gpu/drm/msm/msm_drv.h +8
-0@@ -179,6 +179,8 @@ struct msm_drm_private {/* when we have more than one 'msm_gpu' these need to be an array: */ struct msm_gpu *gpu;struct msm_file_private *lastctx; +/* gpu is only set on open(), but we need this info earlier */ +bool is_a2xx;struct drm_fb_helper *fbdev;@@ -252,9 +254,15 @@ struct msm_gem_address_space * msm_gem_address_space_create(struct device *dev, struct iommu_domain *domain, const char *name); +struct msm_gem_address_space * +msm_gem_address_space_create_a2xx (struct device *dev,struct msm_gpu *gpu, +const char *name,uint64_t va_start,uint64_t va_end); +int msm_register_mmu (struct drm_device *dev,struct msm_mmu *mmu);void msm_unregister_mmu (struct drm_device *dev,struct msm_mmu *mmu); +bool msm_use_mmu (struct drm_device *dev); +void msm_gem_submit_free (struct msm_gem_submit *submit);int msm_ioctl_gem_submit (struct drm_device *dev,void *data,struct drm_file *file);drivers/gpu/drm/msm/msm_gem.c +2
-2@@ -912,7 +912,7 @@ static struct drm_gem_object *_msm_gem_new(struct drm_device *dev, size =PAGE_ALIGN (size); -if (!iommu_present (&platform_bus_type)) +if (!msm_use_mmu (dev)) use_vram = true;else if ((flags & (MSM_BO_STOLEN |MSM_BO_SCANOUT )) && priv->vram.size) use_vram = true;@@ -991,7 +991,7 @@ struct drm_gem_object *msm_gem_import(struct drm_device *dev,int ret, npages;/* if we don't have IOMMU, don't bother pretending we can import: */ -if (!iommu_present (&platform_bus_type)) { +if (!msm_use_mmu (dev)) {dev_err (dev->dev,"cannot import without IOMMU\n" );return ERR_PTR (-EINVAL ); }drivers/gpu/drm/msm/msm_gem_vma.c +23
-0@@ -114,3 +114,26 @@ msm_gem_address_space_create(struct device *dev, struct iommu_domain *domain,return aspace; } + +struct msm_gem_address_space * +msm_gem_address_space_create_a2xx (struct device *dev,struct msm_gpu *gpu, +const char *name,uint64_t va_start,uint64_t va_end) +{ +struct msm_gem_address_space *aspace; +u64 size = va_end - va_start; + + aspace =kzalloc (sizeof (*aspace),GFP_KERNEL ); +if (!aspace) +return ERR_PTR (-ENOMEM ); + +spin_lock_init (&aspace->lock); + aspace->name = name; + aspace->mmu =msm_gpummu_new (dev, gpu); + +drm_mm_init (&aspace->mm, (va_start >>PAGE_SHIFT ), + size >>PAGE_SHIFT ); + +kref_init (&aspace->kref); + +return aspace; +}drivers/gpu/drm/msm/msm_gpu.c +13
-7@@ -19,6 +19,7 @@#include "msm_gem.h" #include "msm_mmu.h" #include "msm_fence.h" +#include "adreno/adreno_gpu.h" #include <generated/utsrelease.h> #include <linux/string_helpers.h> @@ -800,7 +801,7 @@ static struct msm_gem_address_space * msm_gpu_create_address_space(struct msm_gpu *gpu, struct platform_device *pdev, uint64_t va_start, uint64_t va_end) { - struct iommu_domain *iommu; + struct iommu_domain *iommu = NULL;struct msm_gem_address_space *aspace;int ret;@@ -809,20 +810,27 @@ msm_gpu_create_address_space(struct msm_gpu *gpu, struct platform_device *pdev,* and have separate page tables per context. For now, to keep things * simple and to get something working, just use a single address space: */ - iommu =iommu_domain_alloc (&platform_bus_type); -if (!iommu) -return NULL ; +if (!adreno_is_a2xx (to_adreno_gpu (gpu))) { + iommu =iommu_domain_alloc (&platform_bus_type); +if (!iommu) +return NULL ; - iommu->geometry.aperture_start = va_start; - iommu->geometry.aperture_end = va_end; + iommu->geometry.aperture_start = va_start; + iommu->geometry.aperture_end = va_end; -dev_info (gpu->dev->dev,"%s: using IOMMU\n" , gpu->name); +dev_info (gpu->dev->dev,"%s: using IOMMU\n" , gpu->name); + + aspace =msm_gem_address_space_create (&pdev->dev, iommu,"gpu" ); + }else { + aspace = msm_gem_address_space_create_a2xx(&pdev->dev, gpu, "gpu",
drivers/gpu/drm/msm/msm_gpu.c msm_gpu_create_address_space(struct msm_gpu *gpu, struct platform_device *pdev, · line 833
Quoted 10 lines
drivers/gpu/drm/msm/msm_gpu.c +4
-2+ va_start, va_end); + } - aspace =msm_gem_address_space_create (&pdev->dev, iommu,"gpu" );if (IS_ERR (aspace)) {dev_err (gpu->dev->dev,"failed to init iommu: %ld\n" ,PTR_ERR (aspace)); -iommu_domain_free (iommu); +if (iommu) +iommu_domain_free (iommu);
minor nit, maybe just move iommu and the iommu_domain_free() into the if(!a2xx) case?
Quoted 62 lines
drivers/gpu/drm/msm/msm_gpu.c +0
-0return ERR_CAST (aspace); }drivers/gpu/drm/msm/msm_gpummu.c new file +53
-0@@ -0,0 +1,113 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2018 The Linux Foundation. All rights reserved. */ + +#include "msm_drv.h" +#include "msm_mmu.h" + +struct msm_gpummu { +struct msm_mmu base; +struct msm_gpu *gpu; +dma_addr_t pt_base; +uint32_t *table; +}; +#define to_msm_gpummu (x) container_of(x, struct msm_gpummu, base) + +#define VA_START SZ_16M +#define VA_RANGE (0xfff * SZ_64K) +#define MMU_PAGE_SIZE SZ_4K +#define TABLE_SIZE (sizeof(uint32_t) * VA_RANGE / MMU_PAGE_SIZE) + +static int msm_gpummu_attach (struct msm_mmu *mmu,const char *const *names, +int cnt) +{ +return 0 ; +} + +static void msm_gpummu_detach (struct msm_mmu *mmu,const char *const *names, +int cnt) +{ +} + +static void update_pt (struct msm_mmu *mmu,uint64_t iova, +struct sg_table *sgt,unsigned len,unsigned prot) +{ +struct msm_gpummu *gpummu =to_msm_gpummu (mmu); +unsigned idx = (iova -VA_START ) /MMU_PAGE_SIZE ; +struct scatterlist *sg; +unsigned i, j; + +for_each_sg (sgt->sgl, sg, sgt->nents, i) { +dma_addr_t addr = sg->dma_address; +for (j =0 ; j < sg->length /MMU_PAGE_SIZE ; j++, idx++) { + gpummu->table[idx] = prot ? addr | prot :0 ; + addr +=MMU_PAGE_SIZE ; + } + } +} + +static int msm_gpummu_map (struct msm_mmu *mmu,uint64_t iova, +struct sg_table *sgt,unsigned len,int prot) +{ +unsigned prot_bits =0 ; +if (prot &IOMMU_WRITE ) + prot_bits |=1 ;
drivers/gpu/drm/msm/msm_gpummu.c line 63
Quoted 10 lines
drivers/gpu/drm/msm/msm_gpummu.c new file +10
-0+if (prot &IOMMU_READ ) + prot_bits |=2 ; +update_pt (mmu, iova, sgt, len, prot_bits); +return 0 ; +} + +static int msm_gpummu_unmap (struct msm_mmu *mmu,uint64_t iova, +struct sg_table *sgt,unsigned len) +{ +update_pt (mmu, iova, sgt, len,0 );
so one thing I'm a bit concerned about is tlb flush on unmap not happening until the next submit, while meanwhile we've returned the buffer's pages to the OS. If we can trigger tlb inv from CPU, then it is probably a good idea to do so for unmap. (But map is fine to defer.)
If we can't tlb inv from the CPU then maybe we need to keep a list of bo's to defer freeing the pages.
Otherwise this looks fine to me.
BR,
-R
Side note: I have kinda wanted to do something similar for a while for the IOMMU case, and teach the IOMMU about deferred TLB flush.. since the common usage pattern is to map N bo's that we haven't used before in the submit ioctl, and unmap/free M buffers from retire_worker. For a2xx and older iommu's (which had to inv on map) batching the mapping and doing a single inv seems like a win. And for everyone keeping a list of "zombie" bo's which are unmapped but waiting to be free'd until tlb inv, could let us back multiple unmaps and do a single tlb inv.
Quoted 63 lines
drivers/gpu/drm/msm/msm_gpummu.c new file +50
-0+return 0 ; +} + +static void msm_gpummu_destroy (struct msm_mmu *mmu) +{ +struct msm_gpummu *gpummu =to_msm_gpummu (mmu); + +dma_free_attrs (mmu->dev,TABLE_SIZE , gpummu->table, gpummu->pt_base, +DMA_ATTR_FORCE_CONTIGUOUS ); + +kfree (gpummu); +} + +static const struct msm_mmu_funcs funcs = { + .attach = msm_gpummu_attach, + .detach = msm_gpummu_detach, + .map = msm_gpummu_map, + .unmap = msm_gpummu_unmap, + .destroy = msm_gpummu_destroy, +}; + +struct msm_mmu *msm_gpummu_new (struct device *dev,struct msm_gpu *gpu) +{ +struct msm_gpummu *gpummu; + + gpummu =kzalloc (sizeof (*gpummu),GFP_KERNEL ); +if (!gpummu) +return ERR_PTR (-ENOMEM ); + + gpummu->table =dma_alloc_attrs (dev,TABLE_SIZE +32 , &gpummu->pt_base, +GFP_KERNEL | __GFP_ZERO,DMA_ATTR_FORCE_CONTIGUOUS ); +if (!gpummu->table) { +kfree (gpummu); +return ERR_PTR (-ENOMEM ); + } + + gpummu->gpu = gpu; +msm_mmu_init (&gpummu->base, dev, &funcs); + +return &gpummu->base; +} + +void msm_gpummu_params (struct msm_mmu *mmu,dma_addr_t *pt_base, +dma_addr_t *tran_error) +{ +dma_addr_t base =to_msm_gpummu (mmu)->pt_base; + + *pt_base = base; + *tran_error = base +TABLE_SIZE ;/* 32-byte aligned */ +}drivers/gpu/drm/msm/msm_mmu.h +3
-1@@ -54,4 +54,7 @@ static inline void msm_mmu_set_fault_handler(struct msm_mmu *mmu, void *arg, mmu->handler = handler; } +void msm_gpummu_params (struct msm_mmu *mmu,dma_addr_t *pt_base, +dma_addr_t *tran_error); +#endif /* __MSM_MMU_H__ */ --
Quoted 2 lines
2.17.1
_______________________________________________
Freedreno mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/freedreno
PATCH 8/9 drm/msm/mdp5: add config for msm8917
In reply to Jonathan MarekAdd the mdp5_cfg_hw entry for MDP5 version v1.15 found on msm8917.
--- drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c | 86 ++++++++++++++++++++++++ 1 file changed, 86 insertions(+)
drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c +86 -0
@@ -553,6 +553,91 @@ const struct mdp5_cfg_hw msm8x96_config = { .max_clk = 412500000, }; +const struct mdp5_cfg_hw msm8917_config = { + .name ="msm8917" , + .mdp = { + .count =1 , + .caps =MDP_CAP_CDM , + }, + .ctl = { + .count =3 , + .base = {0x01000 ,0x01200 ,0x01400 }, + .flush_hw_mask =0xffffffff , + }, + .pipe_vig = { + .count =1 , + .base = {0x04000 }, + .caps =MDP_PIPE_CAP_HFLIP | +MDP_PIPE_CAP_VFLIP | +MDP_PIPE_CAP_SCALE | +MDP_PIPE_CAP_CSC | +MDP_PIPE_CAP_DECIMATION | +MDP_PIPE_CAP_SW_PIX_EXT | +0 , + }, + .pipe_rgb = { + .count =2 , + .base = {0x14000 ,0x16000 }, + .caps =MDP_PIPE_CAP_HFLIP | +MDP_PIPE_CAP_VFLIP | +MDP_PIPE_CAP_DECIMATION | +MDP_PIPE_CAP_SW_PIX_EXT | +0 , + }, + .pipe_dma = { + .count =1 , + .base = {0x24000 }, + .caps =MDP_PIPE_CAP_HFLIP | +MDP_PIPE_CAP_VFLIP | +MDP_PIPE_CAP_SW_PIX_EXT | +0 , + }, + .pipe_cursor = { + .count =1 , + .base = {0x34000 }, + .caps =MDP_PIPE_CAP_HFLIP | +MDP_PIPE_CAP_VFLIP | +MDP_PIPE_CAP_SW_PIX_EXT | +MDP_PIPE_CAP_CURSOR | +0 , + }, + + .lm = { + .count =2 , + .base = {0x44000 ,0x45000 }, + .instances = { + { .id =0 , .pp =0 , .dspp =0 , + .caps =MDP_LM_CAP_DISPLAY , }, + { .id =1 , .pp =-1 , .dspp =-1 , + .caps =MDP_LM_CAP_WB }, + }, + .nb_stages =8 , + .max_width =2048 , + .max_height =0xFFFF , + }, + .dspp = { + .count =1 , + .base = {0x54000 }, + + }, + .pp = { + .count =1 , + .base = {0x70000 }, + }, + .cdm = { + .count =1 , + .base = {0x79200 }, + }, + .intf = { + .base = {0x6a000 ,0x6a800 }, + .connect = { + [0 ] =INTF_DISABLED , + [1 ] =INTF_DSI , + }, + }, + .max_clk =320000000 , +}; +static const struct mdp5_cfg_handler cfg_handlers[] = { { .revision =0 , .config = { .hw = &msm8x74v1_config } }, { .revision =2 , .config = { .hw = &msm8x74v2_config } },
@@ -560,6 +645,7 @@ static const struct mdp5_cfg_handler cfg_handlers[] = { { .revision = 6, .config = { .hw = &msm8x16_config } }, { .revision = 9, .config = { .hw = &msm8x94_config } }, { .revision = 7, .config = { .hw = &msm8x96_config } }, + { .revision = 15, .config = { .hw = &msm8917_config } }, };static struct mdp5_cfg_platform *mdp5_get_config (struct platform_device *dev);
Signature · 1 line
2.17.1
PATCH 9/9 drm/msm: set priv->kms to NULL before uninit
In reply to Jonathan Marekotherwise, priv->kms is non-NULL and msm_drm_uninit will cause a panic.
--- drivers/gpu/drm/msm/msm_drv.c | 1 + 1 file changed, 1 insertion(+)
drivers/gpu/drm/msm/msm_drv.c +1 -0
@@ -533,6 +533,7 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)*/ dev_err (dev,"failed to load kms\n" ); ret =PTR_ERR (kms); + priv->kms =NULL ; goto err_msm_uninit; }
Signature · 1 line
2.17.1