From e9fad773e64af1d192e840e59b38a7dddc2eed4e Mon Sep 17 00:00:00 2001 From: Harshdeep Dhatt Date: Tue, 11 Feb 2020 14:05:31 -0700 Subject: [PATCH 1/3] msm: kgsl: Clear halt before gmu boot During hard reset if we are not able to toggle the CX gdsc, the halt will remain asserted at the time of next GMU boot. This causes GMU boot to fail and lead to NoC errors. So clear the halt bit before attempting GMU boot. Also, move the wptr retention out among the rest of the register writes instead of piling them inside a6xx_gmu_start(). Change-Id: Id214e0a9261c1f14de13864c715cf1a9d415e1e7 Signed-off-by: Harshdeep Dhatt --- drivers/gpu/msm/adreno_a6xx_gmu.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/msm/adreno_a6xx_gmu.c b/drivers/gpu/msm/adreno_a6xx_gmu.c index 3b2951f2be1d..59a54ea76e45 100644 --- a/drivers/gpu/msm/adreno_a6xx_gmu.c +++ b/drivers/gpu/msm/adreno_a6xx_gmu.c @@ -351,10 +351,6 @@ static int a6xx_gmu_start(struct kgsl_device *device) mask = 0xFFFFFFFF; } - /* Set the log wptr index */ - gmu_core_regwrite(device, A6XX_GPU_GMU_CX_GMU_PWR_COL_CP_RESP, - gmu->log_wptr_retention); - /* Bring GMU out of reset */ gmu_core_regwrite(device, A6XX_GMU_CM3_SYSRESET, 0); @@ -1069,6 +1065,18 @@ static int a6xx_gmu_fw_start(struct kgsl_device *device, */ gmu_core_regwrite(device, A6XX_GMU_CM3_CFG, 0x4052); + /** + * We may have asserted gbif halt as part of reset sequence which may + * not get cleared if the gdsc was not reset. So clear it before + * attempting GMU boot. + */ + if (!adreno_is_a630(ADRENO_DEVICE(device))) + kgsl_regwrite(device, A6XX_GBIF_HALT, 0x0); + + /* Set the log wptr index */ + gmu_core_regwrite(device, A6XX_GPU_GMU_CX_GMU_PWR_COL_CP_RESP, + gmu->log_wptr_retention); + /* Pass chipid to GMU FW, must happen before starting GMU */ /* Keep Core and Major bitfields unchanged */ From 75a9117cadc406e4424bf70fa705e8dcbbc5b46d Mon Sep 17 00:00:00 2001 From: Harshdeep Dhatt Date: Tue, 22 Oct 2019 08:44:04 -0700 Subject: [PATCH 2/3] msm: kgsl: Keep a copy of CP INIT cmdstream This way, we don't have to do checks when composing the CP INIT cmdstream. This will also be used by eCP. Change-Id: I91dc54b18aee0443d5a2724daeaadc5224de1a92 Signed-off-by: Harshdeep Dhatt --- drivers/gpu/msm/adreno.c | 9 ++-- drivers/gpu/msm/adreno.h | 5 +- drivers/gpu/msm/adreno_a3xx.c | 72 ++++++++++++++++++--------- drivers/gpu/msm/adreno_a5xx.c | 93 ++++++++++++++++++++--------------- drivers/gpu/msm/adreno_a6xx.c | 65 ++++++++++++++---------- 5 files changed, 149 insertions(+), 95 deletions(-) diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index 231f6900e610..cee8713fa102 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -1830,6 +1830,12 @@ static int adreno_init(struct kgsl_device *device) if (ret) return ret; + if (gpudev->init != NULL) { + ret = gpudev->init(adreno_dev); + if (ret) + return ret; + } + ret = gmu_core_init(device); if (ret) return ret; @@ -1853,9 +1859,6 @@ static int adreno_init(struct kgsl_device *device) if (ADRENO_GPUREV(adreno_dev) < 600) kgsl_pwrctrl_change_state(device, KGSL_STATE_SLUMBER); - if (gpudev->init != NULL) - gpudev->init(adreno_dev); - set_bit(ADRENO_DEVICE_INITIALIZED, &adreno_dev->priv); /* diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h index d27f151a6e3f..c9018adad2a0 100644 --- a/drivers/gpu/msm/adreno.h +++ b/drivers/gpu/msm/adreno.h @@ -536,7 +536,8 @@ struct adreno_device { * @critpkts: Memory descriptor for 5xx secure critical packets */ struct kgsl_memdesc *critpkts_secure; - + /** @cp_init_cmds: A copy of the CP INIT commands */ + const void *cp_init_cmds; }; /** @@ -776,7 +777,7 @@ struct adreno_gpudev { void (*snapshot)(struct adreno_device *adreno_dev, struct kgsl_snapshot *snapshot); void (*platform_setup)(struct adreno_device *adreno_dev); - void (*init)(struct adreno_device *adreno_dev); + int (*init)(struct adreno_device *adreno_dev); void (*remove)(struct adreno_device *adreno_dev); int (*rb_start)(struct adreno_device *adreno_dev); int (*microcode_read)(struct adreno_device *adreno_dev); diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c index 60aff4b7321a..275613cdfea9 100644 --- a/drivers/gpu/msm/adreno_a3xx.c +++ b/drivers/gpu/msm/adreno_a3xx.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. */ #include @@ -124,6 +124,8 @@ static const unsigned int _a3xx_pwron_fixup_fs_instructions[] = { 0x00000000, 0x03000000, 0x00000000, 0x00000000, }; +static int a3xx_get_cp_init_cmds(struct adreno_device *adreno_dev); + static void a3xx_efuse_speed_bin(struct adreno_device *adreno_dev) { unsigned int val; @@ -623,28 +625,7 @@ static int a3xx_send_me_init(struct adreno_device *adreno_dev, if (cmds == NULL) return -ENOSPC; - *cmds++ = cp_type3_packet(CP_ME_INIT, 17); - - *cmds++ = 0x000003f7; - *cmds++ = 0x00000000; - *cmds++ = 0x00000000; - *cmds++ = 0x00000000; - *cmds++ = 0x00000080; - *cmds++ = 0x00000100; - *cmds++ = 0x00000180; - *cmds++ = 0x00006600; - *cmds++ = 0x00000150; - *cmds++ = 0x0000014e; - *cmds++ = 0x00000154; - *cmds++ = 0x00000001; - *cmds++ = 0x00000000; - *cmds++ = 0x00000000; - - /* Enable protected mode registers for A3XX */ - *cmds++ = 0x20000000; - - *cmds++ = 0x00000000; - *cmds++ = 0x00000000; + memcpy(cmds, adreno_dev->cp_init_cmds, 18 << 2); ret = adreno_ringbuffer_submit_spin(rb, NULL, 2000); if (ret) { @@ -685,13 +666,56 @@ static int a3xx_rb_start(struct adreno_device *adreno_dev) return a3xx_send_me_init(adreno_dev, rb); } +static int a3xx_get_cp_init_cmds(struct adreno_device *adreno_dev) +{ + struct kgsl_device *device = KGSL_DEVICE(adreno_dev); + u32 *cmds; + + if (adreno_dev->cp_init_cmds) + return 0; + + adreno_dev->cp_init_cmds = devm_kzalloc(&device->pdev->dev, 18 << 2, + GFP_KERNEL); + if (!adreno_dev->cp_init_cmds) + return -ENOMEM; + + cmds = (u32 *)adreno_dev->cp_init_cmds; + + *cmds++ = cp_type3_packet(CP_ME_INIT, 17); + + *cmds++ = 0x000003f7; + *cmds++ = 0x00000000; + *cmds++ = 0x00000000; + *cmds++ = 0x00000000; + *cmds++ = 0x00000080; + *cmds++ = 0x00000100; + *cmds++ = 0x00000180; + *cmds++ = 0x00006600; + *cmds++ = 0x00000150; + *cmds++ = 0x0000014e; + *cmds++ = 0x00000154; + *cmds++ = 0x00000001; + *cmds++ = 0x00000000; + *cmds++ = 0x00000000; + + /* Enable protected mode registers for A3XX */ + *cmds++ = 0x20000000; + + *cmds++ = 0x00000000; + *cmds++ = 0x00000000; + + return 0; +} + /* * a3xx_init() - Initialize gpu specific data * @adreno_dev: Pointer to adreno device */ -static void a3xx_init(struct adreno_device *adreno_dev) +static int a3xx_init(struct adreno_device *adreno_dev) { _a3xx_pwron_fixup(adreno_dev); + + return a3xx_get_cp_init_cmds(adreno_dev); } /* diff --git a/drivers/gpu/msm/adreno_a5xx.c b/drivers/gpu/msm/adreno_a5xx.c index 176382b9dcf3..f0804cd7a87d 100644 --- a/drivers/gpu/msm/adreno_a5xx.c +++ b/drivers/gpu/msm/adreno_a5xx.c @@ -25,6 +25,7 @@ static int _read_fw2_block_header(struct kgsl_device *device, uint32_t id, uint32_t major, uint32_t minor); static void a5xx_gpmu_reset(struct work_struct *work); static int a5xx_gpmu_init(struct adreno_device *adreno_dev); +static int a5xx_get_cp_init_cmds(struct adreno_device *adreno_dev); /** * Number of times to check if the regulator enabled before @@ -185,7 +186,7 @@ static int a5xx_critical_packet_construct(struct adreno_device *adreno_dev) return 0; } -static void a5xx_init(struct adreno_device *adreno_dev) +static int a5xx_init(struct adreno_device *adreno_dev) { const struct adreno_a5xx_core *a5xx_core = to_a5xx_core(adreno_dev); @@ -199,8 +200,9 @@ static void a5xx_init(struct adreno_device *adreno_dev) if (ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_CRITICAL_PACKETS)) a5xx_critical_packet_construct(adreno_dev); - a5xx_crashdump_init(adreno_dev); + + return a5xx_get_cp_init_cmds(adreno_dev); } const static struct { @@ -1739,42 +1741,6 @@ static int _me_init_ucode_workarounds(struct adreno_device *adreno_dev) CP_INIT_DEFAULT_RESET_STATE | \ CP_INIT_UCODE_WORKAROUND_MASK) -static void _set_ordinals(struct adreno_device *adreno_dev, - unsigned int *cmds, unsigned int count) -{ - unsigned int *start = cmds; - - /* Enabled ordinal mask */ - *cmds++ = CP_INIT_MASK; - - if (CP_INIT_MASK & CP_INIT_MAX_CONTEXT) - *cmds++ = 0x00000003; - - if (CP_INIT_MASK & CP_INIT_ERROR_DETECTION_CONTROL) - *cmds++ = 0x20000000; - - if (CP_INIT_MASK & CP_INIT_HEADER_DUMP) { - /* Header dump address */ - *cmds++ = 0x00000000; - /* Header dump enable and dump size */ - *cmds++ = 0x00000000; - } - - if (CP_INIT_MASK & CP_INIT_DRAWCALL_FILTER_RANGE) { - /* Start range */ - *cmds++ = 0x00000000; - /* End range (inclusive) */ - *cmds++ = 0x00000000; - } - - if (CP_INIT_MASK & CP_INIT_UCODE_WORKAROUND_MASK) - *cmds++ = _me_init_ucode_workarounds(adreno_dev); - - /* Pad rest of the cmds with 0's */ - while ((unsigned int)(cmds - start) < count) - *cmds++ = 0x0; -} - static int a5xx_critical_packet_submit(struct adreno_device *adreno_dev, struct adreno_ringbuffer *rb) { @@ -1800,6 +1766,53 @@ static int a5xx_critical_packet_submit(struct adreno_device *adreno_dev, return ret; } +static int a5xx_get_cp_init_cmds(struct adreno_device *adreno_dev) +{ + struct kgsl_device *device = KGSL_DEVICE(adreno_dev); + u32 *cmds, i = 0; + + if (adreno_dev->cp_init_cmds) + return 0; + + adreno_dev->cp_init_cmds = devm_kzalloc(&device->pdev->dev, 9 << 2, + GFP_KERNEL); + + if (!adreno_dev->cp_init_cmds) + return -ENOMEM; + + cmds = (u32 *)adreno_dev->cp_init_cmds; + + cmds[i++] = cp_type7_packet(CP_ME_INIT, 8); + + /* Enabled ordinal mask */ + cmds[i++] = CP_INIT_MASK; + + if (CP_INIT_MASK & CP_INIT_MAX_CONTEXT) + cmds[i++] = 0x00000003; + + if (CP_INIT_MASK & CP_INIT_ERROR_DETECTION_CONTROL) + cmds[i++] = 0x20000000; + + if (CP_INIT_MASK & CP_INIT_HEADER_DUMP) { + /* Header dump address */ + cmds[i++] = 0x00000000; + /* Header dump enable and dump size */ + cmds[i++] = 0x00000000; + } + + if (CP_INIT_MASK & CP_INIT_DRAWCALL_FILTER_RANGE) { + /* Start range */ + cmds[i++] = 0x00000000; + /* End range (inclusive) */ + cmds[i++] = 0x00000000; + } + + if (CP_INIT_MASK & CP_INIT_UCODE_WORKAROUND_MASK) + cmds[i++] = _me_init_ucode_workarounds(adreno_dev); + + return 0; +} + /* * a5xx_send_me_init() - Initialize ringbuffer * @adreno_dev: Pointer to adreno device @@ -1819,9 +1832,7 @@ static int a5xx_send_me_init(struct adreno_device *adreno_dev, if (cmds == NULL) return -ENOSPC; - *cmds++ = cp_type7_packet(CP_ME_INIT, 8); - - _set_ordinals(adreno_dev, cmds, 8); + memcpy(cmds, adreno_dev->cp_init_cmds, 9 << 2); ret = adreno_ringbuffer_submit_spin(rb, NULL, 2000); if (ret) diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c index 507bc290a6a9..9e28bf080fef 100644 --- a/drivers/gpu/msm/adreno_a6xx.c +++ b/drivers/gpu/msm/adreno_a6xx.c @@ -99,10 +99,11 @@ static u32 a612_pwrup_reglist[] = { A6XX_RBBM_PERFCTR_CNTL, }; -static void a6xx_init(struct adreno_device *adreno_dev) +static int a6xx_get_cp_init_cmds(struct adreno_device *adreno_dev); + +static int a6xx_init(struct adreno_device *adreno_dev) { const struct adreno_a6xx_core *a6xx_core = to_a6xx_core(adreno_dev); - struct kgsl_device *device = KGSL_DEVICE(adreno_dev); adreno_dev->highest_bank_bit = a6xx_core->highest_bank_bit; @@ -111,10 +112,16 @@ static void a6xx_init(struct adreno_device *adreno_dev) a6xx_crashdump_init(adreno_dev); - if (IS_ERR_OR_NULL(adreno_dev->pwrup_reglist)) - adreno_dev->pwrup_reglist = kgsl_allocate_global(device, - PAGE_SIZE, 0, KGSL_MEMDESC_PRIVILEGED, - "powerup_register_list"); + if (IS_ERR_OR_NULL(adreno_dev->pwrup_reglist)) { + adreno_dev->pwrup_reglist = + kgsl_allocate_global(KGSL_DEVICE(adreno_dev), + PAGE_SIZE, 0, KGSL_MEMDESC_PRIVILEGED, + "powerup_register_list"); + if (IS_ERR(adreno_dev->pwrup_reglist)) + return PTR_ERR(adreno_dev->pwrup_reglist); + } + + return a6xx_get_cp_init_cmds(adreno_dev); } static void a6xx_protect_init(struct adreno_device *adreno_dev) @@ -663,44 +670,54 @@ static int a6xx_microcode_load(struct adreno_device *adreno_dev) CP_INIT_OPERATION_MODE_MASK | \ CP_INIT_REGISTER_INIT_LIST_WITH_SPINLOCK) -static void _set_ordinals(struct adreno_device *adreno_dev, - unsigned int *cmds, unsigned int count) +static int a6xx_get_cp_init_cmds(struct adreno_device *adreno_dev) { - unsigned int *start = cmds; + struct kgsl_device *device = KGSL_DEVICE(adreno_dev); + u32 *cmds, i = 0; + + if (adreno_dev->cp_init_cmds) + return 0; + + adreno_dev->cp_init_cmds = devm_kzalloc(&device->pdev->dev, 12 << 2, + GFP_KERNEL); + if (!adreno_dev->cp_init_cmds) + return -ENOMEM; + + cmds = (u32 *)adreno_dev->cp_init_cmds; + + cmds[i++] = cp_type7_packet(CP_ME_INIT, 11); /* Enabled ordinal mask */ - *cmds++ = CP_INIT_MASK; + cmds[i++] = CP_INIT_MASK; if (CP_INIT_MASK & CP_INIT_MAX_CONTEXT) - *cmds++ = 0x00000003; + cmds[i++] = 0x00000003; if (CP_INIT_MASK & CP_INIT_ERROR_DETECTION_CONTROL) - *cmds++ = 0x20000000; + cmds[i++] = 0x20000000; if (CP_INIT_MASK & CP_INIT_HEADER_DUMP) { /* Header dump address */ - *cmds++ = 0x00000000; + cmds[i++] = 0x00000000; /* Header dump enable and dump size */ - *cmds++ = 0x00000000; + cmds[i++] = 0x00000000; } if (CP_INIT_MASK & CP_INIT_UCODE_WORKAROUND_MASK) - *cmds++ = 0x00000000; + cmds[i++] = 0x00000000; if (CP_INIT_MASK & CP_INIT_OPERATION_MODE_MASK) - *cmds++ = 0x00000002; + cmds[i++] = 0x00000002; if (CP_INIT_MASK & CP_INIT_REGISTER_INIT_LIST_WITH_SPINLOCK) { uint64_t gpuaddr = adreno_dev->pwrup_reglist->gpuaddr; - *cmds++ = lower_32_bits(gpuaddr); - *cmds++ = upper_32_bits(gpuaddr); - *cmds++ = 0; + cmds[i++] = lower_32_bits(gpuaddr); + cmds[i++] = upper_32_bits(gpuaddr); + cmds[i++] = 0; } - /* Pad rest of the cmds with 0's */ - while ((unsigned int)(cmds - start) < count) - *cmds++ = 0x0; + return 0; } /* @@ -721,9 +738,7 @@ static int a6xx_send_cp_init(struct adreno_device *adreno_dev, if (IS_ERR(cmds)) return PTR_ERR(cmds); - *cmds++ = cp_type7_packet(CP_ME_INIT, 11); - - _set_ordinals(adreno_dev, cmds, 11); + memcpy(cmds, adreno_dev->cp_init_cmds, 12 << 2); ret = adreno_ringbuffer_submit_spin(rb, NULL, 2000); if (ret) { From be60d9a000f20ef32564d519d8097efe94c0fb2c Mon Sep 17 00:00:00 2001 From: Harshdeep Dhatt Date: Wed, 12 Feb 2020 17:05:18 -0700 Subject: [PATCH 3/3] msm: kgsl: Set bus scaling function during gmu probe When setting the bus scaling function, we are checking for gmu based targets before gmu has probed. Simplify this by setting the bus scaling function to interconnect by default. Then, replace it with gmu based routine during gmu probe. This works because only gmu based targets set bus votes via gmu. Change-Id: Ib332e736b39e0f38b1028049422ba95bd0370839 Signed-off-by: Harshdeep Dhatt --- drivers/gpu/msm/kgsl_bus.c | 19 +------------------ drivers/gpu/msm/kgsl_gmu.c | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/msm/kgsl_bus.c b/drivers/gpu/msm/kgsl_bus.c index 8d0aafbc7d77..bddf3de31e97 100644 --- a/drivers/gpu/msm/kgsl_bus.c +++ b/drivers/gpu/msm/kgsl_bus.c @@ -10,20 +10,6 @@ #include "kgsl_device.h" #include "kgsl_trace.h" -static int gmu_bus_set(struct kgsl_device *device, int buslevel, - u32 ab) -{ - struct kgsl_pwrctrl *pwr = &device->pwrctrl; - int ret; - - ret = gmu_core_dcvs_set(device, INVALID_DCVS_IDX, buslevel); - - if (!ret) - icc_set_bw(pwr->icc_path, MBps_to_icc(ab), 0); - - return ret; -} - static int interconnect_bus_set(struct kgsl_device *device, int level, u32 ab) { @@ -179,10 +165,7 @@ done: return PTR_ERR(pwr->icc_path); } - if (gmu_core_scales_bandwidth(device)) - pwr->bus_set = gmu_bus_set; - else - pwr->bus_set = interconnect_bus_set; + pwr->bus_set = interconnect_bus_set; return 0; } diff --git a/drivers/gpu/msm/kgsl_gmu.c b/drivers/gpu/msm/kgsl_gmu.c index d3961bf1b067..7d1c93a5e7bc 100644 --- a/drivers/gpu/msm/kgsl_gmu.c +++ b/drivers/gpu/msm/kgsl_gmu.c @@ -1282,6 +1282,20 @@ static void gmu_acd_probe(struct kgsl_device *device, struct gmu_device *gmu, "AOP mailbox init failed: %d\n", ret); } +static int gmu_bus_set(struct kgsl_device *device, int buslevel, + u32 ab) +{ + struct kgsl_pwrctrl *pwr = &device->pwrctrl; + int ret; + + ret = gmu_core_dcvs_set(device, INVALID_DCVS_IDX, buslevel); + + if (!ret) + icc_set_bw(pwr->icc_path, MBps_to_icc(ab), 0); + + return ret; +} + /* Do not access any GMU registers in GMU probe function */ static int gmu_probe(struct kgsl_device *device, struct device_node *node) { @@ -1409,6 +1423,9 @@ static int gmu_probe(struct kgsl_device *device, struct device_node *node) gmu_acd_probe(device, gmu, node); + if (gmu_core_scales_bandwidth(device)) + pwr->bus_set = gmu_bus_set; + set_bit(GMU_ENABLED, &device->gmu_core.flags); device->gmu_core.dev_ops = &adreno_a6xx_gmudev;