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 6dcbea9f5a84..6c951bc26c16 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) @@ -671,44 +678,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; } /* @@ -729,9 +746,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) { 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 */ 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;