Loading drivers/gpu/msm/adreno.c +42 −1 Original line number Diff line number Diff line Loading @@ -3111,9 +3111,50 @@ static void adreno_regwrite(struct kgsl_device *device, __raw_writel(value, reg); } /** * adreno_gmu_clear_and_unmask_irqs() - Clear pending IRQs and Unmask IRQs * @adreno_dev: Pointer to the Adreno device that owns the GMU */ void adreno_gmu_clear_and_unmask_irqs(struct adreno_device *adreno_dev) { struct kgsl_device *device = KGSL_DEVICE(adreno_dev); struct gmu_dev_ops *gmu_dev_ops = GMU_DEVICE_OPS(device); /* Clear any pending IRQs before unmasking on GMU */ adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_GMU2HOST_INTR_CLR, 0xFFFFFFFF); adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_AO_HOST_INTERRUPT_CLR, 0xFFFFFFFF); /* Unmask needed IRQs on GMU */ adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_GMU2HOST_INTR_MASK, (unsigned int) ~(gmu_dev_ops->gmu2host_intr_mask)); adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_AO_HOST_INTERRUPT_MASK, (unsigned int) ~(gmu_dev_ops->gmu_ao_intr_mask)); } /** * adreno_gmu_mask_and_clear_irqs() - Mask all IRQs and clear pending IRQs * @adreno_dev: Pointer to the Adreno device that owns the GMU */ void adreno_gmu_mask_and_clear_irqs(struct adreno_device *adreno_dev) { /* Mask all IRQs on GMU */ adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_AO_HOST_INTERRUPT_MASK, 0xFFFFFFFF); adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_GMU2HOST_INTR_MASK, 0xFFFFFFFF); /* Clear any pending IRQs before disabling */ adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_AO_HOST_INTERRUPT_CLR, 0xFFFFFFFF); adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_GMU2HOST_INTR_CLR, 0xFFFFFFFF); } /* * adreno_gmu_fenced_write() - Check if there is a GMU and it is enabled * @adreno_dev: Pointer to the Adreno device device that owns the GMU * @adreno_dev: Pointer to the Adreno device that owns the GMU * @offset: 32bit register enum that is to be written * @val: The value to be written to the register * @fence_mask: The value to poll the fence status register Loading drivers/gpu/msm/adreno.h +2 −1 Original line number Diff line number Diff line Loading @@ -1935,7 +1935,8 @@ static inline void adreno_deassert_gbif_halt(struct adreno_device *adreno_dev) if (adreno_has_gbif(adreno_dev)) adreno_writereg(adreno_dev, ADRENO_REG_GBIF_HALT, 0x0); } void adreno_gmu_clear_and_unmask_irqs(struct adreno_device *adreno_dev); void adreno_gmu_mask_and_clear_irqs(struct adreno_device *adreno_dev); int adreno_gmu_fenced_write(struct adreno_device *adreno_dev, enum adreno_regs offset, unsigned int val, unsigned int fence_mask); Loading drivers/gpu/msm/adreno_a6xx.c +41 −3 Original line number Diff line number Diff line Loading @@ -1123,6 +1123,44 @@ static int a6xx_rb_start(struct adreno_device *adreno_dev, return a6xx_post_start(adreno_dev); } /* * a6xx_sptprac_enable() - Power on SPTPRAC * @adreno_dev: Pointer to Adreno device */ static int a6xx_sptprac_enable(struct adreno_device *adreno_dev) { if (!adreno_has_sptprac_gdsc(adreno_dev)) return 0; return a6xx_gmu_sptprac_enable(adreno_dev); } /* * a6xx_sptprac_disable() - Power off SPTPRAC * @adreno_dev: Pointer to Adreno device */ static void a6xx_sptprac_disable(struct adreno_device *adreno_dev) { if (!adreno_has_sptprac_gdsc(adreno_dev)) return; a6xx_gmu_sptprac_disable(adreno_dev); } /* * a6xx_sptprac_is_on() - Check if SPTP is on using pwr status register * @adreno_dev - Pointer to adreno_device * This check should only be performed if the keepalive bit is set or it * can be guaranteed that the power state of the GPU will remain unchanged */ bool a6xx_sptprac_is_on(struct adreno_device *adreno_dev) { if (!adreno_has_sptprac_gdsc(adreno_dev)) return true; return a6xx_gmu_sptprac_is_on(adreno_dev); } unsigned int a6xx_set_marker( unsigned int *cmds, enum adreno_cp_marker_type type) { Loading Loading @@ -2813,8 +2851,8 @@ struct adreno_gpudev adreno_a6xx_gpudev = { .platform_setup = a6xx_platform_setup, .init = a6xx_init, .rb_start = a6xx_rb_start, .regulator_enable = a6xx_gmu_sptprac_enable, .regulator_disable = a6xx_gmu_sptprac_disable, .regulator_enable = a6xx_sptprac_enable, .regulator_disable = a6xx_sptprac_disable, .perfcounters = &a6xx_perfcounters, .enable_pwr_counters = a6xx_enable_pwr_counters, .count_throttles = a6xx_count_throttles, Loading @@ -2836,7 +2874,7 @@ struct adreno_gpudev adreno_a6xx_gpudev = { .preemption_context_init = a6xx_preemption_context_init, .preemption_context_destroy = a6xx_preemption_context_destroy, .gx_is_on = a6xx_gmu_gx_is_on, .sptprac_is_on = a6xx_gmu_sptprac_is_on, .sptprac_is_on = a6xx_sptprac_is_on, .ccu_invalidate = a6xx_ccu_invalidate, .perfcounter_update = a6xx_perfcounter_update, .coresight = {&a6xx_coresight, &a6xx_coresight_cx}, Loading drivers/gpu/msm/adreno_a6xx.h +62 −2 Original line number Diff line number Diff line Loading @@ -106,6 +106,68 @@ struct cpu_gpu_lock { #define A6XX_CP_RB_CNTL_DEFAULT (((ilog2(4) << 8) & 0x1F00) | \ (ilog2(KGSL_RB_DWORDS >> 1) & 0x3F)) /* * timed_poll_check() - polling *gmu* register at given offset until * its value changed to match expected value. The function times * out and returns after given duration if register is not updated * as expected. * * @device: Pointer to KGSL device * @offset: Register offset * @expected_ret: expected register value that stops polling * @timout: number of jiffies to abort the polling * @mask: bitmask to filter register value to match expected_ret */ static inline int timed_poll_check(struct kgsl_device *device, unsigned int offset, unsigned int expected_ret, unsigned int timeout, unsigned int mask) { unsigned long t; unsigned int value; t = jiffies + msecs_to_jiffies(timeout); do { gmu_core_regread(device, offset, &value); if ((value & mask) == expected_ret) return 0; /* Wait 100us to reduce unnecessary AHB bus traffic */ usleep_range(10, 100); } while (!time_after(jiffies, t)); /* Double check one last time */ gmu_core_regread(device, offset, &value); if ((value & mask) == expected_ret) return 0; return -ETIMEDOUT; } /* * read_AO_counter() - Returns the 64bit always on counter value * * @device: Pointer to KGSL device */ static inline uint64_t read_AO_counter(struct kgsl_device *device) { unsigned int l, h, h1; gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_H, &h); gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_L, &l); gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_H, &h1); /* * If there's no change in COUNTER_H we have no overflow so return, * otherwise read COUNTER_L again */ if (h == h1) return (uint64_t) l | ((uint64_t) h << 32); gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_L, &l); return (uint64_t) l | ((uint64_t) h1 << 32); } /* Preemption functions */ void a6xx_preemption_trigger(struct adreno_device *adreno_dev); void a6xx_preemption_schedule(struct adreno_device *adreno_dev); Loading @@ -131,8 +193,6 @@ void a6xx_snapshot(struct adreno_device *adreno_dev, struct kgsl_snapshot *snapshot); void a6xx_snapshot_debugbus(struct adreno_device *adreno_dev, struct kgsl_snapshot *snapshot); void a6xx_gmu_snapshot(struct adreno_device *adreno_dev, struct kgsl_snapshot *snapshot); void a6xx_crashdump_init(struct adreno_device *adreno_dev); int a6xx_gmu_sptprac_enable(struct adreno_device *adreno_dev); void a6xx_gmu_sptprac_disable(struct adreno_device *adreno_dev); Loading drivers/gpu/msm/adreno_a6xx_gmu.c +39 −70 Original line number Diff line number Diff line Loading @@ -11,9 +11,8 @@ * */ #include <linux/firmware.h> #include <soc/qcom/subsystem_restart.h> #include <linux/pm_opp.h> #include <linux/jiffies.h> #include <linux/interrupt.h> #include "kgsl_gmu_core.h" #include "kgsl_gmu.h" Loading Loading @@ -171,48 +170,13 @@ static void _load_gmu_rpmh_ucode(struct kgsl_device *device) wmb(); } /* GMU timeouts */ #define GMU_IDLE_TIMEOUT 100 /* ms */ #define GMU_START_TIMEOUT 100 /* ms */ #define GPU_START_TIMEOUT 100 /* ms */ #define GPU_RESET_TIMEOUT 1 /* ms */ #define GPU_RESET_TIMEOUT_US 10 /* us */ /* * timed_poll_check() - polling *gmu* register at given offset until * its value changed to match expected value. The function times * out and returns after given duration if register is not updated * as expected. * * @device: Pointer to KGSL device * @offset: Register offset * @expected_ret: expected register value that stops polling * @timout: number of jiffies to abort the polling * @mask: bitmask to filter register value to match expected_ret */ static int timed_poll_check(struct kgsl_device *device, unsigned int offset, unsigned int expected_ret, unsigned int timeout, unsigned int mask) { unsigned long t; unsigned int value; t = jiffies + msecs_to_jiffies(timeout); do { gmu_core_regread(device, offset, &value); if ((value & mask) == expected_ret) return 0; /* Wait 100us to reduce unnecessary AHB bus traffic */ usleep_range(10, 100); } while (!time_after(jiffies, t)); /* Double check one last time */ gmu_core_regread(device, offset, &value); if ((value & mask) == expected_ret) return 0; return -EINVAL; } /* * The lowest 16 bits of this value are the number of XO clock cycles * for main hysteresis. This is the first hysteresis. Here we set it Loading Loading @@ -334,26 +298,6 @@ static int a6xx_gmu_hfi_start(struct kgsl_device *device) return 0; } static uint64_t read_AO_counter(struct kgsl_device *device) { unsigned int l, h, h1; gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_H, &h); gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_L, &l); gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_H, &h1); /* * If there's no change in COUNTER_H we have no overflow so return, * otherwise read COUNTER_L again */ if (h == h1) return (uint64_t) l | ((uint64_t) h << 32); gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_L, &l); return (uint64_t) l | ((uint64_t) h1 << 32); } static int a6xx_rpmh_power_on_gpu(struct kgsl_device *device) { struct gmu_device *gmu = KGSL_GMU_DEVICE(device); Loading Loading @@ -621,6 +565,32 @@ static inline void a6xx_gmu_oob_clear(struct adreno_device *adreno_dev, trace_kgsl_gmu_oob_clear(clear); } static void a6xx_gmu_irq_enable(struct kgsl_device *device) { struct gmu_device *gmu = KGSL_GMU_DEVICE(device); struct kgsl_hfi *hfi = &gmu->hfi; /* Clear pending IRQs and Unmask needed IRQs */ adreno_gmu_clear_and_unmask_irqs(ADRENO_DEVICE(device)); /* Enable all IRQs on host */ enable_irq(hfi->hfi_interrupt_num); enable_irq(gmu->gmu_interrupt_num); } static void a6xx_gmu_irq_disable(struct kgsl_device *device) { struct gmu_device *gmu = KGSL_GMU_DEVICE(device); struct kgsl_hfi *hfi = &gmu->hfi; /* Disable all IRQs on host */ disable_irq(gmu->gmu_interrupt_num); disable_irq(hfi->hfi_interrupt_num); /* Mask all IRQs and clear pending IRQs */ adreno_gmu_mask_and_clear_irqs(ADRENO_DEVICE(device)); } static int a6xx_gmu_hfi_start_msg(struct adreno_device *adreno_dev) { struct kgsl_device *device = KGSL_DEVICE(adreno_dev); Loading Loading @@ -704,9 +674,6 @@ int a6xx_gmu_sptprac_enable(struct adreno_device *adreno_dev) if (!gmu_core_gpmu_isenabled(device)) return -EINVAL; if (!adreno_has_sptprac_gdsc(adreno_dev)) return 0; gmu_core_regwrite(device, A6XX_GMU_GX_SPTPRAC_POWER_CONTROL, SPTPRAC_POWERON_CTRL_MASK); Loading @@ -731,9 +698,6 @@ void a6xx_gmu_sptprac_disable(struct adreno_device *adreno_dev) struct kgsl_device *device = KGSL_DEVICE(adreno_dev); struct gmu_device *gmu = KGSL_GMU_DEVICE(device); if (!adreno_has_sptprac_gdsc(adreno_dev)) return; if (!gmu_core_gpmu_isenabled(device)) return; Loading Loading @@ -786,7 +750,7 @@ 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) || !adreno_has_sptprac_gdsc(adreno_dev)) if (!gmu_core_isenabled(device)) return true; gmu_core_regread(device, A6XX_GMU_SPTPRAC_PWR_CLK_STATUS, &val); Loading Loading @@ -901,6 +865,9 @@ static int a6xx_gmu_wait_for_idle(struct adreno_device *adreno_dev) return 0; } /* A6xx GMU FENCE RANGE MASK */ #define GMU_FENCE_RANGE_MASK ((0x1 << 31) | ((0xA << 2) << 18) | (0x8A0)) /* * a6xx_gmu_fw_start() - set up GMU and start FW * @device: Pointer to KGSL device Loading Loading @@ -958,7 +925,7 @@ static int a6xx_gmu_fw_start(struct kgsl_device *device, gmu_core_regwrite(device, A6XX_GMU_HFI_QTBL_INFO, 1); gmu_core_regwrite(device, A6XX_GMU_AHB_FENCE_RANGE_0, FENCE_RANGE_MASK); GMU_FENCE_RANGE_MASK); /* Pass chipid to GMU FW, must happen before starting GMU */ Loading Loading @@ -1389,7 +1356,7 @@ static size_t a6xx_snapshot_gmu_mem(struct kgsl_device *device, * This is where all of the A6XX GMU specific bits and pieces are grabbed * into the snapshot memory */ void a6xx_gmu_snapshot(struct adreno_device *adreno_dev, static void a6xx_gmu_snapshot(struct adreno_device *adreno_dev, struct kgsl_snapshot *snapshot) { struct kgsl_device *device = KGSL_DEVICE(adreno_dev); Loading Loading @@ -1432,14 +1399,16 @@ struct gmu_dev_ops adreno_a6xx_gmudev = { .load_firmware = a6xx_gmu_load_firmware, .oob_set = a6xx_gmu_oob_set, .oob_clear = a6xx_gmu_oob_clear, .irq_enable = a6xx_gmu_irq_enable, .irq_disable = a6xx_gmu_irq_disable, .hfi_start_msg = a6xx_gmu_hfi_start_msg, .enable_lm = a6xx_gmu_enable_lm, .rpmh_gpu_pwrctrl = a6xx_gmu_rpmh_gpu_pwrctrl, .wait_for_lowest_idle = a6xx_gmu_wait_for_lowest_idle, .wait_for_gmu_idle = a6xx_gmu_wait_for_idle, .sptprac_enable = a6xx_gmu_sptprac_enable, .sptprac_disable = a6xx_gmu_sptprac_disable, .ifpc_store = a6xx_gmu_ifpc_store, .ifpc_show = a6xx_gmu_ifpc_show, .snapshot = a6xx_gmu_snapshot, .gmu2host_intr_mask = HFI_IRQ_MASK, .gmu_ao_intr_mask = GMU_AO_INT_MASK, }; Loading
drivers/gpu/msm/adreno.c +42 −1 Original line number Diff line number Diff line Loading @@ -3111,9 +3111,50 @@ static void adreno_regwrite(struct kgsl_device *device, __raw_writel(value, reg); } /** * adreno_gmu_clear_and_unmask_irqs() - Clear pending IRQs and Unmask IRQs * @adreno_dev: Pointer to the Adreno device that owns the GMU */ void adreno_gmu_clear_and_unmask_irqs(struct adreno_device *adreno_dev) { struct kgsl_device *device = KGSL_DEVICE(adreno_dev); struct gmu_dev_ops *gmu_dev_ops = GMU_DEVICE_OPS(device); /* Clear any pending IRQs before unmasking on GMU */ adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_GMU2HOST_INTR_CLR, 0xFFFFFFFF); adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_AO_HOST_INTERRUPT_CLR, 0xFFFFFFFF); /* Unmask needed IRQs on GMU */ adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_GMU2HOST_INTR_MASK, (unsigned int) ~(gmu_dev_ops->gmu2host_intr_mask)); adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_AO_HOST_INTERRUPT_MASK, (unsigned int) ~(gmu_dev_ops->gmu_ao_intr_mask)); } /** * adreno_gmu_mask_and_clear_irqs() - Mask all IRQs and clear pending IRQs * @adreno_dev: Pointer to the Adreno device that owns the GMU */ void adreno_gmu_mask_and_clear_irqs(struct adreno_device *adreno_dev) { /* Mask all IRQs on GMU */ adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_AO_HOST_INTERRUPT_MASK, 0xFFFFFFFF); adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_GMU2HOST_INTR_MASK, 0xFFFFFFFF); /* Clear any pending IRQs before disabling */ adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_AO_HOST_INTERRUPT_CLR, 0xFFFFFFFF); adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_GMU2HOST_INTR_CLR, 0xFFFFFFFF); } /* * adreno_gmu_fenced_write() - Check if there is a GMU and it is enabled * @adreno_dev: Pointer to the Adreno device device that owns the GMU * @adreno_dev: Pointer to the Adreno device that owns the GMU * @offset: 32bit register enum that is to be written * @val: The value to be written to the register * @fence_mask: The value to poll the fence status register Loading
drivers/gpu/msm/adreno.h +2 −1 Original line number Diff line number Diff line Loading @@ -1935,7 +1935,8 @@ static inline void adreno_deassert_gbif_halt(struct adreno_device *adreno_dev) if (adreno_has_gbif(adreno_dev)) adreno_writereg(adreno_dev, ADRENO_REG_GBIF_HALT, 0x0); } void adreno_gmu_clear_and_unmask_irqs(struct adreno_device *adreno_dev); void adreno_gmu_mask_and_clear_irqs(struct adreno_device *adreno_dev); int adreno_gmu_fenced_write(struct adreno_device *adreno_dev, enum adreno_regs offset, unsigned int val, unsigned int fence_mask); Loading
drivers/gpu/msm/adreno_a6xx.c +41 −3 Original line number Diff line number Diff line Loading @@ -1123,6 +1123,44 @@ static int a6xx_rb_start(struct adreno_device *adreno_dev, return a6xx_post_start(adreno_dev); } /* * a6xx_sptprac_enable() - Power on SPTPRAC * @adreno_dev: Pointer to Adreno device */ static int a6xx_sptprac_enable(struct adreno_device *adreno_dev) { if (!adreno_has_sptprac_gdsc(adreno_dev)) return 0; return a6xx_gmu_sptprac_enable(adreno_dev); } /* * a6xx_sptprac_disable() - Power off SPTPRAC * @adreno_dev: Pointer to Adreno device */ static void a6xx_sptprac_disable(struct adreno_device *adreno_dev) { if (!adreno_has_sptprac_gdsc(adreno_dev)) return; a6xx_gmu_sptprac_disable(adreno_dev); } /* * a6xx_sptprac_is_on() - Check if SPTP is on using pwr status register * @adreno_dev - Pointer to adreno_device * This check should only be performed if the keepalive bit is set or it * can be guaranteed that the power state of the GPU will remain unchanged */ bool a6xx_sptprac_is_on(struct adreno_device *adreno_dev) { if (!adreno_has_sptprac_gdsc(adreno_dev)) return true; return a6xx_gmu_sptprac_is_on(adreno_dev); } unsigned int a6xx_set_marker( unsigned int *cmds, enum adreno_cp_marker_type type) { Loading Loading @@ -2813,8 +2851,8 @@ struct adreno_gpudev adreno_a6xx_gpudev = { .platform_setup = a6xx_platform_setup, .init = a6xx_init, .rb_start = a6xx_rb_start, .regulator_enable = a6xx_gmu_sptprac_enable, .regulator_disable = a6xx_gmu_sptprac_disable, .regulator_enable = a6xx_sptprac_enable, .regulator_disable = a6xx_sptprac_disable, .perfcounters = &a6xx_perfcounters, .enable_pwr_counters = a6xx_enable_pwr_counters, .count_throttles = a6xx_count_throttles, Loading @@ -2836,7 +2874,7 @@ struct adreno_gpudev adreno_a6xx_gpudev = { .preemption_context_init = a6xx_preemption_context_init, .preemption_context_destroy = a6xx_preemption_context_destroy, .gx_is_on = a6xx_gmu_gx_is_on, .sptprac_is_on = a6xx_gmu_sptprac_is_on, .sptprac_is_on = a6xx_sptprac_is_on, .ccu_invalidate = a6xx_ccu_invalidate, .perfcounter_update = a6xx_perfcounter_update, .coresight = {&a6xx_coresight, &a6xx_coresight_cx}, Loading
drivers/gpu/msm/adreno_a6xx.h +62 −2 Original line number Diff line number Diff line Loading @@ -106,6 +106,68 @@ struct cpu_gpu_lock { #define A6XX_CP_RB_CNTL_DEFAULT (((ilog2(4) << 8) & 0x1F00) | \ (ilog2(KGSL_RB_DWORDS >> 1) & 0x3F)) /* * timed_poll_check() - polling *gmu* register at given offset until * its value changed to match expected value. The function times * out and returns after given duration if register is not updated * as expected. * * @device: Pointer to KGSL device * @offset: Register offset * @expected_ret: expected register value that stops polling * @timout: number of jiffies to abort the polling * @mask: bitmask to filter register value to match expected_ret */ static inline int timed_poll_check(struct kgsl_device *device, unsigned int offset, unsigned int expected_ret, unsigned int timeout, unsigned int mask) { unsigned long t; unsigned int value; t = jiffies + msecs_to_jiffies(timeout); do { gmu_core_regread(device, offset, &value); if ((value & mask) == expected_ret) return 0; /* Wait 100us to reduce unnecessary AHB bus traffic */ usleep_range(10, 100); } while (!time_after(jiffies, t)); /* Double check one last time */ gmu_core_regread(device, offset, &value); if ((value & mask) == expected_ret) return 0; return -ETIMEDOUT; } /* * read_AO_counter() - Returns the 64bit always on counter value * * @device: Pointer to KGSL device */ static inline uint64_t read_AO_counter(struct kgsl_device *device) { unsigned int l, h, h1; gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_H, &h); gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_L, &l); gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_H, &h1); /* * If there's no change in COUNTER_H we have no overflow so return, * otherwise read COUNTER_L again */ if (h == h1) return (uint64_t) l | ((uint64_t) h << 32); gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_L, &l); return (uint64_t) l | ((uint64_t) h1 << 32); } /* Preemption functions */ void a6xx_preemption_trigger(struct adreno_device *adreno_dev); void a6xx_preemption_schedule(struct adreno_device *adreno_dev); Loading @@ -131,8 +193,6 @@ void a6xx_snapshot(struct adreno_device *adreno_dev, struct kgsl_snapshot *snapshot); void a6xx_snapshot_debugbus(struct adreno_device *adreno_dev, struct kgsl_snapshot *snapshot); void a6xx_gmu_snapshot(struct adreno_device *adreno_dev, struct kgsl_snapshot *snapshot); void a6xx_crashdump_init(struct adreno_device *adreno_dev); int a6xx_gmu_sptprac_enable(struct adreno_device *adreno_dev); void a6xx_gmu_sptprac_disable(struct adreno_device *adreno_dev); Loading
drivers/gpu/msm/adreno_a6xx_gmu.c +39 −70 Original line number Diff line number Diff line Loading @@ -11,9 +11,8 @@ * */ #include <linux/firmware.h> #include <soc/qcom/subsystem_restart.h> #include <linux/pm_opp.h> #include <linux/jiffies.h> #include <linux/interrupt.h> #include "kgsl_gmu_core.h" #include "kgsl_gmu.h" Loading Loading @@ -171,48 +170,13 @@ static void _load_gmu_rpmh_ucode(struct kgsl_device *device) wmb(); } /* GMU timeouts */ #define GMU_IDLE_TIMEOUT 100 /* ms */ #define GMU_START_TIMEOUT 100 /* ms */ #define GPU_START_TIMEOUT 100 /* ms */ #define GPU_RESET_TIMEOUT 1 /* ms */ #define GPU_RESET_TIMEOUT_US 10 /* us */ /* * timed_poll_check() - polling *gmu* register at given offset until * its value changed to match expected value. The function times * out and returns after given duration if register is not updated * as expected. * * @device: Pointer to KGSL device * @offset: Register offset * @expected_ret: expected register value that stops polling * @timout: number of jiffies to abort the polling * @mask: bitmask to filter register value to match expected_ret */ static int timed_poll_check(struct kgsl_device *device, unsigned int offset, unsigned int expected_ret, unsigned int timeout, unsigned int mask) { unsigned long t; unsigned int value; t = jiffies + msecs_to_jiffies(timeout); do { gmu_core_regread(device, offset, &value); if ((value & mask) == expected_ret) return 0; /* Wait 100us to reduce unnecessary AHB bus traffic */ usleep_range(10, 100); } while (!time_after(jiffies, t)); /* Double check one last time */ gmu_core_regread(device, offset, &value); if ((value & mask) == expected_ret) return 0; return -EINVAL; } /* * The lowest 16 bits of this value are the number of XO clock cycles * for main hysteresis. This is the first hysteresis. Here we set it Loading Loading @@ -334,26 +298,6 @@ static int a6xx_gmu_hfi_start(struct kgsl_device *device) return 0; } static uint64_t read_AO_counter(struct kgsl_device *device) { unsigned int l, h, h1; gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_H, &h); gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_L, &l); gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_H, &h1); /* * If there's no change in COUNTER_H we have no overflow so return, * otherwise read COUNTER_L again */ if (h == h1) return (uint64_t) l | ((uint64_t) h << 32); gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_L, &l); return (uint64_t) l | ((uint64_t) h1 << 32); } static int a6xx_rpmh_power_on_gpu(struct kgsl_device *device) { struct gmu_device *gmu = KGSL_GMU_DEVICE(device); Loading Loading @@ -621,6 +565,32 @@ static inline void a6xx_gmu_oob_clear(struct adreno_device *adreno_dev, trace_kgsl_gmu_oob_clear(clear); } static void a6xx_gmu_irq_enable(struct kgsl_device *device) { struct gmu_device *gmu = KGSL_GMU_DEVICE(device); struct kgsl_hfi *hfi = &gmu->hfi; /* Clear pending IRQs and Unmask needed IRQs */ adreno_gmu_clear_and_unmask_irqs(ADRENO_DEVICE(device)); /* Enable all IRQs on host */ enable_irq(hfi->hfi_interrupt_num); enable_irq(gmu->gmu_interrupt_num); } static void a6xx_gmu_irq_disable(struct kgsl_device *device) { struct gmu_device *gmu = KGSL_GMU_DEVICE(device); struct kgsl_hfi *hfi = &gmu->hfi; /* Disable all IRQs on host */ disable_irq(gmu->gmu_interrupt_num); disable_irq(hfi->hfi_interrupt_num); /* Mask all IRQs and clear pending IRQs */ adreno_gmu_mask_and_clear_irqs(ADRENO_DEVICE(device)); } static int a6xx_gmu_hfi_start_msg(struct adreno_device *adreno_dev) { struct kgsl_device *device = KGSL_DEVICE(adreno_dev); Loading Loading @@ -704,9 +674,6 @@ int a6xx_gmu_sptprac_enable(struct adreno_device *adreno_dev) if (!gmu_core_gpmu_isenabled(device)) return -EINVAL; if (!adreno_has_sptprac_gdsc(adreno_dev)) return 0; gmu_core_regwrite(device, A6XX_GMU_GX_SPTPRAC_POWER_CONTROL, SPTPRAC_POWERON_CTRL_MASK); Loading @@ -731,9 +698,6 @@ void a6xx_gmu_sptprac_disable(struct adreno_device *adreno_dev) struct kgsl_device *device = KGSL_DEVICE(adreno_dev); struct gmu_device *gmu = KGSL_GMU_DEVICE(device); if (!adreno_has_sptprac_gdsc(adreno_dev)) return; if (!gmu_core_gpmu_isenabled(device)) return; Loading Loading @@ -786,7 +750,7 @@ 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) || !adreno_has_sptprac_gdsc(adreno_dev)) if (!gmu_core_isenabled(device)) return true; gmu_core_regread(device, A6XX_GMU_SPTPRAC_PWR_CLK_STATUS, &val); Loading Loading @@ -901,6 +865,9 @@ static int a6xx_gmu_wait_for_idle(struct adreno_device *adreno_dev) return 0; } /* A6xx GMU FENCE RANGE MASK */ #define GMU_FENCE_RANGE_MASK ((0x1 << 31) | ((0xA << 2) << 18) | (0x8A0)) /* * a6xx_gmu_fw_start() - set up GMU and start FW * @device: Pointer to KGSL device Loading Loading @@ -958,7 +925,7 @@ static int a6xx_gmu_fw_start(struct kgsl_device *device, gmu_core_regwrite(device, A6XX_GMU_HFI_QTBL_INFO, 1); gmu_core_regwrite(device, A6XX_GMU_AHB_FENCE_RANGE_0, FENCE_RANGE_MASK); GMU_FENCE_RANGE_MASK); /* Pass chipid to GMU FW, must happen before starting GMU */ Loading Loading @@ -1389,7 +1356,7 @@ static size_t a6xx_snapshot_gmu_mem(struct kgsl_device *device, * This is where all of the A6XX GMU specific bits and pieces are grabbed * into the snapshot memory */ void a6xx_gmu_snapshot(struct adreno_device *adreno_dev, static void a6xx_gmu_snapshot(struct adreno_device *adreno_dev, struct kgsl_snapshot *snapshot) { struct kgsl_device *device = KGSL_DEVICE(adreno_dev); Loading Loading @@ -1432,14 +1399,16 @@ struct gmu_dev_ops adreno_a6xx_gmudev = { .load_firmware = a6xx_gmu_load_firmware, .oob_set = a6xx_gmu_oob_set, .oob_clear = a6xx_gmu_oob_clear, .irq_enable = a6xx_gmu_irq_enable, .irq_disable = a6xx_gmu_irq_disable, .hfi_start_msg = a6xx_gmu_hfi_start_msg, .enable_lm = a6xx_gmu_enable_lm, .rpmh_gpu_pwrctrl = a6xx_gmu_rpmh_gpu_pwrctrl, .wait_for_lowest_idle = a6xx_gmu_wait_for_lowest_idle, .wait_for_gmu_idle = a6xx_gmu_wait_for_idle, .sptprac_enable = a6xx_gmu_sptprac_enable, .sptprac_disable = a6xx_gmu_sptprac_disable, .ifpc_store = a6xx_gmu_ifpc_store, .ifpc_show = a6xx_gmu_ifpc_show, .snapshot = a6xx_gmu_snapshot, .gmu2host_intr_mask = HFI_IRQ_MASK, .gmu_ao_intr_mask = GMU_AO_INT_MASK, };