Loading drivers/gpu/msm/a4xx_reg.h +4 −0 Original line number Diff line number Diff line Loading @@ -200,6 +200,7 @@ enum a4xx_rb_perfctr_rb_sel { #define A4XX_RBBM_CFG_DEBBUS_CLRC 0x94 #define A4XX_RBBM_CFG_DEBBUS_LOADIVT 0x95 #define A4XX_RBBM_POWER_CNTL_IP 0x98 #define A4XX_RBBM_PERFCTR_CP_0_LO 0x9c #define A4XX_RBBM_PERFCTR_CP_0_HI 0x9d #define A4XX_RBBM_PERFCTR_CP_1_LO 0x9e Loading Loading @@ -402,6 +403,7 @@ enum a4xx_rb_perfctr_rb_sel { #define A4XX_RBBM_CFG_DEBBUS_TRACE_BUF4 0x1ad #define A4XX_RBBM_CFG_DEBBUS_MISR0 0x1ae #define A4XX_RBBM_CFG_DEBBUS_MISR1 0x1af #define A4XX_RBBM_POWER_STATUS 0x1b0 /* CP registers */ #define A4XX_CP_RB_BASE 0x200 Loading @@ -427,6 +429,7 @@ enum a4xx_rb_perfctr_rb_sel { #define A4XX_CP_ME_RAM_DATA 0x227 #define A4XX_CP_DEBUG 0x22e #define A4XX_CP_POWER_COLLAPSE_CNTL 0x234 /* * CP debug settings for A4xx cores * MIU_128BIT_WRITE_ENABLE [25] - Allow 128 bit writes to the VBIF Loading Loading @@ -697,6 +700,7 @@ enum a4xx_pc_perfctr_pc_sel { /* HLSQ registers */ #define A4XX_HLSQ_TIMEOUT_THRESHOLD 0xe00 #define A4XX_HLSQ_STATE_RESTORE_TRIGGER 0xe01 #define A4XX_HLSQ_PERFCTR_HLSQ_SEL_0 0xe06 #define A4XX_HLSQ_PERFCTR_HLSQ_SEL_1 0xe07 #define A4XX_HLSQ_PERFCTR_HLSQ_SEL_2 0xe08 Loading drivers/gpu/msm/adreno.c +37 −5 Original line number Diff line number Diff line Loading @@ -1639,6 +1639,11 @@ static int adreno_init(struct kgsl_device *device) if (test_bit(ADRENO_DEVICE_INITIALIZED, &adreno_dev->priv)) return 0; /* Identify the specific GPU */ adreno_identify_gpu(adreno_dev); gpudev = ADRENO_GPU_DEVICE(adreno_dev); /* Power up the device */ ret = kgsl_pwrctrl_enable(device); if (ret) Loading @@ -1647,11 +1652,6 @@ static int adreno_init(struct kgsl_device *device) /* Make a high priority workqueue for starting the GPU */ adreno_wq = alloc_workqueue("adreno", 0, 1); /* Identify the specific GPU */ adreno_identify_gpu(adreno_dev); gpudev = ADRENO_GPU_DEVICE(adreno_dev); /* Initialize coresight for the target */ adreno_coresight_init(device); Loading Loading @@ -2604,6 +2604,10 @@ bool adreno_hw_isidle(struct kgsl_device *device) struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); if (gpudev->is_sptp_idle) if (!gpudev->is_sptp_idle(adreno_dev)) return false; adreno_readreg(adreno_dev, ADRENO_REG_RBBM_STATUS, ®_rbbm_status); Loading Loading @@ -3102,6 +3106,30 @@ static unsigned int adreno_gpuid(struct kgsl_device *device, return (0x0003 << 16) | ADRENO_GPUREV(adreno_dev); } static void adreno_enable_pc(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); if (gpudev->enable_pc) gpudev->enable_pc(adreno_dev); } static void adreno_disable_pc(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); if (gpudev->disable_pc) gpudev->disable_pc(adreno_dev); } static void adreno_regulator_enable(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); if (gpudev->regulator_enable) gpudev->regulator_enable(adreno_dev); } static const struct kgsl_functable adreno_functable = { /* Mandatory functions */ .regread = adreno_regread, Loading Loading @@ -3133,6 +3161,10 @@ static const struct kgsl_functable adreno_functable = { .setproperty_compat = adreno_setproperty_compat, .drawctxt_sched = adreno_drawctxt_sched, .resume = adreno_dispatcher_start, .enable_pc = adreno_enable_pc, .disable_pc = adreno_disable_pc, .regulator_enable = adreno_regulator_enable, }; static struct platform_driver adreno_platform_driver = { Loading drivers/gpu/msm/adreno.h +5 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include "adreno_profile.h" #include "kgsl_iommu.h" #include <linux/stat.h> #include <linux/delay.h> #ifdef CONFIG_MSM_OCMEM #include <soc/qcom/ocmem.h> Loading Loading @@ -602,6 +603,10 @@ struct adreno_gpudev { void (*perfcounter_write)(struct adreno_device *adreno_dev, unsigned int group, unsigned int counter); void (*soft_reset)(struct adreno_device *device); bool (*is_sptp_idle)(struct adreno_device *); void (*enable_pc)(struct adreno_device *); void (*disable_pc)(struct adreno_device *); void (*regulator_enable)(struct adreno_device *); }; #define FT_DETECT_REGS_COUNT 14 Loading drivers/gpu/msm/adreno_a3xx.c +5 −0 Original line number Diff line number Diff line Loading @@ -1061,10 +1061,15 @@ int a3xx_perfcounter_enable(struct adreno_device *adreno_dev, } reg = &(counters->groups[group].regs[counter]); if (adreno_is_a4xx(adreno_dev)) gpudev->disable_pc(adreno_dev); /* Select the desired perfcounter */ kgsl_regwrite(&adreno_dev->dev, reg->select, countable); counters->groups[group].regs[counter].value = 0; if (adreno_is_a4xx(adreno_dev)) gpudev->enable_pc(adreno_dev); return 0; } Loading drivers/gpu/msm/adreno_a4xx.c +96 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,11 @@ #include "adreno_a3xx.h" #include "adreno_a4xx.h" #include "adreno_cp_parser.h" #include "adreno_trace.h" #define SP_TP_PWR_COLLAPSE_MASK 0x6 #define SP_TP_PWR_ON_MASK BIT(0) #define SP_TP_PWR_ON BIT(20) /* * Set of registers to dump for A4XX on snapshot. Loading Loading @@ -270,6 +275,92 @@ static const struct adreno_vbif_platform a4xx_vbif_platforms[] = { { adreno_is_a430, a430_vbif }, }; /* * a4xx_is_sptp_idle() - A430 SP/TP should be off to be considered idle * @adreno_dev: The adreno device pointer */ static bool a4xx_is_sptp_idle(struct adreno_device *adreno_dev) { unsigned int reg; struct kgsl_device *device = &adreno_dev->dev; if (adreno_is_a420(adreno_dev)) return true; /* If SP/TP pc isn't enabled, don't worry about power */ kgsl_regread(device, A4XX_CP_POWER_COLLAPSE_CNTL, ®); if (!(reg & 0x10)) return true; /* Check that SP/TP is off */ kgsl_regread(device, A4XX_RBBM_POWER_STATUS, ®); return !(reg & SP_TP_PWR_ON); } /* * a4xx_regulator_enable() - Enable any necessary HW regulators * @adreno_dev: The adreno device pointer * * Some HW blocks may need their regulators explicitly enabled * on a restart. Clocks must be on during this call. */ static void a4xx_regulator_enable(struct adreno_device *adreno_dev) { unsigned int reg; struct kgsl_device *device = &adreno_dev->dev; if (adreno_is_a420(adreno_dev)) return; kgsl_regread(device, A4XX_RBBM_POWER_CNTL_IP, ®); reg = (reg & ~SP_TP_PWR_ON_MASK); kgsl_regwrite(device, A4XX_RBBM_POWER_CNTL_IP, reg); do { udelay(5); kgsl_regread(device, A4XX_RBBM_POWER_STATUS, ®); } while (!(reg & SP_TP_PWR_ON)); trace_adreno_sp_tp((unsigned long) __builtin_return_address(0)); } /* * a4xx_enable_pc() - Enable the SP/TP block power collapse * @adreno_dev: The adreno device pointer */ static void a4xx_enable_pc(struct adreno_device *adreno_dev) { unsigned int reg; struct kgsl_device *device = &adreno_dev->dev; if (adreno_is_a420(adreno_dev)) return; kgsl_regread(device, A4XX_RBBM_POWER_CNTL_IP, ®); reg = (reg & ~SP_TP_PWR_COLLAPSE_MASK) | 0x2; kgsl_regwrite(device, A4XX_RBBM_POWER_CNTL_IP, reg); kgsl_regwrite(device, A4XX_CP_POWER_COLLAPSE_CNTL, 0x00400010); trace_adreno_sp_tp((unsigned long) __builtin_return_address(0)); }; /* * a4xx_disable_pc() - Disable the SP/TP block power collapse * @adreno_dev: The adreno device pointer */ static void a4xx_disable_pc(struct adreno_device *adreno_dev) { unsigned int reg; struct kgsl_device *device = &adreno_dev->dev; if (adreno_is_a420(adreno_dev)) return; /* remove hw control and use the sw override */ kgsl_regread(device, A4XX_RBBM_POWER_CNTL_IP, ®); reg = (reg & ~SP_TP_PWR_COLLAPSE_MASK) | 0x4; kgsl_regwrite(device, A4XX_RBBM_POWER_CNTL_IP, reg); /* turn the SP/TP on & restore it */ a4xx_regulator_enable(adreno_dev); kgsl_regwrite(device, A4XX_HLSQ_STATE_RESTORE_TRIGGER, 0x1); trace_adreno_sp_tp((unsigned long) __builtin_return_address(0)); } /* * a4xx_enable_hwcg() - Program the clock control registers * @device: The adreno device pointer Loading Loading @@ -456,6 +547,7 @@ static void a4xx_start(struct adreno_device *adreno_dev) (adreno_is_a420(adreno_dev) ? (1 << 29) : 0)); a4xx_enable_hwcg(device); a4xx_enable_pc(adreno_dev); /* * For A420 set RBBM_CLOCK_DELAY_HLSQ.CGC_HLSQ_TP_EARLY_CYC >= 2 * due to timing issue with HLSQ_TP_CLK_EN Loading Loading @@ -1266,4 +1358,8 @@ struct adreno_gpudev adreno_a4xx_gpudev = { .invalid_countables = a4xx_perfctr_invalid_countables, .soft_reset = a3xx_soft_reset, .snapshot = a4xx_snapshot, .is_sptp_idle = a4xx_is_sptp_idle, .enable_pc = a4xx_enable_pc, .disable_pc = a4xx_disable_pc, .regulator_enable = a4xx_regulator_enable, }; Loading
drivers/gpu/msm/a4xx_reg.h +4 −0 Original line number Diff line number Diff line Loading @@ -200,6 +200,7 @@ enum a4xx_rb_perfctr_rb_sel { #define A4XX_RBBM_CFG_DEBBUS_CLRC 0x94 #define A4XX_RBBM_CFG_DEBBUS_LOADIVT 0x95 #define A4XX_RBBM_POWER_CNTL_IP 0x98 #define A4XX_RBBM_PERFCTR_CP_0_LO 0x9c #define A4XX_RBBM_PERFCTR_CP_0_HI 0x9d #define A4XX_RBBM_PERFCTR_CP_1_LO 0x9e Loading Loading @@ -402,6 +403,7 @@ enum a4xx_rb_perfctr_rb_sel { #define A4XX_RBBM_CFG_DEBBUS_TRACE_BUF4 0x1ad #define A4XX_RBBM_CFG_DEBBUS_MISR0 0x1ae #define A4XX_RBBM_CFG_DEBBUS_MISR1 0x1af #define A4XX_RBBM_POWER_STATUS 0x1b0 /* CP registers */ #define A4XX_CP_RB_BASE 0x200 Loading @@ -427,6 +429,7 @@ enum a4xx_rb_perfctr_rb_sel { #define A4XX_CP_ME_RAM_DATA 0x227 #define A4XX_CP_DEBUG 0x22e #define A4XX_CP_POWER_COLLAPSE_CNTL 0x234 /* * CP debug settings for A4xx cores * MIU_128BIT_WRITE_ENABLE [25] - Allow 128 bit writes to the VBIF Loading Loading @@ -697,6 +700,7 @@ enum a4xx_pc_perfctr_pc_sel { /* HLSQ registers */ #define A4XX_HLSQ_TIMEOUT_THRESHOLD 0xe00 #define A4XX_HLSQ_STATE_RESTORE_TRIGGER 0xe01 #define A4XX_HLSQ_PERFCTR_HLSQ_SEL_0 0xe06 #define A4XX_HLSQ_PERFCTR_HLSQ_SEL_1 0xe07 #define A4XX_HLSQ_PERFCTR_HLSQ_SEL_2 0xe08 Loading
drivers/gpu/msm/adreno.c +37 −5 Original line number Diff line number Diff line Loading @@ -1639,6 +1639,11 @@ static int adreno_init(struct kgsl_device *device) if (test_bit(ADRENO_DEVICE_INITIALIZED, &adreno_dev->priv)) return 0; /* Identify the specific GPU */ adreno_identify_gpu(adreno_dev); gpudev = ADRENO_GPU_DEVICE(adreno_dev); /* Power up the device */ ret = kgsl_pwrctrl_enable(device); if (ret) Loading @@ -1647,11 +1652,6 @@ static int adreno_init(struct kgsl_device *device) /* Make a high priority workqueue for starting the GPU */ adreno_wq = alloc_workqueue("adreno", 0, 1); /* Identify the specific GPU */ adreno_identify_gpu(adreno_dev); gpudev = ADRENO_GPU_DEVICE(adreno_dev); /* Initialize coresight for the target */ adreno_coresight_init(device); Loading Loading @@ -2604,6 +2604,10 @@ bool adreno_hw_isidle(struct kgsl_device *device) struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); if (gpudev->is_sptp_idle) if (!gpudev->is_sptp_idle(adreno_dev)) return false; adreno_readreg(adreno_dev, ADRENO_REG_RBBM_STATUS, ®_rbbm_status); Loading Loading @@ -3102,6 +3106,30 @@ static unsigned int adreno_gpuid(struct kgsl_device *device, return (0x0003 << 16) | ADRENO_GPUREV(adreno_dev); } static void adreno_enable_pc(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); if (gpudev->enable_pc) gpudev->enable_pc(adreno_dev); } static void adreno_disable_pc(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); if (gpudev->disable_pc) gpudev->disable_pc(adreno_dev); } static void adreno_regulator_enable(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); if (gpudev->regulator_enable) gpudev->regulator_enable(adreno_dev); } static const struct kgsl_functable adreno_functable = { /* Mandatory functions */ .regread = adreno_regread, Loading Loading @@ -3133,6 +3161,10 @@ static const struct kgsl_functable adreno_functable = { .setproperty_compat = adreno_setproperty_compat, .drawctxt_sched = adreno_drawctxt_sched, .resume = adreno_dispatcher_start, .enable_pc = adreno_enable_pc, .disable_pc = adreno_disable_pc, .regulator_enable = adreno_regulator_enable, }; static struct platform_driver adreno_platform_driver = { Loading
drivers/gpu/msm/adreno.h +5 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include "adreno_profile.h" #include "kgsl_iommu.h" #include <linux/stat.h> #include <linux/delay.h> #ifdef CONFIG_MSM_OCMEM #include <soc/qcom/ocmem.h> Loading Loading @@ -602,6 +603,10 @@ struct adreno_gpudev { void (*perfcounter_write)(struct adreno_device *adreno_dev, unsigned int group, unsigned int counter); void (*soft_reset)(struct adreno_device *device); bool (*is_sptp_idle)(struct adreno_device *); void (*enable_pc)(struct adreno_device *); void (*disable_pc)(struct adreno_device *); void (*regulator_enable)(struct adreno_device *); }; #define FT_DETECT_REGS_COUNT 14 Loading
drivers/gpu/msm/adreno_a3xx.c +5 −0 Original line number Diff line number Diff line Loading @@ -1061,10 +1061,15 @@ int a3xx_perfcounter_enable(struct adreno_device *adreno_dev, } reg = &(counters->groups[group].regs[counter]); if (adreno_is_a4xx(adreno_dev)) gpudev->disable_pc(adreno_dev); /* Select the desired perfcounter */ kgsl_regwrite(&adreno_dev->dev, reg->select, countable); counters->groups[group].regs[counter].value = 0; if (adreno_is_a4xx(adreno_dev)) gpudev->enable_pc(adreno_dev); return 0; } Loading
drivers/gpu/msm/adreno_a4xx.c +96 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,11 @@ #include "adreno_a3xx.h" #include "adreno_a4xx.h" #include "adreno_cp_parser.h" #include "adreno_trace.h" #define SP_TP_PWR_COLLAPSE_MASK 0x6 #define SP_TP_PWR_ON_MASK BIT(0) #define SP_TP_PWR_ON BIT(20) /* * Set of registers to dump for A4XX on snapshot. Loading Loading @@ -270,6 +275,92 @@ static const struct adreno_vbif_platform a4xx_vbif_platforms[] = { { adreno_is_a430, a430_vbif }, }; /* * a4xx_is_sptp_idle() - A430 SP/TP should be off to be considered idle * @adreno_dev: The adreno device pointer */ static bool a4xx_is_sptp_idle(struct adreno_device *adreno_dev) { unsigned int reg; struct kgsl_device *device = &adreno_dev->dev; if (adreno_is_a420(adreno_dev)) return true; /* If SP/TP pc isn't enabled, don't worry about power */ kgsl_regread(device, A4XX_CP_POWER_COLLAPSE_CNTL, ®); if (!(reg & 0x10)) return true; /* Check that SP/TP is off */ kgsl_regread(device, A4XX_RBBM_POWER_STATUS, ®); return !(reg & SP_TP_PWR_ON); } /* * a4xx_regulator_enable() - Enable any necessary HW regulators * @adreno_dev: The adreno device pointer * * Some HW blocks may need their regulators explicitly enabled * on a restart. Clocks must be on during this call. */ static void a4xx_regulator_enable(struct adreno_device *adreno_dev) { unsigned int reg; struct kgsl_device *device = &adreno_dev->dev; if (adreno_is_a420(adreno_dev)) return; kgsl_regread(device, A4XX_RBBM_POWER_CNTL_IP, ®); reg = (reg & ~SP_TP_PWR_ON_MASK); kgsl_regwrite(device, A4XX_RBBM_POWER_CNTL_IP, reg); do { udelay(5); kgsl_regread(device, A4XX_RBBM_POWER_STATUS, ®); } while (!(reg & SP_TP_PWR_ON)); trace_adreno_sp_tp((unsigned long) __builtin_return_address(0)); } /* * a4xx_enable_pc() - Enable the SP/TP block power collapse * @adreno_dev: The adreno device pointer */ static void a4xx_enable_pc(struct adreno_device *adreno_dev) { unsigned int reg; struct kgsl_device *device = &adreno_dev->dev; if (adreno_is_a420(adreno_dev)) return; kgsl_regread(device, A4XX_RBBM_POWER_CNTL_IP, ®); reg = (reg & ~SP_TP_PWR_COLLAPSE_MASK) | 0x2; kgsl_regwrite(device, A4XX_RBBM_POWER_CNTL_IP, reg); kgsl_regwrite(device, A4XX_CP_POWER_COLLAPSE_CNTL, 0x00400010); trace_adreno_sp_tp((unsigned long) __builtin_return_address(0)); }; /* * a4xx_disable_pc() - Disable the SP/TP block power collapse * @adreno_dev: The adreno device pointer */ static void a4xx_disable_pc(struct adreno_device *adreno_dev) { unsigned int reg; struct kgsl_device *device = &adreno_dev->dev; if (adreno_is_a420(adreno_dev)) return; /* remove hw control and use the sw override */ kgsl_regread(device, A4XX_RBBM_POWER_CNTL_IP, ®); reg = (reg & ~SP_TP_PWR_COLLAPSE_MASK) | 0x4; kgsl_regwrite(device, A4XX_RBBM_POWER_CNTL_IP, reg); /* turn the SP/TP on & restore it */ a4xx_regulator_enable(adreno_dev); kgsl_regwrite(device, A4XX_HLSQ_STATE_RESTORE_TRIGGER, 0x1); trace_adreno_sp_tp((unsigned long) __builtin_return_address(0)); } /* * a4xx_enable_hwcg() - Program the clock control registers * @device: The adreno device pointer Loading Loading @@ -456,6 +547,7 @@ static void a4xx_start(struct adreno_device *adreno_dev) (adreno_is_a420(adreno_dev) ? (1 << 29) : 0)); a4xx_enable_hwcg(device); a4xx_enable_pc(adreno_dev); /* * For A420 set RBBM_CLOCK_DELAY_HLSQ.CGC_HLSQ_TP_EARLY_CYC >= 2 * due to timing issue with HLSQ_TP_CLK_EN Loading Loading @@ -1266,4 +1358,8 @@ struct adreno_gpudev adreno_a4xx_gpudev = { .invalid_countables = a4xx_perfctr_invalid_countables, .soft_reset = a3xx_soft_reset, .snapshot = a4xx_snapshot, .is_sptp_idle = a4xx_is_sptp_idle, .enable_pc = a4xx_enable_pc, .disable_pc = a4xx_disable_pc, .regulator_enable = a4xx_regulator_enable, };