From cba91098c31b120f32db71ba7d5bba880c5e0871 Mon Sep 17 00:00:00 2001 From: Hareesh Gundu Date: Fri, 20 Jul 2018 17:04:11 +0530 Subject: [PATCH 1/2] msm: kgsl: Consolidate some gmu functions Move some gmu functions to gmu_core so that those can reusable without reimplementing on other kind of gmu. Change-Id: Ie083bd541f716eabf56da8cef4e7606a2595d482 Signed-off-by: Hareesh Gundu --- drivers/gpu/msm/adreno.c | 4 +- drivers/gpu/msm/adreno_a6xx_gmu.c | 11 ++- drivers/gpu/msm/kgsl_device.h | 2 +- drivers/gpu/msm/kgsl_gmu.c | 148 ++++++------------------------ drivers/gpu/msm/kgsl_gmu.h | 4 - drivers/gpu/msm/kgsl_gmu_core.c | 83 +++++++---------- drivers/gpu/msm/kgsl_gmu_core.h | 19 +--- drivers/gpu/msm/kgsl_hfi.c | 10 +- drivers/gpu/msm/kgsl_pwrctrl.c | 16 ++-- 9 files changed, 88 insertions(+), 209 deletions(-) diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index afad73cddeb0..713943dc2f77 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -2135,7 +2135,7 @@ static int adreno_stop(struct kgsl_device *device) gmu_dev_ops->oob_clear(adreno_dev, oob_gpu); if (gmu_core_regulator_isenabled(device)) { /* GPU is on. Try recovery */ - gmu_core_setbit(device, GMU_FAULT); + set_bit(GMU_FAULT, &device->gmu_core.flags); gmu_core_snapshot(device); error = -EINVAL; } else { @@ -2177,7 +2177,7 @@ static int adreno_stop(struct kgsl_device *device) if (!error && GMU_DEV_OP_VALID(gmu_dev_ops, wait_for_lowest_idle) && gmu_dev_ops->wait_for_lowest_idle(adreno_dev)) { - gmu_core_setbit(device, GMU_FAULT); + set_bit(GMU_FAULT, &device->gmu_core.flags); gmu_core_snapshot(device); /* * Assume GMU hang after 10ms without responding. diff --git a/drivers/gpu/msm/adreno_a6xx_gmu.c b/drivers/gpu/msm/adreno_a6xx_gmu.c index 27108ae7a4c4..c36a19494feb 100644 --- a/drivers/gpu/msm/adreno_a6xx_gmu.c +++ b/drivers/gpu/msm/adreno_a6xx_gmu.c @@ -373,7 +373,7 @@ static int a6xx_rpmh_power_on_gpu(struct kgsl_device *device) int val; /* Only trigger wakeup sequence if sleep sequence was done earlier */ - if (!test_bit(GMU_RSCC_SLEEP_SEQ_DONE, &gmu->flags)) + if (!test_bit(GMU_RSCC_SLEEP_SEQ_DONE, &device->gmu_core.flags)) return 0; gmu_core_regread(device, A6XX_GPU_CC_GX_DOMAIN_MISC, &val); @@ -406,7 +406,7 @@ static int a6xx_rpmh_power_on_gpu(struct kgsl_device *device) gmu_core_regwrite(device, A6XX_GMU_RSCC_CONTROL_REQ, 0); /* Clear sleep sequence flag as wakeup sequence is successful */ - clear_bit(GMU_RSCC_SLEEP_SEQ_DONE, &gmu->flags); + clear_bit(GMU_RSCC_SLEEP_SEQ_DONE, &device->gmu_core.flags); /* Enable the power counter because it was disabled before slumber */ gmu_core_regwrite(device, A6XX_GMU_CX_GMU_POWER_COUNTER_ENABLE, 1); @@ -423,7 +423,7 @@ static int a6xx_rpmh_power_off_gpu(struct kgsl_device *device) struct adreno_device *adreno_dev = ADRENO_DEVICE(device); int ret; - if (test_bit(GMU_RSCC_SLEEP_SEQ_DONE, &gmu->flags)) + if (test_bit(GMU_RSCC_SLEEP_SEQ_DONE, &device->gmu_core.flags)) return 0; /* RSC sleep sequence is different on v1 */ @@ -468,7 +468,7 @@ static int a6xx_rpmh_power_off_gpu(struct kgsl_device *device) test_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag)) gmu_core_regwrite(device, A6XX_GMU_AO_SPARE_CNTL, 0); - set_bit(GMU_RSCC_SLEEP_SEQ_DONE, &gmu->flags); + set_bit(GMU_RSCC_SLEEP_SEQ_DONE, &device->gmu_core.flags); return 0; } @@ -955,7 +955,8 @@ static int a6xx_gmu_fw_start(struct kgsl_device *device, /* Turn on TCM retention */ gmu_core_regwrite(device, A6XX_GMU_GENERAL_7, 1); - if (!test_and_set_bit(GMU_BOOT_INIT_DONE, &gmu->flags)) + if (!test_and_set_bit(GMU_BOOT_INIT_DONE, + &device->gmu_core.flags)) ret = _load_gmu_rpmh_ucode(device); else ret = a6xx_rpmh_power_on_gpu(device); diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h index a395f8944bcf..c4264df712ae 100644 --- a/drivers/gpu/msm/kgsl_device.h +++ b/drivers/gpu/msm/kgsl_device.h @@ -656,7 +656,7 @@ static inline int kgsl_state_is_awake(struct kgsl_device *device) device->state == KGSL_STATE_AWARE) return true; else if (gmu_core_isenabled(device) && - gmu_core_testbit(device, GMU_CLK_ON)) + test_bit(GMU_CLK_ON, &device->gmu_core.flags)) return true; else return false; diff --git a/drivers/gpu/msm/kgsl_gmu.c b/drivers/gpu/msm/kgsl_gmu.c index faa4977be000..f6437fe6c8e0 100644 --- a/drivers/gpu/msm/kgsl_gmu.c +++ b/drivers/gpu/msm/kgsl_gmu.c @@ -24,9 +24,7 @@ #include "kgsl_device.h" #include "kgsl_gmu.h" #include "kgsl_hfi.h" -#include "a6xx_reg.h" #include "adreno.h" -#include "kgsl_trace.h" #define GMU_CONTEXT_USER 0 #define GMU_CONTEXT_KERNEL 1 @@ -625,7 +623,7 @@ static int gmu_dcvs_set(struct kgsl_device *device, if (ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_HFI_USE_REG)) ret = gmu_dev_ops->rpmh_gpu_pwrctrl(adreno_dev, GMU_DCVS_NOHFI, req.freq, req.bw); - else if (test_bit(GMU_HFI_ON, &gmu->flags)) + else if (test_bit(GMU_HFI_ON, &device->gmu_core.flags)) ret = hfi_send_req(gmu, H2F_MSG_GX_BW_PERF_VOTE, &req); if (ret) { @@ -1076,8 +1074,9 @@ static int gmu_pwrlevel_probe(struct gmu_device *gmu, struct device_node *node) return 0; } -static int gmu_reg_probe(struct gmu_device *gmu) +static int gmu_reg_probe(struct kgsl_device *device) { + struct gmu_device *gmu = KGSL_GMU_DEVICE(device); struct resource *res; res = platform_get_resource_byname(gmu->pdev, IORESOURCE_MEM, @@ -1097,10 +1096,9 @@ static int gmu_reg_probe(struct gmu_device *gmu) gmu->reg_phys = res->start; gmu->reg_len = resource_size(res); - - gmu->reg_virt = devm_ioremap(&gmu->pdev->dev, res->start, - resource_size(res)); - if (gmu->reg_virt == NULL) { + device->gmu_core.reg_virt = devm_ioremap(&gmu->pdev->dev, + res->start, resource_size(res)); + if (device->gmu_core.reg_virt == NULL) { dev_err(&gmu->pdev->dev, "kgsl_gmu_reg ioremap failed\n"); return -ENODEV; } @@ -1264,8 +1262,7 @@ static int gmu_irq_probe(struct kgsl_device *device, struct gmu_device *gmu) } /* Do not access any GMU registers in GMU probe function */ -static int gmu_probe(struct kgsl_device *device, - struct device_node *node, unsigned long flags) +static int gmu_probe(struct kgsl_device *device, struct device_node *node) { struct gmu_device *gmu; struct gmu_memdesc *mem_addr = NULL; @@ -1279,11 +1276,10 @@ static int gmu_probe(struct kgsl_device *device, if (gmu == NULL) return -ENOMEM; + device->gmu_core.ptr = (void *)gmu; hfi = &gmu->hfi; gmu->load_mode = TCM_BOOT; - gmu->ver = ~0U; - gmu->flags = flags; gmu->pdev = of_find_device_by_node(node); of_dma_configure(&gmu->pdev->dev, node); @@ -1305,7 +1301,7 @@ static int gmu_probe(struct kgsl_device *device, mem_addr = gmu->hfi_mem; /* Map and reserve GMU CSRs registers */ - ret = gmu_reg_probe(gmu); + ret = gmu_reg_probe(device); if (ret) goto error; @@ -1372,9 +1368,8 @@ static int gmu_probe(struct kgsl_device *device, /* disable LM during boot time */ clear_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag); - set_bit(GMU_ENABLED, &gmu->flags); + set_bit(GMU_ENABLED, &device->gmu_core.flags); - device->gmu_core.ptr = (void *)gmu; device->gmu_core.dev_ops = &adreno_a6xx_gmudev; return 0; @@ -1384,8 +1379,9 @@ error: return ret; } -static int gmu_enable_clks(struct gmu_device *gmu) +static int gmu_enable_clks(struct kgsl_device *device) { + struct gmu_device *gmu = KGSL_GMU_DEVICE(device); int ret, j = 0; if (IS_ERR_OR_NULL(gmu->clks[0])) @@ -1409,12 +1405,13 @@ static int gmu_enable_clks(struct gmu_device *gmu) j++; } - set_bit(GMU_CLK_ON, &gmu->flags); + set_bit(GMU_CLK_ON, &device->gmu_core.flags); return 0; } -static int gmu_disable_clks(struct gmu_device *gmu) +static int gmu_disable_clks(struct kgsl_device *device) { + struct gmu_device *gmu = KGSL_GMU_DEVICE(device); int j = 0; if (IS_ERR_OR_NULL(gmu->clks[0])) @@ -1425,7 +1422,7 @@ static int gmu_disable_clks(struct gmu_device *gmu) j++; } - clear_bit(GMU_CLK_ON, &gmu->flags); + clear_bit(GMU_CLK_ON, &device->gmu_core.flags); return 0; } @@ -1488,7 +1485,7 @@ static int gmu_suspend(struct kgsl_device *device) struct gmu_dev_ops *gmu_dev_ops = GMU_DEVICE_OPS(device); struct gmu_device *gmu = KGSL_GMU_DEVICE(device); - if (!test_bit(GMU_CLK_ON, &gmu->flags)) + if (!test_bit(GMU_CLK_ON, &device->gmu_core.flags)) return 0; /* Pending message in all queues are abandoned */ @@ -1498,7 +1495,7 @@ static int gmu_suspend(struct kgsl_device *device) if (gmu_dev_ops->rpmh_gpu_pwrctrl(adreno_dev, GMU_SUSPEND, 0, 0)) return -EINVAL; - gmu_disable_clks(gmu); + gmu_disable_clks(device); gmu_disable_gdsc(gmu); dev_err(&gmu->pdev->dev, "Suspended GMU\n"); return 0; @@ -1547,9 +1544,9 @@ static int gmu_start(struct kgsl_device *device) switch (device->state) { case KGSL_STATE_INIT: case KGSL_STATE_SUSPEND: - WARN_ON(test_bit(GMU_CLK_ON, &gmu->flags)); + WARN_ON(test_bit(GMU_CLK_ON, &device->gmu_core.flags)); gmu_enable_gdsc(gmu); - gmu_enable_clks(gmu); + gmu_enable_clks(device); gmu_dev_ops->irq_enable(device); /* Vote for 300MHz DDR for GMU to init */ @@ -1574,9 +1571,9 @@ static int gmu_start(struct kgsl_device *device) break; case KGSL_STATE_SLUMBER: - WARN_ON(test_bit(GMU_CLK_ON, &gmu->flags)); + WARN_ON(test_bit(GMU_CLK_ON, &device->gmu_core.flags)); gmu_enable_gdsc(gmu); - gmu_enable_clks(gmu); + gmu_enable_clks(device); gmu_dev_ops->irq_enable(device); ret = gmu_dev_ops->rpmh_gpu_pwrctrl(adreno_dev, GMU_FW_START, @@ -1593,10 +1590,10 @@ static int gmu_start(struct kgsl_device *device) case KGSL_STATE_RESET: if (test_bit(ADRENO_DEVICE_HARD_RESET, &adreno_dev->priv) || - test_bit(GMU_FAULT, &gmu->flags)) { + test_bit(GMU_FAULT, &device->gmu_core.flags)) { gmu_suspend(device); gmu_enable_gdsc(gmu); - gmu_enable_clks(gmu); + gmu_enable_clks(device); gmu_dev_ops->irq_enable(device); ret = gmu_dev_ops->rpmh_gpu_pwrctrl( @@ -1646,7 +1643,7 @@ static void gmu_stop(struct kgsl_device *device) struct gmu_dev_ops *gmu_dev_ops = GMU_DEVICE_OPS(device); int ret = 0; - if (!test_bit(GMU_CLK_ON, &gmu->flags)) + if (!test_bit(GMU_CLK_ON, &device->gmu_core.flags)) return; /* Wait for the lowest idle level we requested */ @@ -1668,7 +1665,7 @@ static void gmu_stop(struct kgsl_device *device) hfi_stop(gmu); gmu_dev_ops->rpmh_gpu_pwrctrl(adreno_dev, GMU_FW_STOP, 0, 0); - gmu_disable_clks(gmu); + gmu_disable_clks(device); gmu_disable_gdsc(gmu); msm_bus_scale_client_update_request(gmu->pcl, 0); @@ -1680,7 +1677,7 @@ error: * Set GMU_FAULT flag to indicate to power contrller * that hang recovery is needed to power on GPU */ - set_bit(GMU_FAULT, &gmu->flags); + set_bit(GMU_FAULT, &device->gmu_core.flags); dev_err(&gmu->pdev->dev, "Failed to stop GMU\n"); gmu_core_snapshot(device); } @@ -1727,11 +1724,6 @@ static void gmu_remove(struct kgsl_device *device) gmu->pcl = 0; } - if (gmu->reg_virt) { - devm_iounmap(&gmu->pdev->dev, gmu->reg_virt); - gmu->reg_virt = NULL; - } - gmu_memory_close(gmu); for (i = 0; i < MAX_GMU_CLKS; i++) { @@ -1751,86 +1743,12 @@ static void gmu_remove(struct kgsl_device *device) gmu->cx_gdsc = NULL; } - gmu->flags = 0; + device->gmu_core.flags = 0; + device->gmu_core.ptr = NULL; gmu->pdev = NULL; kfree(gmu); } -static void gmu_regwrite(struct kgsl_device *device, - unsigned int offsetwords, unsigned int value) -{ - struct gmu_device *gmu = KGSL_GMU_DEVICE(device); - void __iomem *reg; - - trace_kgsl_regwrite(device, offsetwords, value); - - offsetwords -= device->gmu_core.gmu2gpu_offset; - reg = gmu->reg_virt + (offsetwords << 2); - - /* - * ensure previous writes post before this one, - * i.e. act like normal writel() - */ - wmb(); - __raw_writel(value, reg); -} - -static void gmu_regread(struct kgsl_device *device, - unsigned int offsetwords, unsigned int *value) -{ - struct gmu_device *gmu = KGSL_GMU_DEVICE(device); - void __iomem *reg; - - offsetwords -= device->gmu_core.gmu2gpu_offset; - - reg = gmu->reg_virt + (offsetwords << 2); - - *value = __raw_readl(reg); - - /* - * ensure this read finishes before the next one. - * i.e. act like normal readl() - */ - rmb(); -} - -/* Check if GPMU is in charge of power features */ -static bool gmu_gpmu_isenabled(struct kgsl_device *device) -{ - struct gmu_device *gmu = KGSL_GMU_DEVICE(device); - - return test_bit(GMU_GPMU, &gmu->flags); -} - -/* Check if GMU is enabled. Only set once GMU is fully initialized */ -static bool gmu_isenabled(struct kgsl_device *device) -{ - struct gmu_device *gmu = KGSL_GMU_DEVICE(device); - - return test_bit(GMU_ENABLED, &gmu->flags); -} - -static void gmu_set_bit(struct kgsl_device *device, enum gmu_core_flags flag) -{ - struct gmu_device *gmu = KGSL_GMU_DEVICE(device); - - set_bit(flag, &gmu->flags); -} - -static void gmu_clear_bit(struct kgsl_device *device, enum gmu_core_flags flag) -{ - struct gmu_device *gmu = KGSL_GMU_DEVICE(device); - - clear_bit(flag, &gmu->flags); -} - -static int gmu_test_bit(struct kgsl_device *device, enum gmu_core_flags flag) -{ - struct gmu_device *gmu = KGSL_GMU_DEVICE(device); - - return test_bit(flag, &gmu->flags); -} - static bool gmu_regulator_isenabled(struct kgsl_device *device) { struct gmu_device *gmu = KGSL_GMU_DEVICE(device); @@ -1838,19 +1756,11 @@ static bool gmu_regulator_isenabled(struct kgsl_device *device) return (gmu->gx_gdsc && regulator_is_enabled(gmu->gx_gdsc)); } - struct gmu_core_ops gmu_ops = { .probe = gmu_probe, .remove = gmu_remove, - .regread = gmu_regread, - .regwrite = gmu_regwrite, - .isenabled = gmu_isenabled, - .gpmu_isenabled = gmu_gpmu_isenabled, .start = gmu_start, .stop = gmu_stop, - .set_bit = gmu_set_bit, - .clear_bit = gmu_clear_bit, - .test_bit = gmu_test_bit, .dcvs_set = gmu_dcvs_set, .snapshot = gmu_snapshot, .regulator_isenabled = gmu_regulator_isenabled, diff --git a/drivers/gpu/msm/kgsl_gmu.h b/drivers/gpu/msm/kgsl_gmu.h index 2dba023ab980..db70af20ac9c 100644 --- a/drivers/gpu/msm/kgsl_gmu.h +++ b/drivers/gpu/msm/kgsl_gmu.h @@ -103,7 +103,6 @@ enum gmu_load_mode { * struct gmu_device - GMU device structure * @ver: GMU FW version, read from GMU * @reg_phys: GMU CSR physical address - * @reg_virt: GMU CSR virtual address * @reg_len: GMU CSR range * @gmu_interrupt_num: GMU interrupt number * @fw_image: descriptor of GMU memory that has GMU image in it @@ -127,7 +126,6 @@ enum gmu_load_mode { * @gx_gdsc: GX headswitch that controls power of GPU subsystem * @clks: GPU subsystem clocks required for GMU functionality * @load_mode: GMU FW load/boot mode - * @flags: GMU flags * @wakeup_pwrlevel: GPU wake up power/DCVS level in case different * than default power level * @pcl: GPU BW scaling client @@ -139,7 +137,6 @@ struct gmu_device { unsigned int ver; struct platform_device *pdev; unsigned long reg_phys; - void __iomem *reg_virt; unsigned int reg_len; unsigned int gmu_interrupt_num; struct gmu_memdesc cached_fw_image; @@ -165,7 +162,6 @@ struct gmu_device { struct regulator *gx_gdsc; struct clk *clks[MAX_GMU_CLKS]; enum gmu_load_mode load_mode; - unsigned long flags; unsigned int wakeup_pwrlevel; unsigned int pcl; unsigned int ccl; diff --git a/drivers/gpu/msm/kgsl_gmu_core.c b/drivers/gpu/msm/kgsl_gmu_core.c index 3979a93839a2..e752c3231204 100644 --- a/drivers/gpu/msm/kgsl_gmu_core.c +++ b/drivers/gpu/msm/kgsl_gmu_core.c @@ -15,7 +15,7 @@ #include "kgsl_device.h" #include "kgsl_gmu_core.h" -#include "a6xx_reg.h" +#include "kgsl_trace.h" #include "adreno.h" #undef MODULE_PARAM_PREFIX @@ -36,11 +36,10 @@ int gmu_core_probe(struct kgsl_device *device) { struct device_node *node; struct gmu_core_ops *gmu_core_ops; - unsigned long flags; int i = 0, ret = -ENXIO; - flags = ADRENO_FEATURE(ADRENO_DEVICE(device), ADRENO_GPMU) ? - BIT(GMU_GPMU) : 0; + device->gmu_core.flags = ADRENO_FEATURE(ADRENO_DEVICE(device), + ADRENO_GPMU) ? BIT(GMU_GPMU) : 0; for (i = 0; i < ARRAY_SIZE(gmu_subtypes); i++) { node = of_find_compatible_node(device->pdev->dev.of_node, @@ -53,14 +52,14 @@ int gmu_core_probe(struct kgsl_device *device) /* No GMU in dt, no worries...hopefully */ if (node == NULL) { /* If we are trying to use GPMU and no GMU, that's bad */ - if (flags & BIT(GMU_GPMU)) + if (device->gmu_core.flags & BIT(GMU_GPMU)) return ret; /* Otherwise it's ok and nothing to do */ return 0; } if (gmu_core_ops && gmu_core_ops->probe) { - ret = gmu_core_ops->probe(device, node, flags); + ret = gmu_core_ops->probe(device, node); if (ret == 0) device->gmu_core.core_ops = gmu_core_ops; } @@ -78,22 +77,12 @@ void gmu_core_remove(struct kgsl_device *device) bool gmu_core_isenabled(struct kgsl_device *device) { - struct gmu_core_ops *gmu_core_ops = GMU_CORE_OPS(device); - - if (gmu_core_ops && gmu_core_ops->isenabled) - return !nogmu && gmu_core_ops->isenabled(device); - - return false; + return test_bit(GMU_ENABLED, &device->gmu_core.flags); } bool gmu_core_gpmu_isenabled(struct kgsl_device *device) { - struct gmu_core_ops *gmu_core_ops = GMU_CORE_OPS(device); - - if (gmu_core_ops && gmu_core_ops->gpmu_isenabled) - return gmu_core_ops->gpmu_isenabled(device); - - return false; + return test_bit(GMU_GPMU, &device->gmu_core.flags); } int gmu_core_start(struct kgsl_device *device) @@ -143,32 +132,6 @@ int gmu_core_dcvs_set(struct kgsl_device *device, unsigned int gpu_pwrlevel, return -EINVAL; } -void gmu_core_setbit(struct kgsl_device *device, enum gmu_core_flags flag) -{ - struct gmu_core_ops *gmu_core_ops = GMU_CORE_OPS(device); - - if (gmu_core_ops && gmu_core_ops->set_bit) - return gmu_core_ops->set_bit(device, flag); -} - -void gmu_core_clearbit(struct kgsl_device *device, enum gmu_core_flags flag) -{ - struct gmu_core_ops *gmu_core_ops = GMU_CORE_OPS(device); - - if (gmu_core_ops && gmu_core_ops->clear_bit) - return gmu_core_ops->clear_bit(device, flag); -} - -int gmu_core_testbit(struct kgsl_device *device, enum gmu_core_flags flag) -{ - struct gmu_core_ops *gmu_core_ops = GMU_CORE_OPS(device); - - if (gmu_core_ops && gmu_core_ops->test_bit) - return gmu_core_ops->test_bit(device, flag); - - return -EINVAL; -} - bool gmu_core_regulator_isenabled(struct kgsl_device *device) { struct gmu_core_ops *gmu_core_ops = GMU_CORE_OPS(device); @@ -191,31 +154,47 @@ bool gmu_core_is_register_offset(struct kgsl_device *device, void gmu_core_regread(struct kgsl_device *device, unsigned int offsetwords, unsigned int *value) { - struct gmu_core_ops *gmu_core_ops = GMU_CORE_OPS(device); + void __iomem *reg; if (!gmu_core_is_register_offset(device, offsetwords)) { WARN(1, "Out of bounds register read: 0x%x\n", offsetwords); return; } - if (gmu_core_ops && gmu_core_ops->regread) - gmu_core_ops->regread(device, offsetwords, value); - else - *value = 0; + offsetwords -= device->gmu_core.gmu2gpu_offset; + + reg = device->gmu_core.reg_virt + (offsetwords << 2); + + *value = __raw_readl(reg); + + /* + * ensure this read finishes before the next one. + * i.e. act like normal readl() + */ + rmb(); } void gmu_core_regwrite(struct kgsl_device *device, unsigned int offsetwords, unsigned int value) { - struct gmu_core_ops *gmu_core_ops = GMU_CORE_OPS(device); + void __iomem *reg; if (!gmu_core_is_register_offset(device, offsetwords)) { WARN(1, "Out of bounds register write: 0x%x\n", offsetwords); return; } - if (gmu_core_ops && gmu_core_ops->regwrite) - gmu_core_ops->regwrite(device, offsetwords, value); + trace_kgsl_regwrite(device, offsetwords, value); + + offsetwords -= device->gmu_core.gmu2gpu_offset; + reg = device->gmu_core.reg_virt + (offsetwords << 2); + + /* + * ensure previous writes post before this one, + * i.e. act like normal writel() + */ + wmb(); + __raw_writel(value, reg); } void gmu_core_regrmw(struct kgsl_device *device, diff --git a/drivers/gpu/msm/kgsl_gmu_core.h b/drivers/gpu/msm/kgsl_gmu_core.h index 76a0a6bd3215..496b4c2a6326 100644 --- a/drivers/gpu/msm/kgsl_gmu_core.h +++ b/drivers/gpu/msm/kgsl_gmu_core.h @@ -111,20 +111,10 @@ struct adreno_device; struct kgsl_snapshot; struct gmu_core_ops { - int (*probe)(struct kgsl_device *device, struct device_node *node, - unsigned long flags); + int (*probe)(struct kgsl_device *device, struct device_node *node); void (*remove)(struct kgsl_device *device); - void (*regread)(struct kgsl_device *device, - unsigned int offsetwords, unsigned int *value); - void (*regwrite)(struct kgsl_device *device, - unsigned int offsetwords, unsigned int value); - bool (*isenabled)(struct kgsl_device *device); - bool (*gpmu_isenabled)(struct kgsl_device *device); int (*dcvs_set)(struct kgsl_device *device, unsigned int gpu_pwrlevel, unsigned int bus_level); - void (*set_bit)(struct kgsl_device *device, enum gmu_core_flags flag); - void (*clear_bit)(struct kgsl_device *device, enum gmu_core_flags flag); - int (*test_bit)(struct kgsl_device *device, enum gmu_core_flags flag); int (*start)(struct kgsl_device *device); void (*stop)(struct kgsl_device *device); void (*snapshot)(struct kgsl_device *device); @@ -162,15 +152,19 @@ struct gmu_dev_ops { * and GPU register set, the offset will be used when accessing * gmu registers using offset defined in GPU register space. * @reg_len: GMU registers length + * @reg_virt: GMU CSR virtual address * @core_ops: Pointer to gmu core operations * @dev_ops: Pointer to gmu device operations + * @flags: GMU flags */ struct gmu_core_device { void *ptr; unsigned int gmu2gpu_offset; unsigned int reg_len; + void __iomem *reg_virt; struct gmu_core_ops *core_ops; struct gmu_dev_ops *dev_ops; + unsigned long flags; }; /* GMU core functions */ @@ -186,9 +180,6 @@ bool gmu_core_gpmu_isenabled(struct kgsl_device *device); bool gmu_core_isenabled(struct kgsl_device *device); int gmu_core_dcvs_set(struct kgsl_device *device, unsigned int gpu_pwrlevel, unsigned int bus_level); -void gmu_core_setbit(struct kgsl_device *device, enum gmu_core_flags flag); -void gmu_core_clearbit(struct kgsl_device *device, enum gmu_core_flags flag); -int gmu_core_testbit(struct kgsl_device *device, enum gmu_core_flags flag); bool gmu_core_regulator_isenabled(struct kgsl_device *device); bool gmu_core_is_register_offset(struct kgsl_device *device, unsigned int offsetwords); diff --git a/drivers/gpu/msm/kgsl_hfi.c b/drivers/gpu/msm/kgsl_hfi.c index 291364d3d1c1..6b2f77acc67e 100644 --- a/drivers/gpu/msm/kgsl_hfi.c +++ b/drivers/gpu/msm/kgsl_hfi.c @@ -684,7 +684,7 @@ int hfi_start(struct kgsl_device *device, struct hfi_queue_header *hdr; int result, i; - if (test_bit(GMU_HFI_ON, &gmu->flags)) + if (test_bit(GMU_HFI_ON, &device->gmu_core.flags)) return 0; /* Force read_index to the write_index no matter what */ @@ -742,7 +742,7 @@ int hfi_start(struct kgsl_device *device, return result; } } - set_bit(GMU_HFI_ON, &gmu->flags); + set_bit(GMU_HFI_ON, &device->gmu_core.flags); return 0; } @@ -751,10 +751,12 @@ void hfi_stop(struct gmu_device *gmu) struct gmu_memdesc *mem_addr = gmu->hfi_mem; struct hfi_queue_table *tbl = mem_addr->hostptr; struct hfi_queue_header *hdr; + struct kgsl_hfi *hfi = &gmu->hfi; + struct kgsl_device *device = hfi->kgsldev; unsigned int i; - if (!test_bit(GMU_HFI_ON, &gmu->flags)) + if (!test_bit(GMU_HFI_ON, &device->gmu_core.flags)) return; /* Flush HFI queues */ @@ -769,7 +771,7 @@ void hfi_stop(struct gmu_device *gmu) i, hdr->read_index, hdr->write_index); } - clear_bit(GMU_HFI_ON, &gmu->flags); + clear_bit(GMU_HFI_ON, &device->gmu_core.flags); } /* Entry point for external HFI requests */ diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c index db434cdc44d8..c26127c30a59 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.c +++ b/drivers/gpu/msm/kgsl_pwrctrl.c @@ -255,9 +255,9 @@ int kgsl_clk_set_rate(struct kgsl_device *device, int num_gpupwrlevels = pwr->num_pwrlevels; /* If GMU has not been started, save it */ - if (!gmu_core_testbit(device, GMU_HFI_ON)) { + if (!test_bit(GMU_HFI_ON, &device->gmu_core.flags)) { /* store clock change request */ - gmu_core_setbit(device, GMU_DCVS_REPLAY); + set_bit(GMU_DCVS_REPLAY, &device->gmu_core.flags); return 0; } @@ -270,8 +270,8 @@ int kgsl_clk_set_rate(struct kgsl_device *device, return -EINVAL; } ret = gmu_core_dcvs_set(device, pwrlevel, INVALID_DCVS_IDX); - /* indicate actual clock change */ - gmu_core_clearbit(device, GMU_DCVS_REPLAY); + /* indicate actual clock change */ + clear_bit(GMU_DCVS_REPLAY, &device->gmu_core.flags); } else /* Linux clock driver scales GPU freq */ ret = kgsl_pwrctrl_clk_set_rate(pwr->grp_clks[0], @@ -444,7 +444,7 @@ void kgsl_pwrctrl_pwrlevel_change(struct kgsl_device *device, kgsl_pwrctrl_set_thermal_cycle(device, new_level); if (new_level == old_level && - !gmu_core_testbit(device, GMU_DCVS_REPLAY)) + !test_bit(GMU_DCVS_REPLAY, &device->gmu_core.flags)) return; kgsl_pwrscale_update_stats(device); @@ -2793,7 +2793,7 @@ _aware(struct kgsl_device *device) case KGSL_STATE_SLUMBER: /* if GMU already in FAULT */ if (gmu_core_isenabled(device) && - gmu_core_testbit(device, GMU_FAULT)) { + test_bit(GMU_FAULT, &device->gmu_core.flags)) { status = -EINVAL; break; } @@ -2808,7 +2808,7 @@ _aware(struct kgsl_device *device) if (gmu_core_isenabled(device)) { /* GMU hang recovery */ kgsl_pwrctrl_set_state(device, KGSL_STATE_RESET); - gmu_core_setbit(device, GMU_FAULT); + set_bit(GMU_FAULT, &device->gmu_core.flags); status = kgsl_pwrctrl_enable(device); if (status) { /* @@ -2844,7 +2844,7 @@ _aware(struct kgsl_device *device) KGSL_STATE_AWARE); } - gmu_core_clearbit(device, GMU_FAULT); + clear_bit(GMU_FAULT, &device->gmu_core.flags); return status; } From 4f193e8b57aee53c238c41acd31dcae791991f14 Mon Sep 17 00:00:00 2001 From: Hareesh Gundu Date: Fri, 20 Jul 2018 20:01:28 +0530 Subject: [PATCH 2/2] msm: kgsl: Do not access GMU_HFI_ON flag in power control HFI is not a common feature, it's specific to few A6xx GPUs. Move HFI flags related operations inside GMU module. Change-Id: I3041533854389514c6737b167dd5c4b521886924 Signed-off-by: Hareesh Gundu --- drivers/gpu/msm/kgsl_gmu.c | 18 +++++++++++++++++- drivers/gpu/msm/kgsl_pwrctrl.c | 23 ++--------------------- 2 files changed, 19 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/msm/kgsl_gmu.c b/drivers/gpu/msm/kgsl_gmu.c index f6437fe6c8e0..ae42233e28bd 100644 --- a/drivers/gpu/msm/kgsl_gmu.c +++ b/drivers/gpu/msm/kgsl_gmu.c @@ -609,6 +609,18 @@ static int gmu_dcvs_set(struct kgsl_device *device, .bw = INVALID_DCVS_IDX, }; + /* Do not set to XO and lower GPU clock vote from GMU */ + if ((gpu_pwrlevel != INVALID_DCVS_IDX) && + (gpu_pwrlevel >= gmu->num_gpupwrlevels - 1)) + return -EINVAL; + + /* If GMU has not been started, save it */ + if (!test_bit(GMU_HFI_ON, &device->gmu_core.flags)) { + /* store clock change request */ + set_bit(GMU_DCVS_REPLAY, &device->gmu_core.flags); + return 0; + } + if (gpu_pwrlevel < gmu->num_gpupwrlevels - 1) req.freq = gmu->num_gpupwrlevels - gpu_pwrlevel - 1; @@ -617,8 +629,10 @@ static int gmu_dcvs_set(struct kgsl_device *device, /* GMU will vote for slumber levels through the sleep sequence */ if ((req.freq == INVALID_DCVS_IDX) && - (req.bw == INVALID_DCVS_IDX)) + (req.bw == INVALID_DCVS_IDX)) { + clear_bit(GMU_DCVS_REPLAY, &device->gmu_core.flags); return 0; + } if (ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_HFI_USE_REG)) ret = gmu_dev_ops->rpmh_gpu_pwrctrl(adreno_dev, @@ -635,6 +649,8 @@ static int gmu_dcvs_set(struct kgsl_device *device, adreno_dispatcher_schedule(device); } + /* indicate actual clock change */ + clear_bit(GMU_DCVS_REPLAY, &device->gmu_core.flags); return ret; } diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c index c26127c30a59..a36127f2bbd0 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.c +++ b/drivers/gpu/msm/kgsl_pwrctrl.c @@ -251,28 +251,9 @@ int kgsl_clk_set_rate(struct kgsl_device *device, int ret = 0; /* GMU scales GPU freq */ - if (gmu_core_gpmu_isenabled(device)) { - int num_gpupwrlevels = pwr->num_pwrlevels; - - /* If GMU has not been started, save it */ - if (!test_bit(GMU_HFI_ON, &device->gmu_core.flags)) { - /* store clock change request */ - set_bit(GMU_DCVS_REPLAY, &device->gmu_core.flags); - return 0; - } - - if (num_gpupwrlevels < 0) - return -EINVAL; - - /* If the GMU is on we cannot vote for the lowest level */ - if (pwrlevel == (num_gpupwrlevels - 1)) { - WARN(1, "Cannot set 0 GPU frequency with GMU\n"); - return -EINVAL; - } + if (gmu_core_gpmu_isenabled(device)) ret = gmu_core_dcvs_set(device, pwrlevel, INVALID_DCVS_IDX); - /* indicate actual clock change */ - clear_bit(GMU_DCVS_REPLAY, &device->gmu_core.flags); - } else + else /* Linux clock driver scales GPU freq */ ret = kgsl_pwrctrl_clk_set_rate(pwr->grp_clks[0], pl->gpu_freq, clocks[0]);