diff --git a/drivers/gpu/msm/adreno-gpulist.h b/drivers/gpu/msm/adreno-gpulist.h index 606837dd690a..544f80d98f8f 100644 --- a/drivers/gpu/msm/adreno-gpulist.h +++ b/drivers/gpu/msm/adreno-gpulist.h @@ -28,7 +28,6 @@ static const struct adreno_a3xx_core adreno_gpu_core_a306 = { .gpudev = &adreno_a3xx_gpudev, .gmem_base = 0, .gmem_size = SZ_128K, - .busy_mask = 0x7ffffffe, .bus_width = 0, .snapshot_size = 600 * SZ_1K, }, @@ -51,7 +50,6 @@ static const struct adreno_a3xx_core adreno_gpu_core_a306a = { .gpudev = &adreno_a3xx_gpudev, .gmem_base = 0, .gmem_size = SZ_128K, - .busy_mask = 0x7ffffffe, .bus_width = 16, .snapshot_size = 600 * SZ_1K, }, @@ -72,7 +70,6 @@ static const struct adreno_a3xx_core adreno_gpu_core_a304 = { .gpudev = &adreno_a3xx_gpudev, .gmem_base = 0, .gmem_size = (SZ_64K + SZ_32K), - .busy_mask = 0x7ffffffe, .bus_width = 0, .snapshot_size = 600 * SZ_1K, }, @@ -197,7 +194,6 @@ static const struct adreno_a5xx_core adreno_gpu_core_a530v2 = { .gpudev = &adreno_a5xx_gpudev, .gmem_base = 0x100000, .gmem_size = SZ_1M, - .busy_mask = 0xfffffffe, .bus_width = 32, .snapshot_size = SZ_1M, }, @@ -224,7 +220,6 @@ static const struct adreno_a5xx_core adreno_gpu_core_a530v3 = { .gpudev = &adreno_a5xx_gpudev, .gmem_base = 0x100000, .gmem_size = SZ_1M, - .busy_mask = 0xfffffffe, .bus_width = 32, .snapshot_size = SZ_1M, }, @@ -291,7 +286,6 @@ static const struct adreno_a5xx_core adreno_gpu_core_a505 = { .gpudev = &adreno_a5xx_gpudev, .gmem_base = 0x100000, .gmem_size = (SZ_128K + SZ_8K), - .busy_mask = 0xfffffffe, .bus_width = 16, .snapshot_size = SZ_1M, }, @@ -311,7 +305,6 @@ static const struct adreno_a5xx_core adreno_gpu_core_a506 = { .gpudev = &adreno_a5xx_gpudev, .gmem_base = 0x100000, .gmem_size = (SZ_128K + SZ_8K), - .busy_mask = 0xfffffffe, .bus_width = 16, .snapshot_size = SZ_1M, }, @@ -390,7 +383,6 @@ static const struct adreno_a5xx_core adreno_gpu_core_a510 = { .gpudev = &adreno_a5xx_gpudev, .gmem_base = 0x100000, .gmem_size = SZ_256K, - .busy_mask = 0xfffffffe, .bus_width = 16, .snapshot_size = SZ_1M, }, @@ -516,7 +508,6 @@ static const struct adreno_a5xx_core adreno_gpu_core_a540v2 = { .gpudev = &adreno_a5xx_gpudev, .gmem_base = 0x100000, .gmem_size = SZ_1M, - .busy_mask = 0xfffffffe, .bus_width = 32, .snapshot_size = SZ_1M, }, @@ -600,7 +591,6 @@ static const struct adreno_a5xx_core adreno_gpu_core_a512 = { .gpudev = &adreno_a5xx_gpudev, .gmem_base = 0x100000, .gmem_size = (SZ_256K + SZ_16K), - .busy_mask = 0xfffffffe, .bus_width = 32, .snapshot_size = SZ_1M, }, @@ -620,7 +610,6 @@ static const struct adreno_a5xx_core adreno_gpu_core_a508 = { .gpudev = &adreno_a5xx_gpudev, .gmem_base = 0x100000, .gmem_size = (SZ_128K + SZ_8K), - .busy_mask = 0xfffffffe, .bus_width = 32, .snapshot_size = SZ_1M, }, @@ -796,7 +785,6 @@ static const struct adreno_a6xx_core adreno_gpu_core_a630v2 = { .gpudev = &adreno_a6xx_gpudev, .gmem_base = 0x100000, .gmem_size = SZ_1M, - .busy_mask = 0xfffffffe, .bus_width = 32, .snapshot_size = SZ_1M, }, @@ -897,7 +885,6 @@ static const struct adreno_a6xx_core adreno_gpu_core_a615 = { .gpudev = &adreno_a6xx_gpudev, .gmem_base = 0x100000, .gmem_size = SZ_512K, - .busy_mask = 0xfffffffe, .bus_width = 32, .snapshot_size = 600 * SZ_1K, }, @@ -926,7 +913,6 @@ static const struct adreno_a6xx_core adreno_gpu_core_a618 = { .gpudev = &adreno_a6xx_gpudev, .gmem_base = 0x100000, .gmem_size = SZ_512K, - .busy_mask = 0xfffffffe, .bus_width = 32, .snapshot_size = SZ_1M, }, @@ -1056,7 +1042,6 @@ static const struct adreno_a6xx_core adreno_gpu_core_a620 = { .gpudev = &adreno_a6xx_gpudev, .gmem_base = 0, .gmem_size = SZ_512K, - .busy_mask = 0xfffffffe, .bus_width = 32, .snapshot_size = 2 * SZ_1M, }, @@ -1148,7 +1133,6 @@ static const struct adreno_a6xx_core adreno_gpu_core_a640 = { .gpudev = &adreno_a6xx_gpudev, .gmem_base = 0x100000, .gmem_size = SZ_1M, //Verified 1MB - .busy_mask = 0xfffffffe, .bus_width = 32, .snapshot_size = 2 * SZ_1M, }, @@ -1230,7 +1214,6 @@ static const struct adreno_a6xx_core adreno_gpu_core_a650 = { .gpudev = &adreno_a6xx_gpudev, .gmem_base = 0, .gmem_size = SZ_1M + SZ_128K, /* verified 1152kB */ - .busy_mask = 0xfffffffe, .bus_width = 32, .snapshot_size = 2 * SZ_1M, }, @@ -1261,7 +1244,6 @@ static const struct adreno_a6xx_core adreno_gpu_core_a650v2 = { .gpudev = &adreno_a6xx_gpudev, .gmem_base = 0, .gmem_size = SZ_1M + SZ_128K, /* verified 1152kB */ - .busy_mask = 0xfffffffe, .bus_width = 32, .snapshot_size = 2 * SZ_1M, }, @@ -1289,7 +1271,6 @@ static const struct adreno_a6xx_core adreno_gpu_core_a680 = { .gpudev = &adreno_a6xx_gpudev, .gmem_base = 0x100000, .gmem_size = SZ_2M, - .busy_mask = 0xfffffffe, .bus_width = 32, .snapshot_size = SZ_1M, }, @@ -1368,7 +1349,6 @@ static const struct adreno_a6xx_core adreno_gpu_core_a612 = { .gpudev = &adreno_a6xx_gpudev, .gmem_base = 0x100000, .gmem_size = (SZ_128K + SZ_4K), - .busy_mask = 0xfffffffe, .bus_width = 32, .snapshot_size = SZ_1M, }, @@ -1395,7 +1375,6 @@ static const struct adreno_a6xx_core adreno_gpu_core_a616 = { .gpudev = &adreno_a6xx_gpudev, .gmem_base = 0x100000, .gmem_size = SZ_512K, - .busy_mask = 0xfffffffe, .bus_width = 32, .snapshot_size = SZ_1M, }, @@ -1423,7 +1402,6 @@ static const struct adreno_a6xx_core adreno_gpu_core_a610 = { .gpudev = &adreno_a6xx_gpudev, .gmem_base = 0x100000, .gmem_size = (SZ_128K + SZ_4K), - .busy_mask = 0xfffffffe, .bus_width = 32, }, .prim_fifo_threshold = 0x00080000, @@ -1537,7 +1515,6 @@ static const struct adreno_a6xx_core adreno_gpu_core_a660 = { .gpudev = &adreno_a6xx_gpudev, .gmem_base = 0, .gmem_size = SZ_1M + SZ_512K, - .busy_mask = 0xfffffffe, .bus_width = 32, .snapshot_size = SZ_1M, }, diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index d0c81c13324a..6b6a5803b5b3 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -31,6 +31,7 @@ #include "adreno-gpulist.h" static void adreno_input_work(struct work_struct *work); +static int adreno_soft_reset(struct kgsl_device *device); static unsigned int counter_delta(struct kgsl_device *device, unsigned int reg, unsigned int *counter); @@ -500,7 +501,7 @@ static struct input_handler adreno_input_handler = { * all the HW logic, restores GPU registers to default state and * flushes out pending VBIF transactions. */ -static int _soft_reset(struct adreno_device *adreno_dev) +static void _soft_reset(struct adreno_device *adreno_dev) { struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); unsigned int reg; @@ -517,8 +518,6 @@ static int _soft_reset(struct adreno_device *adreno_dev) if (gpudev->regulator_enable) gpudev->regulator_enable(adreno_dev); - - return 0; } /** @@ -986,7 +985,7 @@ static void adreno_of_get_limits(struct adreno_device *adreno_dev, pwrctrl->throttle_mask = GENMASK(pwrctrl->num_pwrlevels - 1, pwrctrl->num_pwrlevels - 1 - throttle_level); - set_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag); + adreno_dev->lm_enabled = true; } static int adreno_of_get_legacy_pwrlevels(struct adreno_device *adreno_dev, @@ -1364,13 +1363,6 @@ static void adreno_setup_device(struct adreno_device *adreno_dev) INIT_WORK(&adreno_dev->input_work, adreno_input_work); - /* - * Enable SPTP power collapse, throttling and hardware clock gating by - * default where applicable - */ - adreno_dev->pwrctrl_flag = BIT(ADRENO_SPTP_PC_CTRL) | - BIT(ADRENO_THROTTLING_CTRL) | BIT(ADRENO_HWCG_CTRL); - INIT_LIST_HEAD(&adreno_dev->active_list); spin_lock_init(&adreno_dev->active_list_lock); @@ -2315,28 +2307,21 @@ no_gx_power: int adreno_reset(struct kgsl_device *device, int fault) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); int ret = -EINVAL; - int i = 0; + int i; + + if (gpudev->reset) + return gpudev->reset(device, fault); /* * Try soft reset first Do not do soft reset for a IOMMU fault (because - * the IOMMU hardware needs a reset too) or for the A304 because it - * can't do SMMU programming of any kind after a soft reset + * the IOMMU hardware needs a reset too) */ - if (!(fault & ADRENO_IOMMU_PAGE_FAULT) && !adreno_is_a304(adreno_dev) - && !adreno_is_a612(adreno_dev) && !adreno_is_a610(adreno_dev)) { - /* Make sure VBIF is cleared before resetting */ - ret = adreno_clear_pending_transactions(device); + if (!(fault & ADRENO_IOMMU_PAGE_FAULT)) + ret = adreno_soft_reset(device); - if (ret == 0) { - ret = adreno_soft_reset(device); - if (ret) - dev_err(device->dev, - "Device soft reset failed: ret=%d\n", - ret); - } - } if (ret) { /* If soft reset failed/skipped, then pull the power */ kgsl_pwrctrl_change_state(device, KGSL_STATE_INIT); @@ -2346,22 +2331,18 @@ int adreno_reset(struct kgsl_device *device, int fault) /* Try to reset the device */ ret = adreno_start(device, 0); - /* On some GPUS, keep trying until it works */ - if (ret && ADRENO_GPUREV(adreno_dev) < 600) { - for (i = 0; i < NUM_TIMES_RESET_RETRY; i++) { - msleep(20); - ret = adreno_start(device, 0); - if (!ret) - break; - } + for (i = 0; ret && i < NUM_TIMES_RESET_RETRY; i++) { + msleep(20); + ret = adreno_start(device, 0); } - } - if (ret) - return ret; - if (i != 0) - dev_warn(device->dev, + if (ret) + return ret; + + if (i != 0) + dev_warn(device->dev, "Device hard reset tried %d tries\n", i); + } /* * If active_cnt is non-zero then the system was active before @@ -2752,7 +2733,7 @@ static int adreno_setproperty(struct kgsl_device_private *dev_priv, * * Returns true if interrupts are pending from device else 0. */ -inline unsigned int adreno_irq_pending(struct adreno_device *adreno_dev) +bool adreno_irq_pending(struct adreno_device *adreno_dev) { unsigned int status; @@ -2767,67 +2748,37 @@ inline unsigned int adreno_irq_pending(struct adreno_device *adreno_dev) */ if ((status & adreno_dev->irq_mask) || atomic_read(&adreno_dev->pending_irq_refcnt)) - return 1; - else - return 0; + return true; + + return false; } - -/** - * adreno_hw_isidle() - Check if the GPU core is idle - * @adreno_dev: Pointer to the Adreno device structure for the GPU - * - * Return true if the RBBM status register for the GPU type indicates that the - * hardware is idle - */ -bool adreno_hw_isidle(struct adreno_device *adreno_dev) -{ - const struct adreno_gpu_core *gpucore = adreno_dev->gpucore; - unsigned int reg_rbbm_status; - struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); - - /* if hw driver implements idle check - use it */ - if (gpudev->hw_isidle) - return gpudev->hw_isidle(adreno_dev); - - if (adreno_is_a540(adreno_dev)) - /** - * Due to CRC idle throttling GPU - * idle hysteresys can take up to - * 3usec for expire - account for it - */ - udelay(5); - - adreno_readreg(adreno_dev, ADRENO_REG_RBBM_STATUS, - ®_rbbm_status); - - if (reg_rbbm_status & gpucore->busy_mask) - return false; - - /* Don't consider ourselves idle if there is an IRQ pending */ - if (adreno_irq_pending(adreno_dev)) - return false; - - return true; -} - -/** - * adreno_soft_reset() - Do a soft reset of the GPU hardware +/* + * adreno_soft_reset - Do a soft reset of the GPU hardware * @device: KGSL device to soft reset * * "soft reset" the GPU hardware - this is a fast path GPU reset * The GPU hardware is reset but we never pull power so we can skip * a lot of the standard adreno_stop/adreno_start sequence */ -int adreno_soft_reset(struct kgsl_device *device) +static int adreno_soft_reset(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); int ret; - ret = gmu_core_dev_oob_set(device, oob_gpu); - if (ret) + /* + * Don't allow a soft reset for a304 because the SMMU needs to be hard + * reset + */ + if (adreno_is_a304(adreno_dev)) + return -ENODEV; + + ret = adreno_clear_pending_transactions(device); + if (ret) { + dev_err(device->dev, "Timed out while clearing the VBIF\n"); return ret; + } kgsl_pwrctrl_change_state(device, KGSL_STATE_AWARE); adreno_set_active_ctxs_null(adreno_dev); @@ -2841,15 +2792,7 @@ int adreno_soft_reset(struct kgsl_device *device) /* save physical performance counter values before GPU soft reset */ adreno_perfcounter_save(adreno_dev); - /* Reset the GPU */ - if (gpudev->soft_reset) - ret = gpudev->soft_reset(adreno_dev); - else - ret = _soft_reset(adreno_dev); - if (ret) { - gmu_core_dev_oob_clear(device, oob_gpu); - return ret; - } + _soft_reset(adreno_dev); /* Clear the busy_data stats - we're starting over from scratch */ adreno_dev->busy_data.gpu_busy = 0; @@ -2889,25 +2832,19 @@ int adreno_soft_reset(struct kgsl_device *device) /* Restore physical performance counter values after soft reset */ adreno_perfcounter_restore(adreno_dev); - gmu_core_dev_oob_clear(device, oob_gpu); + if (ret) + dev_err(device->dev, "Device soft reset failed: %d\n", ret); return ret; } -/* - * adreno_isidle() - return true if the GPU hardware is idle - * @device: Pointer to the KGSL device structure for the GPU - * - * Return true if the GPU hardware is idle and there are no commands pending in - * the ringbuffer - */ -bool adreno_isidle(struct kgsl_device *device) +static bool adreno_isidle(struct adreno_device *adreno_dev) { - struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); struct adreno_ringbuffer *rb; int i; - if (!kgsl_state_is_awake(device)) + if (!kgsl_state_is_awake(KGSL_DEVICE(adreno_dev))) return true; /* @@ -2926,7 +2863,7 @@ bool adreno_isidle(struct kgsl_device *device) return false; } - return adreno_hw_isidle(adreno_dev); + return gpudev->hw_isidle(adreno_dev); } /* Print some key registers if a spin-for-idle times out */ @@ -2987,7 +2924,7 @@ int adreno_spin_idle(struct adreno_device *adreno_dev, unsigned int timeout) if (adreno_gpu_fault(adreno_dev) != 0) return -EDEADLK; - if (adreno_isidle(KGSL_DEVICE(adreno_dev))) + if (adreno_isidle(adreno_dev)) return 0; } while (time_before(jiffies, wait)); @@ -3000,7 +2937,7 @@ int adreno_spin_idle(struct adreno_device *adreno_dev, unsigned int timeout) if (adreno_gpu_fault(adreno_dev) != 0) return -EDEADLK; - if (adreno_isidle(KGSL_DEVICE(adreno_dev))) + if (adreno_isidle(adreno_dev)) return 0; return -ETIMEDOUT; @@ -3028,7 +2965,7 @@ int adreno_idle(struct kgsl_device *device) return -EDEADLK; /* Check if we are already idle before idling dispatcher */ - if (adreno_isidle(device)) + if (adreno_isidle(adreno_dev)) return 0; /* * Wait for dispatcher to finish completing commands @@ -3725,7 +3662,7 @@ static bool adreno_is_hw_collapsible(struct kgsl_device *device) device->pwrctrl.ctrl_flags) return false; - return adreno_isidle(device) && (gpudev->is_sptp_idle ? + return adreno_isidle(adreno_dev) && (gpudev->is_sptp_idle ? gpudev->is_sptp_idle(adreno_dev) : true); } @@ -3789,7 +3726,7 @@ static bool adreno_is_hwcg_on(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); - return test_bit(ADRENO_HWCG_CTRL, &adreno_dev->pwrctrl_flag); + return adreno_dev->hwcg_enabled; } static int adreno_queue_cmds(struct kgsl_device_private *dev_priv, @@ -3811,7 +3748,6 @@ static const struct kgsl_functable adreno_functable = { .regread = adreno_regread, .regwrite = adreno_regwrite, .idle = adreno_idle, - .isidle = adreno_isidle, .suspend_context = adreno_suspend_context, .first_open = adreno_first_open, .start = adreno_start, diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h index 3384128e3937..aeef52bd585a 100644 --- a/drivers/gpu/msm/adreno.h +++ b/drivers/gpu/msm/adreno.h @@ -206,12 +206,6 @@ enum adreno_gpurev { #define ADRENO_CTX_DETATCH_TIMEOUT_FAULT BIT(6) #define ADRENO_GMU_FAULT_SKIP_SNAPSHOT BIT(7) -#define ADRENO_SPTP_PC_CTRL 0 -#define ADRENO_LM_CTRL 1 -#define ADRENO_HWCG_CTRL 2 -#define ADRENO_THROTTLING_CTRL 3 -#define ADRENO_ACD_CTRL 4 - /* VBIF, GBIF halt request and ack mask */ #define GBIF_HALT_REQUEST 0x1E0 #define VBIF_RESET_ACK_MASK 0x00f0 @@ -340,7 +334,6 @@ struct adreno_reglist { * @gpudev: Pointer to the GPU family specific functions for this core * @gmem_base: Base address of binning memory (GMEM/OCMEM) * @gmem_size: Amount of binning memory (GMEM/OCMEM) to reserve for the core - * @busy_mask: mask to check if GPU is busy in RBBM_STATUS * @bus_width: Bytes transferred in 1 cycle */ struct adreno_gpu_core { @@ -350,7 +343,6 @@ struct adreno_gpu_core { struct adreno_gpudev *gpudev; unsigned long gmem_base; size_t gmem_size; - unsigned int busy_mask; u32 bus_width; /** @snapshot_size: Size of the static snapshot region in bytes */ u32 snapshot_size; @@ -413,7 +405,6 @@ struct adreno_gpu_core { * @halt: Atomic variable to check whether the GPU is currently halted * @pending_irq_refcnt: Atomic variable to keep track of running IRQ handlers * @ctx_d_debugfs: Context debugfs node - * @pwrctrl_flag: Flag to hold adreno specific power attributes * @profile_buffer: Memdesc holding the drawobj profiling buffer * @profile_index: Index to store the start/stop ticks in the profiling * buffer @@ -485,8 +476,16 @@ struct adreno_device { atomic_t halt; atomic_t pending_irq_refcnt; struct dentry *ctx_d_debugfs; - unsigned long pwrctrl_flag; - + /** @lm_enabled: True if limits management is enabled for this target */ + bool lm_enabled; + /** @acd_enabled: True if acd is enabled for this target */ + bool acd_enabled; + /** @hwcg_enabled: True if hardware clock gating is enabled */ + bool hwcg_enabled; + /** @throttling_enabled: True if LM throttling is enabled on a5xx */ + bool throttling_enabled; + /** @sptp_pc_enabled: True if SPTP power collapse is enabled on a5xx */ + bool sptp_pc_enabled; struct kgsl_memdesc *profile_buffer; unsigned int profile_index; struct kgsl_memdesc *pwrup_reglist; @@ -643,8 +642,6 @@ enum adreno_regs { ADRENO_REG_RBBM_INT_0_STATUS, ADRENO_REG_RBBM_PM_OVERRIDE2, ADRENO_REG_RBBM_SW_RESET_CMD, - ADRENO_REG_RBBM_BLOCK_SW_RESET_CMD, - ADRENO_REG_RBBM_BLOCK_SW_RESET_CMD2, ADRENO_REG_RBBM_CLOCK_CTL, ADRENO_REG_PA_SC_AA_CONFIG, ADRENO_REG_SQ_GPR_MANAGEMENT, @@ -789,7 +786,6 @@ struct adreno_gpudev { const char *(*iommu_fault_block)(struct kgsl_device *device, unsigned int fsynr1); int (*reset)(struct kgsl_device *device, int fault); - int (*soft_reset)(struct adreno_device *adreno_dev); bool (*sptprac_is_on)(struct adreno_device *adreno_dev); unsigned int (*ccu_invalidate)(struct adreno_device *adreno_dev, unsigned int *cmds); @@ -871,7 +867,6 @@ extern int adreno_wake_nice; extern unsigned int adreno_wake_timeout; int adreno_start(struct kgsl_device *device, int priority); -int adreno_soft_reset(struct kgsl_device *device); long adreno_ioctl(struct kgsl_device_private *dev_priv, unsigned int cmd, unsigned long arg); @@ -893,7 +888,6 @@ int adreno_switch_to_unsecure_mode(struct adreno_device *adreno_dev, void adreno_spin_idle_debug(struct adreno_device *adreno_dev, const char *str); int adreno_spin_idle(struct adreno_device *device, unsigned int timeout); int adreno_idle(struct kgsl_device *device); -bool adreno_isidle(struct kgsl_device *device); int adreno_set_constraint(struct kgsl_device *device, struct kgsl_context *context, @@ -909,8 +903,6 @@ void adreno_fault_skipcmd_detached(struct adreno_device *adreno_dev, struct adreno_context *drawctxt, struct kgsl_drawobj *drawobj); -bool adreno_hw_isidle(struct adreno_device *adreno_dev); - void adreno_fault_detect_start(struct adreno_device *adreno_dev); void adreno_fault_detect_stop(struct adreno_device *adreno_dev); @@ -950,6 +942,13 @@ void adreno_rscc_regread(struct adreno_device *adreno_dev, void adreno_isense_regread(struct adreno_device *adreno_dev, unsigned int offsetwords, unsigned int *value); +/** + * adreno_irq_pending - Return true if an interrupt is pending + * @adreno_dev: An Adreno GPU device handle + * + * Returns: true if interrupts are pending on the device + */ +bool adreno_irq_pending(struct adreno_device *adreno_dev); #define ADRENO_TARGET(_name, _id) \ static inline int adreno_is_##_name(struct adreno_device *adreno_dev) \ diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c index 150af9a93ff5..a36d2b74e598 100644 --- a/drivers/gpu/msm/adreno_a3xx.c +++ b/drivers/gpu/msm/adreno_a3xx.c @@ -1381,6 +1381,19 @@ static irqreturn_t a3xx_irq_handler(struct adreno_device *adreno_dev) return ret; } +static bool a3xx_hw_isidle(struct adreno_device *adreno_dev) +{ + struct kgsl_device *device = KGSL_DEVICE(adreno_dev); + u32 status; + + kgsl_regread(device, A3XX_RBBM_STATUS, &status); + + if (status & 0x7ffffffe) + return false; + + return adreno_irq_pending(adreno_dev) ? false : true; +} + struct adreno_gpudev adreno_a3xx_gpudev = { .reg_offsets = a3xx_register_offsets, .ft_perf_counters = a3xx_ft_perf_counters, @@ -1399,4 +1412,5 @@ struct adreno_gpudev adreno_a3xx_gpudev = { #endif .clk_set_options = a3xx_clk_set_options, .read_alwayson = a3xx_read_alwayson, + .hw_isidle = a3xx_hw_isidle, }; diff --git a/drivers/gpu/msm/adreno_a5xx.c b/drivers/gpu/msm/adreno_a5xx.c index 661c3445ba6c..d7948be3b37c 100644 --- a/drivers/gpu/msm/adreno_a5xx.c +++ b/drivers/gpu/msm/adreno_a5xx.c @@ -89,7 +89,15 @@ static void a530_efuse_leakage(struct adreno_device *adreno_dev) static void a5xx_platform_setup(struct adreno_device *adreno_dev) { - set_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag); + adreno_dev->sptp_pc_enabled = + ADRENO_FEATURE(adreno_dev, ADRENO_SPTP_PC); + + if (adreno_is_a540(adreno_dev)) + adreno_dev->throttling_enabled = true; + + adreno_dev->hwcg_enabled = true; + adreno_dev->lm_enabled = + ADRENO_FEATURE(adreno_dev, ADRENO_LM); /* Set the GPU busy counter to use for frequency scaling */ adreno_dev->perfctr_pwr_lo = A5XX_RBBM_PERFCTR_RBBM_0_LO; @@ -261,8 +269,7 @@ static bool a5xx_is_sptp_idle(struct adreno_device *adreno_dev) struct kgsl_device *device = KGSL_DEVICE(adreno_dev); /* If feature is not supported or enabled, no worry */ - if (!ADRENO_FEATURE(adreno_dev, ADRENO_SPTP_PC) || - !test_bit(ADRENO_SPTP_PC_CTRL, &adreno_dev->pwrctrl_flag)) + if (!adreno_dev->sptp_pc_enabled) return true; kgsl_regread(device, A5XX_GPMU_SP_PWR_CLK_STATUS, ®); if (reg & BIT(20)) @@ -404,8 +411,7 @@ static void a5xx_regulator_disable(struct adreno_device *adreno_dev) return; /* If feature is not supported or not enabled */ - if (!ADRENO_FEATURE(adreno_dev, ADRENO_SPTP_PC) || - !test_bit(ADRENO_SPTP_PC_CTRL, &adreno_dev->pwrctrl_flag)) { + if (!adreno_dev->sptp_pc_enabled) { /* Set the default register values; set SW_COLLAPSE to 1 */ kgsl_regwrite(device, A5XX_GPMU_SP_POWER_CNTL, 0x778001); /* @@ -456,8 +462,7 @@ static void a5xx_enable_pc(struct adreno_device *adreno_dev) { struct kgsl_device *device = KGSL_DEVICE(adreno_dev); - if (!ADRENO_FEATURE(adreno_dev, ADRENO_SPTP_PC) || - !test_bit(ADRENO_SPTP_PC_CTRL, &adreno_dev->pwrctrl_flag)) + if (!adreno_dev->sptp_pc_enabled) return; kgsl_regwrite(device, A5XX_GPMU_PWR_COL_INTER_FRAME_CTRL, 0x0000007F); @@ -701,7 +706,7 @@ void a5xx_hwcg_set(struct adreno_device *adreno_dev, bool on) const struct adreno_a5xx_core *a5xx_core = to_a5xx_core(adreno_dev); int i; - if (!test_bit(ADRENO_HWCG_CTRL, &adreno_dev->pwrctrl_flag)) + if (!adreno_dev->hwcg_enabled) return; for (i = 0; i < a5xx_core->hwcg_count; i++) @@ -934,8 +939,7 @@ static void a530_lm_init(struct adreno_device *adreno_dev) struct kgsl_device *device = KGSL_DEVICE(adreno_dev); const struct adreno_a5xx_core *a5xx_core = to_a5xx_core(adreno_dev); - if (!ADRENO_FEATURE(adreno_dev, ADRENO_LM) || - !test_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag)) + if (!adreno_dev->lm_enabled) return; /* If something was wrong with the sequence file, return */ @@ -985,8 +989,7 @@ static void a530_lm_enable(struct adreno_device *adreno_dev) { struct kgsl_device *device = KGSL_DEVICE(adreno_dev); - if (!ADRENO_FEATURE(adreno_dev, ADRENO_LM) || - !test_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag)) + if (!adreno_dev->lm_enabled) return; /* If no sequence properly initialized, return */ @@ -1015,10 +1018,10 @@ static void a540_lm_init(struct adreno_device *adreno_dev) << AGC_GPU_VERSION_SHIFT); unsigned int r; - if (!test_bit(ADRENO_THROTTLING_CTRL, &adreno_dev->pwrctrl_flag)) + if (!adreno_dev->throttling_enabled) agc_lm_config |= AGC_THROTTLE_DISABLE; - if (lm_on(adreno_dev)) { + if (adreno_dev->lm_enabled) { agc_lm_config |= AGC_LM_CONFIG_ENABLE_GPMU_ADAPTIVE | AGC_LM_CONFIG_ISENSE_ENABLE; @@ -1096,20 +1099,11 @@ static void a5xx_pwrlevel_change_settings(struct adreno_device *adreno_dev, unsigned int prelevel, unsigned int postlevel, bool post) { - int on = 0; - - /* On pre A540 HW only call through if LMx is supported and enabled */ - if (ADRENO_FEATURE(adreno_dev, ADRENO_LM) && - test_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag)) - on = ADRENO_LM; - - /* On 540+ HW call through unconditionally as long as GPMU is enabled */ - if (ADRENO_FEATURE(adreno_dev, ADRENO_GPMU)) { - if (adreno_is_a540(adreno_dev)) - on = ADRENO_GPMU; - } - - if (!on) + /* + * On pre A540 HW only call through if LMx is supported and enabled, and + * always call through for a540 + */ + if (!adreno_is_a540(adreno_dev) && !adreno_dev->lm_enabled) return; if (!post) { @@ -1158,13 +1152,7 @@ static int64_t a5xx_read_throttling_counters(struct adreno_device *adreno_dev) uint32_t th[ADRENO_GPMU_THROTTLE_COUNTERS]; struct adreno_busy_data *busy = &adreno_dev->busy_data; - if (!adreno_is_a540(adreno_dev)) - return 0; - - if (!ADRENO_FEATURE(adreno_dev, ADRENO_GPMU)) - return 0; - - if (!test_bit(ADRENO_THROTTLING_CTRL, &adreno_dev->pwrctrl_flag)) + if (!adreno_dev->throttling_enabled) return 0; for (i = 0; i < ADRENO_GPMU_THROTTLE_COUNTERS; i++) { @@ -2378,10 +2366,6 @@ static unsigned int a5xx_register_offsets[ADRENO_REG_REGISTER_MAX] = { ADRENO_REG_DEFINE(ADRENO_REG_RBBM_INT_0_STATUS, A5XX_RBBM_INT_0_STATUS), ADRENO_REG_DEFINE(ADRENO_REG_RBBM_CLOCK_CTL, A5XX_RBBM_CLOCK_CNTL), ADRENO_REG_DEFINE(ADRENO_REG_RBBM_SW_RESET_CMD, A5XX_RBBM_SW_RESET_CMD), - ADRENO_REG_DEFINE(ADRENO_REG_RBBM_BLOCK_SW_RESET_CMD, - A5XX_RBBM_BLOCK_SW_RESET_CMD), - ADRENO_REG_DEFINE(ADRENO_REG_RBBM_BLOCK_SW_RESET_CMD2, - A5XX_RBBM_BLOCK_SW_RESET_CMD2), ADRENO_REG_DEFINE(ADRENO_REG_UCHE_INVALIDATE0, A5XX_UCHE_INVALIDATE0), ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_RBBM_0_LO, A5XX_RBBM_PERFCTR_RBBM_0_LO), @@ -2756,6 +2740,26 @@ static irqreturn_t a5xx_irq_handler(struct adreno_device *adreno_dev) return ret; } +static bool a5xx_hw_isidle(struct adreno_device *adreno_dev) +{ + struct kgsl_device *device = KGSL_DEVICE(adreno_dev); + u32 status; + + /* + * Due to CRC idle throttling the GPU idle hysteresis on a540 can take + * up to 5uS to expire + */ + if (adreno_is_a540(adreno_dev)) + udelay(5); + + kgsl_regread(device, A5XX_RBBM_STATUS, &status); + + if (status & 0xfffffffe) + return false; + + return adreno_irq_pending(adreno_dev) ? false : true; +} + #ifdef CONFIG_QCOM_KGSL_CORESIGHT static struct adreno_coresight_register a5xx_coresight_registers[] = { { A5XX_RBBM_CFG_DBGBUS_SEL_A }, @@ -2982,4 +2986,5 @@ struct adreno_gpudev adreno_a5xx_gpudev = { .preemption_schedule = a5xx_preemption_schedule, .clk_set_options = a5xx_clk_set_options, .read_alwayson = a5xx_read_alwayson, + .hw_isidle = a5xx_hw_isidle, }; diff --git a/drivers/gpu/msm/adreno_a5xx.h b/drivers/gpu/msm/adreno_a5xx.h index 41060a2bd166..90baffa9fc52 100644 --- a/drivers/gpu/msm/adreno_a5xx.h +++ b/drivers/gpu/msm/adreno_a5xx.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2015-2017,2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2017,2019-2020 The Linux Foundation. All rights reserved. */ #ifndef _ADRENO_A5XX_H_ @@ -205,12 +205,6 @@ void a5xx_hwcg_set(struct adreno_device *adreno_dev, bool on); #define LM_DEFAULT_LIMIT 6000 #define A530_DEFAULT_LEAKAGE 0x004E001A -static inline bool lm_on(struct adreno_device *adreno_dev) -{ - return ADRENO_FEATURE(adreno_dev, ADRENO_LM) && - test_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag); -} - /** * to_a5xx_core - return the a5xx specific GPU core struct * @adreno_dev: An Adreno GPU device handle diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c index 55545558b6c0..73f95b44b036 100644 --- a/drivers/gpu/msm/adreno_a6xx.c +++ b/drivers/gpu/msm/adreno_a6xx.c @@ -238,7 +238,7 @@ static void a6xx_hwcg_set(struct adreno_device *adreno_dev, bool on) unsigned int value; int i; - if (!test_bit(ADRENO_HWCG_CTRL, &adreno_dev->pwrctrl_flag)) + if (!adreno_dev->hwcg_enabled) on = false; if (gmu_core_isenabled(device)) { @@ -405,10 +405,6 @@ static void a6xx_start(struct adreno_device *adreno_dev) adreno_dev->irq_mask = A6XX_INT_MASK; - /* runtime adjust callbacks based on feature sets */ - if (!gmu_core_isenabled(device)) - /* Legacy idle management if gmu is disabled */ - ADRENO_GPU_DEVICE(adreno_dev)->hw_isidle = NULL; /* enable hardware clockgating */ a6xx_hwcg_set(adreno_dev, true); @@ -986,17 +982,24 @@ static void a6xx_gpu_keepalive(struct adreno_device *adreno_dev, ADRENO_REG_GMU_PWR_COL_KEEPALIVE, state); } -/* Bitmask for GPU idle status check */ -#define GPUBUSYIGNAHB BIT(23) static bool a6xx_hw_isidle(struct adreno_device *adreno_dev) { + struct kgsl_device *device = KGSL_DEVICE(adreno_dev); unsigned int reg; - gmu_core_regread(KGSL_DEVICE(adreno_dev), - A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS, ®); - if (reg & GPUBUSYIGNAHB) - return false; - return true; + /* Non GMU devices monitor the RBBM status */ + if (!gmu_core_isenabled(device)) { + kgsl_regread(device, A6XX_RBBM_STATUS, ®); + if (reg & 0xfffffffe) + return false; + + return adreno_irq_pending(adreno_dev) ? false : true; + } + + gmu_core_regread(device, A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS, ®); + + /* Bit 23 is GPUBUSYIGNAHB */ + return (reg & BIT(23)) ? false : true; } /* @@ -1011,30 +1014,6 @@ static int a6xx_microcode_read(struct adreno_device *adreno_dev) return adreno_get_firmware(adreno_dev, a6xx_core->sqefw_name, sqe_fw); } -static int a6xx_soft_reset(struct adreno_device *adreno_dev) -{ - struct kgsl_device *device = KGSL_DEVICE(adreno_dev); - unsigned int reg; - - if (gmu_core_isenabled(device)) - return 0; - - adreno_writereg(adreno_dev, ADRENO_REG_RBBM_SW_RESET_CMD, 1); - /* - * Do a dummy read to get a brief read cycle delay for the - * reset to take effect - */ - adreno_readreg(adreno_dev, ADRENO_REG_RBBM_SW_RESET_CMD, ®); - adreno_writereg(adreno_dev, ADRENO_REG_RBBM_SW_RESET_CMD, 0); - - /* Clear GBIF client halt and CX arbiter halt */ - adreno_deassert_gbif_halt(adreno_dev); - - a6xx_sptprac_enable(adreno_dev); - - return 0; -} - static int64_t a6xx_read_throttling_counters(struct adreno_device *adreno_dev) { struct kgsl_device *device = KGSL_DEVICE(adreno_dev); @@ -1042,8 +1021,7 @@ static int64_t a6xx_read_throttling_counters(struct adreno_device *adreno_dev) u32 a, b, c; struct adreno_busy_data *busy = &adreno_dev->busy_data; - if (!ADRENO_FEATURE(adreno_dev, ADRENO_LM) || - !test_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag)) + if (!adreno_dev->lm_enabled) return 0; /* The counters are selected in a6xx_gmu_enable_lm() */ @@ -1098,12 +1076,14 @@ static int a6xx_reset(struct kgsl_device *device, int fault) struct adreno_device *adreno_dev = ADRENO_DEVICE(device); int ret; - /* Use the regular reset sequence for No GMU */ - if (!gmu_core_isenabled(device)) - return adreno_reset(device, fault); - - /* Transition from ACTIVE to RESET state */ - kgsl_pwrctrl_change_state(device, KGSL_STATE_RESET); + /* + * GMU devices transition to KGSL_STATE_RESET, non GMU devices go + * directly to KGSL_STATE_INIT + */ + if (gmu_core_isenabled(device)) + kgsl_pwrctrl_change_state(device, KGSL_STATE_RESET); + else + kgsl_pwrctrl_change_state(device, KGSL_STATE_INIT); /* since device is officially off now clear start bit */ clear_bit(ADRENO_DEVICE_STARTED, &adreno_dev->priv); @@ -2300,6 +2280,8 @@ static void a6xx_platform_setup(struct adreno_device *adreno_dev) { struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); + adreno_dev->hwcg_enabled = true; + adreno_dev->preempt.preempt_level = 1; adreno_dev->preempt.skipsaverestore = true; adreno_dev->preempt.usesgmem = true; @@ -2407,11 +2389,6 @@ static unsigned int a6xx_register_offsets[ADRENO_REG_REGISTER_MAX] = { ADRENO_REG_DEFINE(ADRENO_REG_RBBM_INT_0_MASK, A6XX_RBBM_INT_0_MASK), ADRENO_REG_DEFINE(ADRENO_REG_RBBM_INT_0_STATUS, A6XX_RBBM_INT_0_STATUS), ADRENO_REG_DEFINE(ADRENO_REG_RBBM_CLOCK_CTL, A6XX_RBBM_CLOCK_CNTL), - ADRENO_REG_DEFINE(ADRENO_REG_RBBM_SW_RESET_CMD, A6XX_RBBM_SW_RESET_CMD), - ADRENO_REG_DEFINE(ADRENO_REG_RBBM_BLOCK_SW_RESET_CMD, - A6XX_RBBM_BLOCK_SW_RESET_CMD), - ADRENO_REG_DEFINE(ADRENO_REG_RBBM_BLOCK_SW_RESET_CMD2, - A6XX_RBBM_BLOCK_SW_RESET_CMD2), ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_LOAD_VALUE_LO, A6XX_RBBM_PERFCTR_LOAD_VALUE_LO), ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_LOAD_VALUE_HI, @@ -2612,10 +2589,9 @@ struct adreno_gpudev adreno_a6xx_gpudev = { .read_throttling_counters = a6xx_read_throttling_counters, .microcode_read = a6xx_microcode_read, .gpu_keepalive = a6xx_gpu_keepalive, - .hw_isidle = a6xx_hw_isidle, /* Replaced by NULL if GMU is disabled */ + .hw_isidle = a6xx_hw_isidle, .iommu_fault_block = a6xx_iommu_fault_block, .reset = a6xx_reset, - .soft_reset = a6xx_soft_reset, .preemption_pre_ibsubmit = a6xx_preemption_pre_ibsubmit, .preemption_post_ibsubmit = a6xx_preemption_post_ibsubmit, .preemption_init = a6xx_preemption_init, diff --git a/drivers/gpu/msm/adreno_a6xx_gmu.c b/drivers/gpu/msm/adreno_a6xx_gmu.c index 5dae8152f4c3..8d2d4e703339 100644 --- a/drivers/gpu/msm/adreno_a6xx_gmu.c +++ b/drivers/gpu/msm/adreno_a6xx_gmu.c @@ -487,8 +487,7 @@ static int a6xx_rpmh_power_off_gpu(struct kgsl_device *device) gmu_core_regwrite(device, A6XX_GMU_RSCC_CONTROL_REQ, 0); - if (ADRENO_FEATURE(adreno_dev, ADRENO_LM) && - test_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag)) + if (adreno_dev->lm_enabled) gmu_core_regwrite(device, A6XX_GMU_AO_SPARE_CNTL, 0); set_bit(GMU_RSCC_SLEEP_SEQ_DONE, &device->gmu_core.flags); @@ -1409,8 +1408,7 @@ static void a6xx_gmu_enable_lm(struct kgsl_device *device) memset(adreno_dev->busy_data.throttle_cycles, 0, sizeof(adreno_dev->busy_data.throttle_cycles)); - if (!ADRENO_FEATURE(adreno_dev, ADRENO_LM) || - !test_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag)) + if (!adreno_dev->lm_enabled) return; /* diff --git a/drivers/gpu/msm/adreno_debugfs.c b/drivers/gpu/msm/adreno_debugfs.c index 03a59ce24408..2d2a6473089d 100644 --- a/drivers/gpu/msm/adreno_debugfs.c +++ b/drivers/gpu/msm/adreno_debugfs.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2002,2008-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2002,2008-2020, The Linux Foundation. All rights reserved. */ #include @@ -59,7 +59,7 @@ static int _lm_limit_set(void *data, u64 val) adreno_dev->lm_limit = val; - if (test_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag)) { + if (adreno_dev->lm_enabled) { mutex_lock(&device->mutex); kgsl_pwrctrl_change_state(device, KGSL_STATE_SUSPEND); kgsl_pwrctrl_change_state(device, KGSL_STATE_SLUMBER); diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c index a8f3e0592cf1..cf5176404627 100644 --- a/drivers/gpu/msm/adreno_dispatch.c +++ b/drivers/gpu/msm/adreno_dispatch.c @@ -175,8 +175,8 @@ static void fault_detect_read(struct adreno_device *adreno_dev) */ static inline bool _isidle(struct adreno_device *adreno_dev) { - const struct adreno_gpu_core *gpucore = adreno_dev->gpucore; unsigned int reg_rbbm_status; + u32 mask; if (!kgsl_state_is_awake(KGSL_DEVICE(adreno_dev))) goto ret; @@ -187,7 +187,12 @@ static inline bool _isidle(struct adreno_device *adreno_dev) /* only check rbbm status to determine if GPU is idle */ adreno_readreg(adreno_dev, ADRENO_REG_RBBM_STATUS, ®_rbbm_status); - if (reg_rbbm_status & gpucore->busy_mask) + if (adreno_is_a3xx(adreno_dev)) + mask = 0x7ffffffe; + else + mask = 0xfffffffe; + + if (reg_rbbm_status & mask) return false; ret: @@ -2197,10 +2202,7 @@ static int dispatcher_do_fault(struct adreno_device *adreno_dev) kgsl_process_event_group(device, &hung_rb->events); } - if (gpudev->reset) - ret = gpudev->reset(device, fault); - else - ret = adreno_reset(device, fault); + ret = adreno_reset(device, fault); mutex_unlock(&device->mutex); /* if any other fault got in until reset then ignore */ diff --git a/drivers/gpu/msm/adreno_sysfs.c b/drivers/gpu/msm/adreno_sysfs.c index 5256c25be624..f5fb8641fd5c 100644 --- a/drivers/gpu/msm/adreno_sysfs.c +++ b/drivers/gpu/msm/adreno_sysfs.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2020, The Linux Foundation. All rights reserved. */ #include @@ -139,19 +139,19 @@ static bool _ft_hang_intr_status_show(struct adreno_device *adreno_dev) return true; } -static int _pwrctrl_store(struct adreno_device *adreno_dev, - unsigned int val, unsigned int flag) +static int pwrflag_store(struct adreno_device *adreno_dev, + unsigned int val, bool *flag) { struct kgsl_device *device = KGSL_DEVICE(adreno_dev); - if (val == test_bit(flag, &adreno_dev->pwrctrl_flag)) + if (*flag == val) return 0; mutex_lock(&device->mutex); /* Power down the GPU before changing the state */ kgsl_pwrctrl_change_state(device, KGSL_STATE_SUSPEND); - change_bit(flag, &adreno_dev->pwrctrl_flag); + *flag = val; kgsl_pwrctrl_change_state(device, KGSL_STATE_SLUMBER); mutex_unlock(&device->mutex); @@ -201,42 +201,51 @@ static bool _preemption_show(struct adreno_device *adreno_dev) static int _hwcg_store(struct adreno_device *adreno_dev, bool val) { - return _pwrctrl_store(adreno_dev, val, ADRENO_HWCG_CTRL); + return pwrflag_store(adreno_dev, val, &adreno_dev->hwcg_enabled); } static bool _hwcg_show(struct adreno_device *adreno_dev) { - return test_bit(ADRENO_HWCG_CTRL, &adreno_dev->pwrctrl_flag); + return adreno_dev->hwcg_enabled; } static int _throttling_store(struct adreno_device *adreno_dev, bool val) { - return _pwrctrl_store(adreno_dev, val, ADRENO_THROTTLING_CTRL); + if (!adreno_is_a540(adreno_dev)) + return 0; + + return pwrflag_store(adreno_dev, val, &adreno_dev->throttling_enabled); } static bool _throttling_show(struct adreno_device *adreno_dev) { - return test_bit(ADRENO_THROTTLING_CTRL, &adreno_dev->pwrctrl_flag); + return adreno_dev->throttling_enabled; } static int _sptp_pc_store(struct adreno_device *adreno_dev, bool val) { - return _pwrctrl_store(adreno_dev, val, ADRENO_SPTP_PC_CTRL); + if (!ADRENO_FEATURE(adreno_dev, ADRENO_SPTP_PC)) + return 0; + + return pwrflag_store(adreno_dev, val, &adreno_dev->sptp_pc_enabled); } static bool _sptp_pc_show(struct adreno_device *adreno_dev) { - return test_bit(ADRENO_SPTP_PC_CTRL, &adreno_dev->pwrctrl_flag); + return adreno_dev->sptp_pc_enabled; } static int _lm_store(struct adreno_device *adreno_dev, bool val) { - return _pwrctrl_store(adreno_dev, val, ADRENO_LM_CTRL); + if (!ADRENO_FEATURE(adreno_dev, ADRENO_LM)) + return 0; + + return pwrflag_store(adreno_dev, val, &adreno_dev->lm_enabled); } static bool _lm_show(struct adreno_device *adreno_dev) { - return test_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag); + return adreno_dev->lm_enabled; } static int _ifpc_store(struct adreno_device *adreno_dev, bool val) @@ -263,17 +272,12 @@ static unsigned int _preempt_count_show(struct adreno_device *adreno_dev) static bool _acd_show(struct adreno_device *adreno_dev) { - return test_bit(ADRENO_ACD_CTRL, &adreno_dev->pwrctrl_flag); + return adreno_dev->acd_enabled; } static int _acd_store(struct adreno_device *adreno_dev, bool val) { - struct kgsl_device *device = KGSL_DEVICE(adreno_dev); - - if (test_bit(ADRENO_ACD_CTRL, &adreno_dev->pwrctrl_flag) == val) - return 0; - - return gmu_core_acd_set(device, val); + return gmu_core_acd_set(KGSL_DEVICE(adreno_dev), val); } static ssize_t _sysfs_store_u32(struct device *dev, diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h index 5d6c25383fb1..9e45d8455f58 100644 --- a/drivers/gpu/msm/kgsl_device.h +++ b/drivers/gpu/msm/kgsl_device.h @@ -97,7 +97,6 @@ struct kgsl_functable { void (*regwrite)(struct kgsl_device *device, unsigned int offsetwords, unsigned int value); int (*idle)(struct kgsl_device *device); - bool (*isidle)(struct kgsl_device *device); int (*suspend_context)(struct kgsl_device *device); int (*first_open)(struct kgsl_device *device); int (*last_close)(struct kgsl_device *device); diff --git a/drivers/gpu/msm/kgsl_gmu.c b/drivers/gpu/msm/kgsl_gmu.c index f7b28d9a70a3..d39f2c0fa8ab 100644 --- a/drivers/gpu/msm/kgsl_gmu.c +++ b/drivers/gpu/msm/kgsl_gmu.c @@ -25,7 +25,7 @@ struct gmu_iommu_context { const char *name; - struct device *dev; + struct platform_device *pdev; struct iommu_domain *domain; }; @@ -277,48 +277,57 @@ static struct gmu_memdesc *allocate_gmu_kmem(struct gmu_device *gmu, } static int gmu_iommu_cb_probe(struct gmu_device *gmu, - struct gmu_iommu_context *ctx, - struct device_node *node) + const char *name, struct gmu_iommu_context *ctx, + struct device_node *parent, iommu_fault_handler_t handler) { - struct platform_device *pdev = of_find_device_by_node(node); - struct device *dev; + struct device_node *node = of_get_child_by_name(parent, name); + struct platform_device *pdev; int ret; - dev = &pdev->dev; - of_dma_configure(dev, node, true); + if (!node) + return -ENODEV; - ctx->dev = dev; + pdev = of_find_device_by_node(node); + of_dma_configure(&pdev->dev, node, true); + + of_node_put(node); + + ctx->pdev = pdev; ctx->domain = iommu_domain_alloc(&platform_bus_type); if (ctx->domain == NULL) { dev_err(&gmu->pdev->dev, "gmu iommu fail to alloc %s domain\n", ctx->name); + platform_device_put(pdev); return -ENODEV; } - ret = iommu_attach_device(ctx->domain, dev); - if (ret) { - dev_err(&gmu->pdev->dev, "gmu iommu fail to attach %s device\n", - ctx->name); - iommu_domain_free(ctx->domain); + ret = iommu_attach_device(ctx->domain, &pdev->dev); + if (!ret) { + iommu_set_fault_handler(ctx->domain, handler, ctx); + return 0; } + dev_err(&gmu->pdev->dev, + "gmu iommu fail to attach %s device\n", ctx->name); + iommu_domain_free(ctx->domain); + ctx->domain = NULL; + platform_device_put(pdev); + return ret; } -static struct { - const char *compatible; - int index; - iommu_fault_handler_t hdlr; -} cbs[] = { - { "qcom,smmu-gmu-user-cb", - GMU_CONTEXT_USER, - gmu_user_fault_handler, - }, - { "qcom,smmu-gmu-kernel-cb", - GMU_CONTEXT_KERNEL, - gmu_kernel_fault_handler, - }, -}; + +static void gmu_iommu_cb_close(struct gmu_iommu_context *ctx) +{ + if (!ctx->domain) + return; + + iommu_detach_device(ctx->domain, &ctx->pdev->dev); + iommu_domain_free(ctx->domain); + + platform_device_put(ctx->pdev); + memset(ctx, 0, sizeof(*ctx)); +} /* * gmu_iommu_init() - probe IOMMU context banks used by GMU @@ -328,34 +337,17 @@ static struct { */ static int gmu_iommu_init(struct gmu_device *gmu, struct device_node *node) { - struct device_node *child; - struct gmu_iommu_context *ctx = NULL; - int ret, i; + int ret; - of_platform_populate(node, NULL, NULL, &gmu->pdev->dev); + devm_of_platform_populate(&gmu->pdev->dev); - for (i = 0; i < ARRAY_SIZE(cbs); i++) { - child = of_find_compatible_node(node, NULL, cbs[i].compatible); - if (child) { - ctx = &gmu_ctx[cbs[i].index]; - ret = gmu_iommu_cb_probe(gmu, ctx, child); - if (ret) - return ret; - iommu_set_fault_handler(ctx->domain, - cbs[i].hdlr, ctx); - } - } + ret = gmu_iommu_cb_probe(gmu, "gmu_user", + &gmu_ctx[GMU_CONTEXT_USER], node, gmu_user_fault_handler); + if (ret) + return ret; - for (i = 0; i < ARRAY_SIZE(gmu_ctx); i++) { - if (gmu_ctx[i].domain == NULL) { - dev_err(&gmu->pdev->dev, - "Missing GMU %s context bank node\n", - gmu_ctx[i].name); - return -EINVAL; - } - } - - return 0; + return gmu_iommu_cb_probe(gmu, "gmu_kernel", + &gmu_ctx[GMU_CONTEXT_KERNEL], node, gmu_kernel_fault_handler); } /* @@ -394,14 +386,8 @@ static void gmu_memory_close(struct gmu_device *gmu) clear_bit(i, &gmu->kmem_bitmap); } - for (i = 0; i < ARRAY_SIZE(gmu_ctx); i++) { - ctx = &gmu_ctx[i]; - - if (ctx->domain) { - iommu_detach_device(ctx->domain, ctx->dev); - iommu_domain_free(ctx->domain); - } - } + gmu_iommu_cb_close(&gmu_ctx[GMU_CONTEXT_USER]); + gmu_iommu_cb_close(&gmu_ctx[GMU_CONTEXT_KERNEL]); } static enum gmu_mem_type gmu_get_blk_memtype(struct gmu_device *gmu, @@ -1061,60 +1047,44 @@ static int gmu_reg_probe(struct kgsl_device *device) res = platform_get_resource_byname(gmu->pdev, IORESOURCE_MEM, "kgsl_gmu_reg"); - if (res == NULL) { - dev_err(&gmu->pdev->dev, - "platform_get_resource kgsl_gmu_reg failed\n"); - return -EINVAL; - } - - if (res->start == 0 || resource_size(res) == 0) { - dev_err(&gmu->pdev->dev, - "dev %d kgsl_gmu_reg invalid register region\n", - gmu->pdev->dev.id); - return -EINVAL; - } - - gmu->reg_phys = res->start; - gmu->reg_len = resource_size(res); - 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"); + if (!res) { + dev_err(&gmu->pdev->dev, "The GMU register region isn't defined\n"); return -ENODEV; } + device->gmu_core.gmu2gpu_offset = (res->start - device->reg_phys) >> 2; + device->gmu_core.reg_len = resource_size(res); + + /* + * We can't use devm_ioremap_resource here because we purposely double + * map the gpu_cc registers for debugging purposes + */ + device->gmu_core.reg_virt = devm_ioremap(&gmu->pdev->dev, res->start, + resource_size(res)); + + if (!device->gmu_core.reg_virt) { + dev_err(&gmu->pdev->dev, "Unable to map the GMU registers\n"); + return -ENOMEM; + } + return 0; } static int gmu_regulators_probe(struct gmu_device *gmu, - struct device_node *node) + struct platform_device *pdev) { - const char *name; - struct property *prop; - struct device *dev = &gmu->pdev->dev; - int ret = 0; + gmu->cx_gdsc = devm_regulator_get(&pdev->dev, "vddcx"); + if (IS_ERR(gmu->cx_gdsc)) { + if (PTR_ERR(gmu->cx_gdsc) != -EPROBE_DEFER) + dev_err(&pdev->dev, "Couldn't get the vddcx gdsc\n"); + return PTR_ERR(gmu->cx_gdsc); + } - of_property_for_each_string(node, "regulator-names", prop, name) { - if (!strcmp(name, "vddcx")) { - gmu->cx_gdsc = devm_regulator_get(dev, name); - if (IS_ERR(gmu->cx_gdsc)) { - ret = PTR_ERR(gmu->cx_gdsc); - dev_err(dev, "dt: GMU couldn't get CX gdsc\n"); - gmu->cx_gdsc = NULL; - return ret; - } - } else if (!strcmp(name, "vdd")) { - gmu->gx_gdsc = devm_regulator_get(dev, name); - if (IS_ERR(gmu->gx_gdsc)) { - ret = PTR_ERR(gmu->gx_gdsc); - dev_err(dev, "dt: GMU couldn't get GX gdsc\n"); - gmu->gx_gdsc = NULL; - return ret; - } - } else { - dev_err(dev, "dt: Unknown GMU regulator: %s\n", name); - return -ENODEV; - } + gmu->gx_gdsc = devm_regulator_get(&pdev->dev, "vdd"); + if (IS_ERR(gmu->gx_gdsc)) { + if (PTR_ERR(gmu->gx_gdsc) != -EPROBE_DEFER) + dev_err(&pdev->dev, "Couldn't get the vdd gdsc\n"); + return PTR_ERR(gmu->gx_gdsc); } return 0; @@ -1160,11 +1130,11 @@ static int gmu_aop_mailbox_init(struct kgsl_device *device, if (IS_ERR(mailbox->channel)) return PTR_ERR(mailbox->channel); - set_bit(ADRENO_ACD_CTRL, &adreno_dev->pwrctrl_flag); + adreno_dev->acd_enabled = true; return 0; } -static int gmu_acd_set(struct kgsl_device *device, unsigned int val) +static int gmu_acd_set(struct kgsl_device *device, bool val) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct gmu_device *gmu = KGSL_GMU_DEVICE(device); @@ -1173,7 +1143,7 @@ static int gmu_acd_set(struct kgsl_device *device, unsigned int val) return -EINVAL; /* Don't do any unneeded work if ACD is already in the correct state */ - if (val == test_bit(ADRENO_ACD_CTRL, &adreno_dev->pwrctrl_flag)) + if (adreno_dev->acd_enabled == val) return 0; mutex_lock(&device->mutex); @@ -1181,13 +1151,8 @@ static int gmu_acd_set(struct kgsl_device *device, unsigned int val) /* Power down the GPU before enabling or disabling ACD */ kgsl_pwrctrl_change_state(device, KGSL_STATE_SUSPEND); - if (val) { - set_bit(ADRENO_ACD_CTRL, &adreno_dev->pwrctrl_flag); - gmu_aop_send_acd_state(device, true); - } else { - clear_bit(ADRENO_ACD_CTRL, &adreno_dev->pwrctrl_flag); - gmu_aop_send_acd_state(device, false); - } + adreno_dev->acd_enabled = val; + gmu_aop_send_acd_state(device, val); kgsl_pwrctrl_change_state(device, KGSL_STATE_SLUMBER); @@ -1321,7 +1286,7 @@ static int gmu_probe(struct kgsl_device *device, struct platform_device *pdev) gmu->pdev = pdev; - device->gmu_core.ptr = (void *)gmu; + device->gmu_core.ptr = gmu; hfi = &gmu->hfi; gmu->load_mode = TCM_BOOT; @@ -1330,11 +1295,11 @@ static int gmu_probe(struct kgsl_device *device, struct platform_device *pdev) set_dma_ops(&gmu->pdev->dev, NULL); /* Set up GMU regulators */ - ret = gmu_regulators_probe(gmu, pdev->dev.of_node); + ret = gmu_regulators_probe(gmu, pdev); if (ret) return ret; - ret = devm_clk_bulk_get_all(&gmu->pdev->dev, &gmu->clks); + ret = devm_clk_bulk_get_all(&pdev->dev, &gmu->clks); if (ret < 0) return ret; @@ -1343,8 +1308,9 @@ static int gmu_probe(struct kgsl_device *device, struct platform_device *pdev) /* Get a pointer to the GMU clock */ gmu->gmu_clk = kgsl_of_clk_by_name(gmu->clks, gmu->num_clks, "gmu_clk"); if (!gmu->gmu_clk) { - dev_err(&gmu->pdev->dev, "Couldn't get gmu_clk\n"); - return -ENODEV; + dev_err(&pdev->dev, "Couldn't get gmu_clk\n"); + ret = -ENODEV; + goto error; } /* Set up GMU IOMMU and shared memory with GMU */ @@ -1366,10 +1332,6 @@ static int gmu_probe(struct kgsl_device *device, struct platform_device *pdev) if (ret) goto error; - device->gmu_core.gmu2gpu_offset = - (gmu->reg_phys - device->reg_phys) >> 2; - device->gmu_core.reg_len = gmu->reg_len; - /* Initialize HFI and GMU interrupts */ hfi->hfi_interrupt_num = kgsl_request_irq(gmu->pdev, "kgsl_hfi_irq", hfi_irq_handler, device); @@ -1474,9 +1436,6 @@ static int gmu_enable_gdsc(struct gmu_device *gmu) { int ret; - if (IS_ERR_OR_NULL(gmu->cx_gdsc)) - return 0; - ret = regulator_enable(gmu->cx_gdsc); if (ret) dev_err(&gmu->pdev->dev, @@ -1598,8 +1557,7 @@ static int gmu_start(struct kgsl_device *device) switch (device->state) { case KGSL_STATE_INIT: - gmu_aop_send_acd_state(device, test_bit(ADRENO_ACD_CTRL, - &adreno_dev->pwrctrl_flag)); + gmu_aop_send_acd_state(device, adreno_dev->acd_enabled); /* Fall-thru */ case KGSL_STATE_SUSPEND: WARN_ON(test_bit(GMU_CLK_ON, &device->gmu_core.flags)); @@ -1738,21 +1696,15 @@ static void gmu_remove(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct gmu_device *gmu = KGSL_GMU_DEVICE(device); - struct kgsl_hfi *hfi; - if (gmu == NULL || gmu->pdev == NULL) - return; - - hfi = &gmu->hfi; - - tasklet_kill(&hfi->tasklet); + tasklet_kill(&gmu->hfi.tasklet); gmu_stop(device); if (!IS_ERR_OR_NULL(gmu->mailbox.channel)) mbox_free_channel(gmu->mailbox.channel); - clear_bit(ADRENO_ACD_CTRL, &adreno_dev->pwrctrl_flag); + adreno_dev->acd_enabled = false; if (gmu->fw_image) release_firmware(gmu->fw_image); diff --git a/drivers/gpu/msm/kgsl_gmu.h b/drivers/gpu/msm/kgsl_gmu.h index 7c6ca7e03b5c..b6a815d90965 100644 --- a/drivers/gpu/msm/kgsl_gmu.h +++ b/drivers/gpu/msm/kgsl_gmu.h @@ -141,8 +141,6 @@ struct icc_path; /** * struct gmu_device - GMU device structure * @ver: GMU Version information - * @reg_phys: GMU CSR physical address - * @reg_len: GMU CSR range * @gmu_interrupt_num: GMU interrupt number * @fw_image: GMU FW image * @hfi_mem: pointer to HFI shared memory @@ -174,8 +172,6 @@ struct gmu_device { u32 hfi; } ver; struct platform_device *pdev; - unsigned long reg_phys; - unsigned int reg_len; int gmu_interrupt_num; const struct firmware *fw_image; struct gmu_memdesc *hfi_mem; diff --git a/drivers/gpu/msm/kgsl_gmu_core.c b/drivers/gpu/msm/kgsl_gmu_core.c index 81414d8ae594..6072e9c8b7d5 100644 --- a/drivers/gpu/msm/kgsl_gmu_core.c +++ b/drivers/gpu/msm/kgsl_gmu_core.c @@ -142,7 +142,7 @@ int gmu_core_dcvs_set(struct kgsl_device *device, int gpu_pwrlevel, return -EINVAL; } -int gmu_core_acd_set(struct kgsl_device *device, unsigned int val) +int gmu_core_acd_set(struct kgsl_device *device, bool val) { struct gmu_core_ops *gmu_core_ops = GMU_CORE_OPS(device); diff --git a/drivers/gpu/msm/kgsl_gmu_core.h b/drivers/gpu/msm/kgsl_gmu_core.h index 45280614dc9f..655693a68205 100644 --- a/drivers/gpu/msm/kgsl_gmu_core.h +++ b/drivers/gpu/msm/kgsl_gmu_core.h @@ -109,7 +109,7 @@ struct gmu_core_ops { void (*snapshot)(struct kgsl_device *device); bool (*regulator_isenabled)(struct kgsl_device *device); int (*suspend)(struct kgsl_device *device); - int (*acd_set)(struct kgsl_device *device, unsigned int val); + int (*acd_set)(struct kgsl_device *device, bool val); }; struct gmu_dev_ops { @@ -179,7 +179,7 @@ bool gmu_core_scales_bandwidth(struct kgsl_device *device); bool gmu_core_isenabled(struct kgsl_device *device); int gmu_core_dcvs_set(struct kgsl_device *device, int gpu_pwrlevel, int bus_level); -int gmu_core_acd_set(struct kgsl_device *device, unsigned int val); +int gmu_core_acd_set(struct kgsl_device *device, bool val); 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 cdd0a07309c7..d4affcda1b7d 100644 --- a/drivers/gpu/msm/kgsl_hfi.c +++ b/drivers/gpu/msm/kgsl_hfi.c @@ -653,7 +653,7 @@ static int hfi_send_lm_feature_ctrl(struct gmu_device *gmu, u32 slope = 0; int ret; - if (!test_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag)) + if (!adreno_dev->lm_enabled) return 0; memset(&req, 0, sizeof(req)); @@ -678,7 +678,7 @@ static int hfi_send_acd_feature_ctrl(struct gmu_device *gmu, { int ret = 0; - if (test_bit(ADRENO_ACD_CTRL, &adreno_dev->pwrctrl_flag)) { + if (adreno_dev->acd_enabled) { ret = hfi_send_acd_tbl(gmu); if (!ret) ret = hfi_send_feature_ctrl(gmu, HFI_FEATURE_ACD, 1, 0); diff --git a/drivers/gpu/msm/kgsl_rgmu.c b/drivers/gpu/msm/kgsl_rgmu.c index 008589ddae3f..dcd4f679769c 100644 --- a/drivers/gpu/msm/kgsl_rgmu.c +++ b/drivers/gpu/msm/kgsl_rgmu.c @@ -23,88 +23,65 @@ static int rgmu_irq_probe(struct kgsl_device *device) struct rgmu_device *rgmu = KGSL_RGMU_DEVICE(device); int ret; - rgmu->oob_interrupt_num = platform_get_irq_byname(rgmu->pdev, - "kgsl_oob"); - - ret = devm_request_irq(&rgmu->pdev->dev, - rgmu->oob_interrupt_num, - oob_irq_handler, IRQF_TRIGGER_HIGH, - "kgsl-oob", device); - if (ret) { - dev_err(&rgmu->pdev->dev, - "Request kgsl-oob interrupt failed:%d\n", ret); + ret = kgsl_request_irq(rgmu->pdev, "kgsl_oob", oob_irq_handler, device); + if (ret < 0) return ret; - } - rgmu->rgmu_interrupt_num = platform_get_irq_byname(rgmu->pdev, - "kgsl_rgmu"); + rgmu->oob_interrupt_num = ret; - ret = devm_request_irq(&rgmu->pdev->dev, - rgmu->rgmu_interrupt_num, - rgmu_irq_handler, IRQF_TRIGGER_HIGH, - "kgsl-rgmu", device); - if (ret) - dev_err(&rgmu->pdev->dev, - "Request kgsl-rgmu interrupt failed:%d\n", ret); + ret = kgsl_request_irq(rgmu->pdev, + "kgsl_rgmu", rgmu_irq_handler, device); + if (ret < 0) + return ret; - return ret; + rgmu->rgmu_interrupt_num = ret; + return 0; } -static int rgmu_regulators_probe(struct rgmu_device *rgmu, - struct device_node *node) +static int rgmu_regulators_probe(struct rgmu_device *rgmu) { - int ret; + int ret = 0; rgmu->cx_gdsc = devm_regulator_get(&rgmu->pdev->dev, "vddcx"); - if (IS_ERR_OR_NULL(rgmu->cx_gdsc)) { + if (IS_ERR(rgmu->cx_gdsc)) { ret = PTR_ERR(rgmu->cx_gdsc); - dev_err(&rgmu->pdev->dev, + if (ret != -EPROBE_DEFER) + dev_err(&rgmu->pdev->dev, "Couldn't get CX gdsc error:%d\n", ret); - rgmu->cx_gdsc = NULL; return ret; } rgmu->gx_gdsc = devm_regulator_get(&rgmu->pdev->dev, "vdd"); - if (IS_ERR_OR_NULL(rgmu->gx_gdsc)) { + if (IS_ERR(rgmu->gx_gdsc)) { ret = PTR_ERR(rgmu->gx_gdsc); - dev_err(&rgmu->pdev->dev, + if (ret != -EPROBE_DEFER) + dev_err(&rgmu->pdev->dev, "Couldn't get GX gdsc error:%d\n", ret); - rgmu->gx_gdsc = NULL; - return ret; } - return 0; + return ret; } static int rgmu_clocks_probe(struct rgmu_device *rgmu, struct device_node *node) { - const char *cname; - struct property *prop; - struct clk *c; - int i = 0; + int ret; - of_property_for_each_string(node, "clock-names", prop, cname) { + ret = devm_clk_bulk_get_all(&rgmu->pdev->dev, &rgmu->clks); + if (ret < 0) + return ret; - if (i >= ARRAY_SIZE(rgmu->clks)) { - dev_err(&rgmu->pdev->dev, - "dt: too many RGMU clocks defined\n"); - return -EINVAL; - } + rgmu->num_clks = ret; - c = devm_clk_get(&rgmu->pdev->dev, cname); - if (IS_ERR_OR_NULL(c)) { - dev_err(&rgmu->pdev->dev, - "dt: Couldn't get clock: %s\n", cname); - return PTR_ERR(c); - } + rgmu->gpu_clk = kgsl_of_clk_by_name(rgmu->clks, ret, "core"); + if (!rgmu->gpu_clk) { + dev_err(&rgmu->pdev->dev, "The GPU clock isn't defined\n"); + return -ENODEV; + } - /* Remember the key clocks that we need to control later */ - if (!strcmp(cname, "core")) - rgmu->gpu_clk = c; - else if (!strcmp(cname, "gmu")) - rgmu->rgmu_clk = c; - - rgmu->clks[i++] = c; + rgmu->rgmu_clk = kgsl_of_clk_by_name(rgmu->clks, ret, "gmu"); + if (!rgmu->rgmu_clk) { + dev_err(&rgmu->pdev->dev, "The RGMU clock isn't defined\n"); + return -ENODEV; } return 0; @@ -114,7 +91,7 @@ static void rgmu_disable_clks(struct kgsl_device *device) { struct rgmu_device *rgmu = KGSL_RGMU_DEVICE(device); struct gmu_dev_ops *gmu_dev_ops = GMU_DEVICE_OPS(device); - int j = 0, ret; + int ret; /* Check GX GDSC is status */ if (gmu_dev_ops->gx_is_on(device)) { @@ -141,22 +118,17 @@ static void rgmu_disable_clks(struct kgsl_device *device) dev_err(&rgmu->pdev->dev, "gx is stuck on\n"); } - for (j = 0; j < ARRAY_SIZE(rgmu->clks); j++) - clk_disable_unprepare(rgmu->clks[j]); + clk_bulk_disable_unprepare(rgmu->num_clks, rgmu->clks); clear_bit(GMU_CLK_ON, &device->gmu_core.flags); } static int rgmu_enable_clks(struct kgsl_device *device) { - int ret, j = 0; + int ret; struct rgmu_device *rgmu = KGSL_RGMU_DEVICE(device); struct kgsl_pwrctrl *pwr = &device->pwrctrl; - if (IS_ERR_OR_NULL(rgmu->rgmu_clk) || - IS_ERR_OR_NULL(rgmu->gpu_clk)) - return -EINVAL; - ret = clk_set_rate(rgmu->rgmu_clk, RGMU_CLK_FREQ); if (ret) { dev_err(&rgmu->pdev->dev, "Couldn't set the RGMU clock\n"); @@ -170,14 +142,10 @@ static int rgmu_enable_clks(struct kgsl_device *device) return ret; } - for (j = 0; j < ARRAY_SIZE(rgmu->clks); j++) { - ret = clk_prepare_enable(rgmu->clks[j]); - if (ret) { - dev_err(&rgmu->pdev->dev, - "Fail(%d) to enable gpucc clk idx %d\n", - ret, j); - return ret; - } + ret = clk_bulk_prepare_enable(rgmu->num_clks, rgmu->clks); + if (ret) { + dev_err(&rgmu->pdev->dev, "Failed to enable RGMU clocks\n"); + return ret; } set_bit(GMU_CLK_ON, &device->gmu_core.flags); @@ -289,42 +257,31 @@ static int rgmu_probe(struct kgsl_device *device, struct platform_device *pdev) rgmu->pdev = pdev; /* Set up RGMU regulators */ - ret = rgmu_regulators_probe(rgmu, pdev->dev.of_node); + ret = rgmu_regulators_probe(rgmu); if (ret) return ret; + /* Set up RGMU clocks */ ret = rgmu_clocks_probe(rgmu, pdev->dev.of_node); if (ret) return ret; /* Map and reserve RGMU CSRs registers */ - res = platform_get_resource_byname(rgmu->pdev, - IORESOURCE_MEM, "kgsl_rgmu"); - if (res == NULL) { - dev_err(&rgmu->pdev->dev, - "platform_get_resource failed\n"); - return -EINVAL; - } - - if (res->start == 0 || resource_size(res) == 0) { - dev_err(&rgmu->pdev->dev, - "Register region is invalid\n"); - return -EINVAL; - } - - rgmu->reg_phys = res->start; - rgmu->reg_len = resource_size(res); - device->gmu_core.reg_virt = devm_ioremap(&rgmu->pdev->dev, res->start, - resource_size(res)); - - if (device->gmu_core.reg_virt == NULL) { - dev_err(&rgmu->pdev->dev, "Unable to remap rgmu registers\n"); + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "kgsl_rgmu"); + if (!res) { + dev_err(&pdev->dev, "The RGMU register region isn't defined\n"); return -ENODEV; } - device->gmu_core.gmu2gpu_offset = - (rgmu->reg_phys - device->reg_phys) >> 2; - device->gmu_core.reg_len = rgmu->reg_len; + device->gmu_core.gmu2gpu_offset = (res->start - device->reg_phys) >> 2; + device->gmu_core.reg_len = resource_size(res); + device->gmu_core.reg_virt = devm_ioremap_resource(&pdev->dev, res); + + if (IS_ERR(device->gmu_core.reg_virt)) { + dev_err(&pdev->dev, "Unable to map the RGMU registers\n"); + return PTR_ERR(device->gmu_core.reg_virt); + } + device->gmu_core.ptr = (void *)rgmu; /* Initialize OOB and RGMU interrupts */ diff --git a/drivers/gpu/msm/kgsl_rgmu.h b/drivers/gpu/msm/kgsl_rgmu.h index 4b8f7f45955e..112f6e52c6ef 100644 --- a/drivers/gpu/msm/kgsl_rgmu.h +++ b/drivers/gpu/msm/kgsl_rgmu.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #ifndef __KGSL_RGMU_H #define __KGSL_RGMU_H @@ -18,9 +18,6 @@ /** * struct rgmu_device - rGMU device structure * @ver: RGMU firmware version - * @reg_phys: RGMU CSR physical address - * @reg_virt: RGMU CSR virtual address - * @reg_len: RGMU CSR range * @rgmu_interrupt_num: RGMU interrupt number * @oob_interrupt_num: number of RGMU asserted OOB interrupt * @fw_hostptr: Buffer which holds the RGMU firmware @@ -37,15 +34,15 @@ struct rgmu_device { u32 ver; struct platform_device *pdev; - unsigned long reg_phys; - unsigned int reg_len; unsigned int rgmu_interrupt_num; unsigned int oob_interrupt_num; unsigned int *fw_hostptr; uint32_t fw_size; struct regulator *cx_gdsc; struct regulator *gx_gdsc; - struct clk *clks[MAX_RGMU_CLKS]; + struct clk_bulk_data *clks; + /** @num_clks: Number of clocks in @clks */ + int num_clks; struct clk *gpu_clk; struct clk *rgmu_clk; unsigned int idle_level;