Loading drivers/gpu/msm/adreno.c +40 −3 Original line number Diff line number Diff line Loading @@ -3004,6 +3004,33 @@ static void adreno_regwrite(struct kgsl_device *device, __raw_writel(value, reg); } void adreno_read_gmu_wrapper(struct adreno_device *adreno_dev, u32 offsetwords, u32 *val) { if (!adreno_dev->gmu_wrapper_virt) return; *val = __raw_readl(adreno_dev->gmu_wrapper_virt + (offsetwords << 2) - adreno_dev->gmu_wrapper_base); /* Order this read with respect to the following memory accesses */ rmb(); } void adreno_write_gmu_wrapper(struct adreno_device *adreno_dev, u32 offsetwords, u32 value) { if (!adreno_dev->gmu_wrapper_virt) return; /* * ensure previous writes post before this one, * i.e. act like normal writel() */ wmb(); __raw_writel(value, adreno_dev->gmu_wrapper_virt + (offsetwords << 2) - adreno_dev->gmu_wrapper_base); } /* * adreno_gmu_fenced_write() - Check if there is a GMU and it is enabled * @adreno_dev: Pointer to the Adreno device that owns the GMU Loading Loading @@ -3378,12 +3405,22 @@ static void adreno_power_stats(struct kgsl_device *device, struct kgsl_pwrctrl *pwr = &device->pwrctrl; struct adreno_busy_data *busy = &adreno_dev->busy_data; int64_t adj = 0; u64 gpu_busy; u64 gpu_busy = 0; unsigned int val; memset(stats, 0, sizeof(*stats)); gpu_busy = counter_delta(device, adreno_dev->perfctr_pwr_lo, &busy->gpu_busy); if (adreno_is_a619_holi(adreno_dev)) adreno_read_gmu_wrapper(adreno_dev, adreno_dev->perfctr_pwr_lo, &val); else kgsl_regread(device, adreno_dev->perfctr_pwr_lo, &val); if (busy->gpu_busy) gpu_busy = (val >= busy->gpu_busy) ? val - busy->gpu_busy : (~0UL - busy->gpu_busy) + val; busy->gpu_busy = val; if (gpudev->read_throttling_counters) { adj = gpudev->read_throttling_counters(adreno_dev); Loading drivers/gpu/msm/adreno.h +27 −0 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ #ifndef __ADRENO_H #define __ADRENO_H #include <linux/of.h> #include "adreno_coresight.h" #include "adreno_dispatch.h" #include "adreno_drawctxt.h" Loading Loading @@ -487,6 +488,8 @@ struct adreno_device { unsigned long isense_base; unsigned int isense_len; void __iomem *isense_virt; unsigned long gmu_wrapper_base; void __iomem *gmu_wrapper_virt; const struct adreno_gpu_core *gpucore; struct adreno_firmware fw[2]; size_t gpmu_cmds_size; Loading Loading @@ -1124,6 +1127,12 @@ static inline int adreno_is_a650_family(struct adreno_device *adreno_dev) rev == ADRENO_REV_A660); } static inline int adreno_is_a619_holi(struct adreno_device *adreno_dev) { return of_device_is_compatible(adreno_dev->dev.pdev->dev.of_node, "qcom,adreno-gpu-a619-holi"); } static inline int adreno_is_a620v1(struct adreno_device *adreno_dev) { return (ADRENO_GPUREV(adreno_dev) == ADRENO_REV_A620) && Loading Loading @@ -1252,6 +1261,24 @@ static inline void adreno_write_gmureg(struct adreno_device *adreno_dev, gpudev->reg_offsets[offset_name], val); } /** * adreno_read_gmu_wrapper() - Read a GMU wrapper register * @adreno_dev: Pointer to the the adreno device * @offsetwords: Offset of the wrapper register * @val: Register value read is placed here */ void adreno_read_gmu_wrapper(struct adreno_device *adreno_dev, u32 offsetwords, u32 *val); /** * adreno_write_gmu_wrapper() - write on a GMU wrapper register * @adreno_dev: Pointer to the the adreno device * @offsetwords: Offset of the wrapper register * @val: value to write on wrapper register */ void adreno_write_gmu_wrapper(struct adreno_device *adreno_dev, u32 offsetwords, u32 value); /** * adreno_gpu_fault() - Return the current state of the GPU * @adreno_dev: A pointer to the adreno_device to query Loading drivers/gpu/msm/adreno_a6xx.c +42 −3 Original line number Diff line number Diff line Loading @@ -121,10 +121,32 @@ static u32 a615_pwrup_reglist[] = { static int a6xx_get_cp_init_cmds(struct adreno_device *adreno_dev); static void a6xx_gmu_wrapper_init(struct adreno_device *adreno_dev) { struct kgsl_device *device = KGSL_DEVICE(adreno_dev); struct resource *res; if (adreno_dev->gmu_wrapper_virt) return; res = platform_get_resource_byname(device->pdev, IORESOURCE_MEM, "gmu_wrapper"); if (!res) return; adreno_dev->gmu_wrapper_base = res->start - device->reg_phys; adreno_dev->gmu_wrapper_virt = devm_ioremap(&device->pdev->dev, res->start, resource_size(res)); if (!adreno_dev->gmu_wrapper_virt) dev_warn(device->dev, "gmu_wrapper ioremap failed\n"); } int a6xx_init(struct adreno_device *adreno_dev) { const struct adreno_a6xx_core *a6xx_core = to_a6xx_core(adreno_dev); a6xx_gmu_wrapper_init(adreno_dev); adreno_dev->highest_bank_bit = a6xx_core->highest_bank_bit; /* If the memory type is DDR 4, override the existing configuration */ Loading Loading @@ -605,10 +627,27 @@ void a6xx_start(struct adreno_device *adreno_dev) * Enable GMU power counter 0 to count GPU busy. This is applicable to * all a6xx targets */ kgsl_regwrite(device, A6XX_GPU_GMU_AO_GPU_CX_BUSY_MASK, 0xff000000); kgsl_regrmw(device, A6XX_GMU_CX_GMU_POWER_COUNTER_SELECT_0, 0xff, 0x20); kgsl_regwrite(device, A6XX_GMU_CX_GMU_POWER_COUNTER_ENABLE, 0x1); if (adreno_is_a619_holi(adreno_dev)) { unsigned int val; adreno_write_gmu_wrapper(adreno_dev, A6XX_GPU_GMU_AO_GPU_CX_BUSY_MASK, 0xff000000); adreno_read_gmu_wrapper(adreno_dev, A6XX_GMU_CX_GMU_POWER_COUNTER_SELECT_0, &val); adreno_write_gmu_wrapper(adreno_dev, A6XX_GMU_CX_GMU_POWER_COUNTER_SELECT_0, (val & 0xff) | 0x20); adreno_write_gmu_wrapper(adreno_dev, A6XX_GMU_CX_GMU_POWER_COUNTER_ENABLE, 0x1); } else { kgsl_regwrite(device, A6XX_GPU_GMU_AO_GPU_CX_BUSY_MASK, 0xff000000); kgsl_regrmw(device, A6XX_GMU_CX_GMU_POWER_COUNTER_SELECT_0, 0xff, 0x20); kgsl_regwrite(device, A6XX_GMU_CX_GMU_POWER_COUNTER_ENABLE, 0x1); } a6xx_protect_init(adreno_dev); /* * We start LM here because we want all the following to be up Loading drivers/gpu/msm/adreno_a6xx_gmu.c +62 −2 Original line number Diff line number Diff line Loading @@ -923,6 +923,32 @@ int a6xx_gmu_sptprac_enable(struct adreno_device *adreno_dev) struct kgsl_device *device = KGSL_DEVICE(adreno_dev); struct a6xx_gmu_device *gmu = to_a6xx_gmu(adreno_dev); if (adreno_is_a619_holi(adreno_dev)) { u32 val; void __iomem *addr = adreno_dev->gmu_wrapper_virt + (A6XX_GMU_SPTPRAC_PWR_CLK_STATUS << 2) - adreno_dev->gmu_wrapper_base; if (!adreno_dev->gmu_wrapper_virt) { dev_err(device->dev, "invalid gmu_wrapper addr, power on SPTPRAC fail\n"); return -EINVAL; } adreno_write_gmu_wrapper(adreno_dev, A6XX_GMU_GX_SPTPRAC_POWER_CONTROL, SPTPRAC_POWERON_CTRL_MASK); if (readl_poll_timeout(addr, val, (val & SPTPRAC_POWERON_STATUS_MASK) == SPTPRAC_POWERON_STATUS_MASK, 10, 10 * 1000)) { dev_err(device->dev, "power on SPTPRAC fail\n"); return -EINVAL; } return 0; } if (!gmu_core_gpmu_isenabled(device) || !adreno_has_sptprac_gdsc(adreno_dev)) return 0; Loading Loading @@ -952,6 +978,35 @@ void a6xx_gmu_sptprac_disable(struct adreno_device *adreno_dev) struct kgsl_device *device = KGSL_DEVICE(adreno_dev); struct a6xx_gmu_device *gmu = to_a6xx_gmu(adreno_dev); if (adreno_is_a619_holi(adreno_dev)) { u32 val; void __iomem *addr = adreno_dev->gmu_wrapper_virt + (A6XX_GMU_SPTPRAC_PWR_CLK_STATUS << 2) - adreno_dev->gmu_wrapper_base; if (!adreno_dev->gmu_wrapper_virt) { dev_err(device->dev, "invalid gmu_wrapper addr, power off SPTPRAC fail\n"); return; } /* Ensure that retention is on */ adreno_read_gmu_wrapper(adreno_dev, A6XX_GPU_CC_GX_GDSCR, &val); adreno_write_gmu_wrapper(adreno_dev, A6XX_GPU_CC_GX_GDSCR, (val | A6XX_RETAIN_FF_ENABLE_ENABLE_MASK)); adreno_write_gmu_wrapper(adreno_dev, A6XX_GMU_GX_SPTPRAC_POWER_CONTROL, SPTPRAC_POWEROFF_CTRL_MASK); if (readl_poll_timeout(addr, val, (val & SPTPRAC_POWEROFF_STATUS_MASK) == SPTPRAC_POWEROFF_STATUS_MASK, 10, 10 * 1000)) dev_err(device->dev, "power off SPTPRAC fail\n"); return; } if (!gmu_core_gpmu_isenabled(device) || !adreno_has_sptprac_gdsc(adreno_dev)) return; Loading Loading @@ -996,10 +1051,15 @@ bool a6xx_gmu_sptprac_is_on(struct adreno_device *adreno_dev) struct kgsl_device *device = KGSL_DEVICE(adreno_dev); unsigned int val; if (!gmu_core_isenabled(device)) if (gmu_core_isenabled(device)) gmu_core_regread(device, A6XX_GMU_SPTPRAC_PWR_CLK_STATUS, &val); else if (adreno_is_a619_holi(adreno_dev)) adreno_read_gmu_wrapper(adreno_dev, A6XX_GMU_SPTPRAC_PWR_CLK_STATUS, &val); else return true; gmu_core_regread(device, A6XX_GMU_SPTPRAC_PWR_CLK_STATUS, &val); return !(val & (SPTPRAC_POWER_OFF | SP_CLK_OFF)); } Loading Loading
drivers/gpu/msm/adreno.c +40 −3 Original line number Diff line number Diff line Loading @@ -3004,6 +3004,33 @@ static void adreno_regwrite(struct kgsl_device *device, __raw_writel(value, reg); } void adreno_read_gmu_wrapper(struct adreno_device *adreno_dev, u32 offsetwords, u32 *val) { if (!adreno_dev->gmu_wrapper_virt) return; *val = __raw_readl(adreno_dev->gmu_wrapper_virt + (offsetwords << 2) - adreno_dev->gmu_wrapper_base); /* Order this read with respect to the following memory accesses */ rmb(); } void adreno_write_gmu_wrapper(struct adreno_device *adreno_dev, u32 offsetwords, u32 value) { if (!adreno_dev->gmu_wrapper_virt) return; /* * ensure previous writes post before this one, * i.e. act like normal writel() */ wmb(); __raw_writel(value, adreno_dev->gmu_wrapper_virt + (offsetwords << 2) - adreno_dev->gmu_wrapper_base); } /* * adreno_gmu_fenced_write() - Check if there is a GMU and it is enabled * @adreno_dev: Pointer to the Adreno device that owns the GMU Loading Loading @@ -3378,12 +3405,22 @@ static void adreno_power_stats(struct kgsl_device *device, struct kgsl_pwrctrl *pwr = &device->pwrctrl; struct adreno_busy_data *busy = &adreno_dev->busy_data; int64_t adj = 0; u64 gpu_busy; u64 gpu_busy = 0; unsigned int val; memset(stats, 0, sizeof(*stats)); gpu_busy = counter_delta(device, adreno_dev->perfctr_pwr_lo, &busy->gpu_busy); if (adreno_is_a619_holi(adreno_dev)) adreno_read_gmu_wrapper(adreno_dev, adreno_dev->perfctr_pwr_lo, &val); else kgsl_regread(device, adreno_dev->perfctr_pwr_lo, &val); if (busy->gpu_busy) gpu_busy = (val >= busy->gpu_busy) ? val - busy->gpu_busy : (~0UL - busy->gpu_busy) + val; busy->gpu_busy = val; if (gpudev->read_throttling_counters) { adj = gpudev->read_throttling_counters(adreno_dev); Loading
drivers/gpu/msm/adreno.h +27 −0 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ #ifndef __ADRENO_H #define __ADRENO_H #include <linux/of.h> #include "adreno_coresight.h" #include "adreno_dispatch.h" #include "adreno_drawctxt.h" Loading Loading @@ -487,6 +488,8 @@ struct adreno_device { unsigned long isense_base; unsigned int isense_len; void __iomem *isense_virt; unsigned long gmu_wrapper_base; void __iomem *gmu_wrapper_virt; const struct adreno_gpu_core *gpucore; struct adreno_firmware fw[2]; size_t gpmu_cmds_size; Loading Loading @@ -1124,6 +1127,12 @@ static inline int adreno_is_a650_family(struct adreno_device *adreno_dev) rev == ADRENO_REV_A660); } static inline int adreno_is_a619_holi(struct adreno_device *adreno_dev) { return of_device_is_compatible(adreno_dev->dev.pdev->dev.of_node, "qcom,adreno-gpu-a619-holi"); } static inline int adreno_is_a620v1(struct adreno_device *adreno_dev) { return (ADRENO_GPUREV(adreno_dev) == ADRENO_REV_A620) && Loading Loading @@ -1252,6 +1261,24 @@ static inline void adreno_write_gmureg(struct adreno_device *adreno_dev, gpudev->reg_offsets[offset_name], val); } /** * adreno_read_gmu_wrapper() - Read a GMU wrapper register * @adreno_dev: Pointer to the the adreno device * @offsetwords: Offset of the wrapper register * @val: Register value read is placed here */ void adreno_read_gmu_wrapper(struct adreno_device *adreno_dev, u32 offsetwords, u32 *val); /** * adreno_write_gmu_wrapper() - write on a GMU wrapper register * @adreno_dev: Pointer to the the adreno device * @offsetwords: Offset of the wrapper register * @val: value to write on wrapper register */ void adreno_write_gmu_wrapper(struct adreno_device *adreno_dev, u32 offsetwords, u32 value); /** * adreno_gpu_fault() - Return the current state of the GPU * @adreno_dev: A pointer to the adreno_device to query Loading
drivers/gpu/msm/adreno_a6xx.c +42 −3 Original line number Diff line number Diff line Loading @@ -121,10 +121,32 @@ static u32 a615_pwrup_reglist[] = { static int a6xx_get_cp_init_cmds(struct adreno_device *adreno_dev); static void a6xx_gmu_wrapper_init(struct adreno_device *adreno_dev) { struct kgsl_device *device = KGSL_DEVICE(adreno_dev); struct resource *res; if (adreno_dev->gmu_wrapper_virt) return; res = platform_get_resource_byname(device->pdev, IORESOURCE_MEM, "gmu_wrapper"); if (!res) return; adreno_dev->gmu_wrapper_base = res->start - device->reg_phys; adreno_dev->gmu_wrapper_virt = devm_ioremap(&device->pdev->dev, res->start, resource_size(res)); if (!adreno_dev->gmu_wrapper_virt) dev_warn(device->dev, "gmu_wrapper ioremap failed\n"); } int a6xx_init(struct adreno_device *adreno_dev) { const struct adreno_a6xx_core *a6xx_core = to_a6xx_core(adreno_dev); a6xx_gmu_wrapper_init(adreno_dev); adreno_dev->highest_bank_bit = a6xx_core->highest_bank_bit; /* If the memory type is DDR 4, override the existing configuration */ Loading Loading @@ -605,10 +627,27 @@ void a6xx_start(struct adreno_device *adreno_dev) * Enable GMU power counter 0 to count GPU busy. This is applicable to * all a6xx targets */ kgsl_regwrite(device, A6XX_GPU_GMU_AO_GPU_CX_BUSY_MASK, 0xff000000); kgsl_regrmw(device, A6XX_GMU_CX_GMU_POWER_COUNTER_SELECT_0, 0xff, 0x20); kgsl_regwrite(device, A6XX_GMU_CX_GMU_POWER_COUNTER_ENABLE, 0x1); if (adreno_is_a619_holi(adreno_dev)) { unsigned int val; adreno_write_gmu_wrapper(adreno_dev, A6XX_GPU_GMU_AO_GPU_CX_BUSY_MASK, 0xff000000); adreno_read_gmu_wrapper(adreno_dev, A6XX_GMU_CX_GMU_POWER_COUNTER_SELECT_0, &val); adreno_write_gmu_wrapper(adreno_dev, A6XX_GMU_CX_GMU_POWER_COUNTER_SELECT_0, (val & 0xff) | 0x20); adreno_write_gmu_wrapper(adreno_dev, A6XX_GMU_CX_GMU_POWER_COUNTER_ENABLE, 0x1); } else { kgsl_regwrite(device, A6XX_GPU_GMU_AO_GPU_CX_BUSY_MASK, 0xff000000); kgsl_regrmw(device, A6XX_GMU_CX_GMU_POWER_COUNTER_SELECT_0, 0xff, 0x20); kgsl_regwrite(device, A6XX_GMU_CX_GMU_POWER_COUNTER_ENABLE, 0x1); } a6xx_protect_init(adreno_dev); /* * We start LM here because we want all the following to be up Loading
drivers/gpu/msm/adreno_a6xx_gmu.c +62 −2 Original line number Diff line number Diff line Loading @@ -923,6 +923,32 @@ int a6xx_gmu_sptprac_enable(struct adreno_device *adreno_dev) struct kgsl_device *device = KGSL_DEVICE(adreno_dev); struct a6xx_gmu_device *gmu = to_a6xx_gmu(adreno_dev); if (adreno_is_a619_holi(adreno_dev)) { u32 val; void __iomem *addr = adreno_dev->gmu_wrapper_virt + (A6XX_GMU_SPTPRAC_PWR_CLK_STATUS << 2) - adreno_dev->gmu_wrapper_base; if (!adreno_dev->gmu_wrapper_virt) { dev_err(device->dev, "invalid gmu_wrapper addr, power on SPTPRAC fail\n"); return -EINVAL; } adreno_write_gmu_wrapper(adreno_dev, A6XX_GMU_GX_SPTPRAC_POWER_CONTROL, SPTPRAC_POWERON_CTRL_MASK); if (readl_poll_timeout(addr, val, (val & SPTPRAC_POWERON_STATUS_MASK) == SPTPRAC_POWERON_STATUS_MASK, 10, 10 * 1000)) { dev_err(device->dev, "power on SPTPRAC fail\n"); return -EINVAL; } return 0; } if (!gmu_core_gpmu_isenabled(device) || !adreno_has_sptprac_gdsc(adreno_dev)) return 0; Loading Loading @@ -952,6 +978,35 @@ void a6xx_gmu_sptprac_disable(struct adreno_device *adreno_dev) struct kgsl_device *device = KGSL_DEVICE(adreno_dev); struct a6xx_gmu_device *gmu = to_a6xx_gmu(adreno_dev); if (adreno_is_a619_holi(adreno_dev)) { u32 val; void __iomem *addr = adreno_dev->gmu_wrapper_virt + (A6XX_GMU_SPTPRAC_PWR_CLK_STATUS << 2) - adreno_dev->gmu_wrapper_base; if (!adreno_dev->gmu_wrapper_virt) { dev_err(device->dev, "invalid gmu_wrapper addr, power off SPTPRAC fail\n"); return; } /* Ensure that retention is on */ adreno_read_gmu_wrapper(adreno_dev, A6XX_GPU_CC_GX_GDSCR, &val); adreno_write_gmu_wrapper(adreno_dev, A6XX_GPU_CC_GX_GDSCR, (val | A6XX_RETAIN_FF_ENABLE_ENABLE_MASK)); adreno_write_gmu_wrapper(adreno_dev, A6XX_GMU_GX_SPTPRAC_POWER_CONTROL, SPTPRAC_POWEROFF_CTRL_MASK); if (readl_poll_timeout(addr, val, (val & SPTPRAC_POWEROFF_STATUS_MASK) == SPTPRAC_POWEROFF_STATUS_MASK, 10, 10 * 1000)) dev_err(device->dev, "power off SPTPRAC fail\n"); return; } if (!gmu_core_gpmu_isenabled(device) || !adreno_has_sptprac_gdsc(adreno_dev)) return; Loading Loading @@ -996,10 +1051,15 @@ bool a6xx_gmu_sptprac_is_on(struct adreno_device *adreno_dev) struct kgsl_device *device = KGSL_DEVICE(adreno_dev); unsigned int val; if (!gmu_core_isenabled(device)) if (gmu_core_isenabled(device)) gmu_core_regread(device, A6XX_GMU_SPTPRAC_PWR_CLK_STATUS, &val); else if (adreno_is_a619_holi(adreno_dev)) adreno_read_gmu_wrapper(adreno_dev, A6XX_GMU_SPTPRAC_PWR_CLK_STATUS, &val); else return true; gmu_core_regread(device, A6XX_GMU_SPTPRAC_PWR_CLK_STATUS, &val); return !(val & (SPTPRAC_POWER_OFF | SP_CLK_OFF)); } Loading