以Find x3 pro设备树文件为例进行分析:https://github.com/oppo-source/android_kernel_modules_and_devicetree_oppo_sm8350/blob/oppo/sm8350_s_12.1_find_x3_pro/vendor/qcom/proprietary/devicetree/qcom/sm8150-gpu.dtsi
1. dts配置文件
#define MHZ_TO_KBPS(mhz, w) ((mhz * 1000000 * w) / (1024))&soc {pil_gpu: qcom,kgsl-hyp {compatible = "qcom,pil-tz-generic";qcom,pas-id = <13>;qcom,firmware-name = "a640_zap";memory-region = <&pil_gpu_mem>;};// kgsl配置msm_gpu: qcom,kgsl-3d0@2c00000 {label = "kgsl-3d0";compatible = "qcom,kgsl-3d0", "qcom,kgsl-3d";status = "ok";// 寄存器地址与偏移量reg = <0x2c00000 0x40000>, <0x2c61000 0x800>,<0x6900000 0x44000>, <0x780000 0x6fff>;// 寄存器名称reg-names = "kgsl_3d0_reg_memory", "cx_dbgc","qdss_gfx", "qfprom_memory";interrupts = <0 300 IRQ_TYPE_LEVEL_HIGH>;// 中断名称interrupt-names = "kgsl_3d0_irq";qcom,id = <0>;// 主版本号:6// 副版本号:4// patchid: 0qcom,chipid = <0x06040000>;// 默认频率qcom,initial-pwrlevel = <5>;qcom,gpu-quirk-secvid-set-once;qcom,gpu-quirk-cx-gdsc;qcom,idle-timeout = <80>; //msecsqcom,no-nap;qcom,highest-bank-bit = <15>;qcom,min-access-length = <32>;qcom,ubwc-mode = <3>;qcom,gpu-qdss-stm = <0x161c0000 0x40000>; // base addr, size#cooling-cells = <2>;// 时钟clocks = <&gcc GCC_GPU_CFG_AHB_CLK>,<&gpucc GPU_CC_CXO_CLK>,<&gcc GCC_DDRSS_GPU_AXI_CLK>,<&gcc GCC_GPU_MEMNOC_GFX_CLK>,<&gpucc GPU_CC_CX_GMU_CLK>,<&gpucc GPU_CC_AHB_CLK>;// 时钟名称clock-names = "gcc_gpu_ahb", "rbbmtimer_clk","gcc_gpu_axi_clk", "gcc_gpu_memnoc_gfx","gmu_clk", "gpu_cc_ahb";qcom,isense-clk-on-level = <1>;interconnects = <&gem_noc MASTER_GFX3D &mc_virt SLAVE_EBI1>;interconnect-names = "gpu_icc_path";qcom,bus-table-ddr =<MHZ_TO_KBPS(0, 4)>, /* index=0 */<MHZ_TO_KBPS(100, 4)>, /* index=1 */<MHZ_TO_KBPS(150, 4)>, /* index=2 */<MHZ_TO_KBPS(200, 4)>, /* index=3 */<MHZ_TO_KBPS(300, 4)>, /* index=4 */<MHZ_TO_KBPS(412, 4)>, /* index=5 */<MHZ_TO_KBPS(547, 4)>, /* index=6 */<MHZ_TO_KBPS(681, 4)>, /* index=7 */<MHZ_TO_KBPS(768, 4)>, /* index=8 */<MHZ_TO_KBPS(1017, 4)>, /* index=9 */<MHZ_TO_KBPS(1296, 4)>, /* index=10 */<MHZ_TO_KBPS(1555, 4)>, /* index=11 */<MHZ_TO_KBPS(1804, 4)>; /* index=12 */qcom,bus-table-cnoc =<0>, /* Off */<100>; /* On *//* GDSC regulator names */regulator-names = "vddcx", "vdd";/* GDSC oxili regulators */vddcx-supply = <&gpu_cx_gdsc>;vdd-supply = <&gpu_gx_gdsc>;qcom,l3-pwrlevels {#address-cells = <1>;#size-cells = <0>;compatible = "qcom,l3-pwrlevels";qcom,l3-pwrlevel@0 {reg = <0>;qcom,l3-freq = <0>;};qcom,l3-pwrlevel@1 {reg = <1>;qcom,l3-freq = <864000000>;};qcom,l3-pwrlevel@2 {reg = <2>;qcom,l3-freq = <1344000000>;};};/* GPU Mempools */// kgsl内存池配置qcom,gpu-mempools {#address-cells = <1>;#size-cells = <0>;compatible = "qcom,gpu-mempools";/* 4K Page Pool configuration */qcom,gpu-mempool@0 {reg = <0>;qcom,mempool-page-size = <4096>;qcom,mempool-reserved = <2048>;qcom,mempool-allocate;};/* 8K Page Pool configuration */qcom,gpu-mempool@1 {reg = <1>;qcom,mempool-page-size = <8192>;qcom,mempool-reserved = <1024>;qcom,mempool-allocate;};/* 64K Page Pool configuration */qcom,gpu-mempool@2 {reg = <2>;qcom,mempool-page-size = <65536>;qcom,mempool-reserved = <256>;};/* 1M Page Pool configuration */qcom,gpu-mempool@3 {reg = <3>;qcom,mempool-page-size = <1048576>;qcom,mempool-reserved = <32>;};};/* Power levels */// kgsl频率配置qcom,gpu-pwrlevels {#address-cells = <1>;#size-cells = <0>;compatible = "qcom,gpu-pwrlevels";qcom,gpu-pwrlevel@0 {reg = <0>;qcom,gpu-freq = <600000000>;qcom,level = <RPMH_REGULATOR_LEVEL_TURBO>;qcom,bus-freq = <12>;qcom,bus-min = <10>;qcom,bus-max = <12>;};qcom,gpu-pwrlevel@1 {reg = <1>;qcom,gpu-freq = <553850000>;qcom,level = <RPMH_REGULATOR_LEVEL_NOM_L1>;qcom,bus-freq = <10>;qcom,bus-min = <9>;qcom,bus-max = <11>;};qcom,gpu-pwrlevel@2 {reg = <2>;qcom,gpu-freq = <486460000>;qcom,level = <RPMH_REGULATOR_LEVEL_NOM>;qcom,bus-freq = <9>;qcom,bus-min = <8>;qcom,bus-max = <10>;};qcom,gpu-pwrlevel@3 {reg = <3>;qcom,gpu-freq = <379650000>;qcom,level = <RPMH_REGULATOR_LEVEL_SVS_L1>;qcom,bus-freq = <8>;qcom,bus-min = <7>;qcom,bus-max = <9>;};qcom,gpu-pwrlevel@4 {reg = <4>;qcom,gpu-freq = <309110000>;qcom,level = <RPMH_REGULATOR_LEVEL_SVS>;qcom,bus-freq = <5>;qcom,bus-min = <5>;qcom,bus-max = <7>;};qcom,gpu-pwrlevel@5 {reg = <5>;qcom,gpu-freq = <215000000>;qcom,level = <RPMH_REGULATOR_LEVEL_LOW_SVS>;qcom,bus-freq = <4>;qcom,bus-min = <3>;qcom,bus-max = <5>;};qcom,gpu-pwrlevel@6 {reg = <6>;qcom,gpu-freq = <0>;qcom,level = <RPMH_REGULATOR_LEVEL_RETENTION>;qcom,bus-freq = <0>;qcom,bus-min = <0>;qcom,bus-max = <0>;};};};// iommu配置kgsl_msm_iommu: qcom,kgsl-iommu@2ca0000 {compatible = "qcom,kgsl-smmu-v2";reg = <0x2ca0000 0x10000>;gfx3d_user: gfx3d_user {compatible = "qcom,smmu-kgsl-cb";label = "gfx3d_user";iommus = <&kgsl_smmu 0x0 0x401>;qcom,iommu-dma = "disabled";};gfx3d_secure: gfx3d_secure {compatible = "qcom,smmu-kgsl-cb";label = "gfx3d_secure";iommus = <&kgsl_smmu 0x2 0x400>;qcom,iommu-dma = "disabled";};};// gmu配置gmu: qcom,gmu@2c6a000 {compatible = "qcom,gpu-gmu";reg = <0x2c6a000 0x30000>,<0xb280000 0x10000>,<0xb480000 0x10000>;reg-names = "kgsl_gmu_reg","kgsl_gmu_pdc_cfg","kgsl_gmu_pdc_seq";interrupts = <0 304 IRQ_TYPE_LEVEL_HIGH>,<0 305 IRQ_TYPE_LEVEL_HIGH>;interrupt-names = "kgsl_hfi_irq", "kgsl_gmu_irq";regulator-names = "vddcx", "vdd";iommus = <&kgsl_smmu 0x5 0x400>;qcom,iommu-dma = "disabled";vddcx-supply = <&gpu_cx_gdsc>;vdd-supply = <&gpu_gx_gdsc>;clocks = <&gpucc GPU_CC_CX_GMU_CLK>,<&gpucc GPU_CC_CXO_CLK>,<&gcc GCC_DDRSS_GPU_AXI_CLK>,<&gcc GCC_GPU_MEMNOC_GFX_CLK>,<&gpucc GPU_CC_AHB_CLK>;clock-names = "gmu_clk", "cxo_clk", "axi_clk","gcc_gpu_memnoc_gfx_clk", "gpu_cc_ahb";/* AOP mailbox for sending ACD enable and disable messages */mboxes = <&qmp_aop 0>;mbox-names = "aop";};
};
2. adreno_gpu_core
/*** struct adreno_gpu_core - A specific GPU core definition*/
// 定义adreno gpu的核心实现
struct adreno_gpu_core {enum adreno_gpurev gpurev;// 核心系列, 主版本号, 副版本号, patchidunsigned int core, major, minor, patchid;/*** @compatible: If specified, use the compatible string to match the* device*/const char *compatible;// 支持的特性unsigned long features;// Pointer to the GPU family specific functions for this core[见2.1节]const struct adreno_gpudev *gpudev;// 性能计数器[见2.2节]const struct adreno_perfcounters *perfcounters;size_t gmem_size;u32 bus_width;/** @snapshot_size: Size of the static snapshot region in bytes */u32 snapshot_size;
};
2.1 adreno_gpudev
struct adreno_gpudev {/** These registers are in a different location on different devices,* so define them in the structure and use them as variables.*/// 寄存器偏移地址unsigned int *const reg_offsets;const struct adreno_ft_perf_counters *ft_perf_counters;unsigned int ft_perf_counters_count;struct adreno_coresight *coresight[2];/* GPU specific function hooks */int (*probe)(struct platform_device *pdev, u32 chipid,const struct adreno_gpu_core *gpucore);void (*snapshot)(struct adreno_device *adreno_dev,struct kgsl_snapshot *snapshot);irqreturn_t (*irq_handler)(struct adreno_device *adreno_dev);int (*init)(struct adreno_device *adreno_dev);void (*remove)(struct adreno_device *adreno_dev);int (*rb_start)(struct adreno_device *adreno_dev);int (*microcode_read)(struct adreno_device *adreno_dev);void (*start)(struct adreno_device *adreno_dev);bool (*is_sptp_idle)(struct adreno_device *adreno_dev);int (*regulator_enable)(struct adreno_device *adreno_dev);void (*regulator_disable)(struct adreno_device *adreno_dev);void (*pwrlevel_change_settings)(struct adreno_device *adreno_dev,unsigned int prelevel, unsigned int postlevel,bool post);int64_t (*read_throttling_counters)(struct adreno_device *adreno_dev);void (*count_throttles)(struct adreno_device *adreno_dev,uint64_t adj);unsigned int (*preemption_pre_ibsubmit)(struct adreno_device *adreno_dev,struct adreno_ringbuffer *rb,unsigned int *cmds,struct kgsl_context *context);int (*preemption_yield_enable)(unsigned int *cmds);unsigned int (*set_marker)(unsigned int *cmds,enum adreno_cp_marker_type type);unsigned int (*preemption_post_ibsubmit)(struct adreno_device *adreno_dev,unsigned int *cmds);int (*preemption_init)(struct adreno_device *adreno_dev);void (*preemption_schedule)(struct adreno_device *adreno_dev);int (*preemption_context_init)(struct kgsl_context *context);void (*context_detach)(struct adreno_context *drawctxt);void (*clk_set_options)(struct adreno_device *adreno_dev,const char *name, struct clk *clk, bool on);void (*pre_reset)(struct adreno_device *adreno_dev);void (*gpu_keepalive)(struct adreno_device *adreno_dev,bool state);bool (*hw_isidle)(struct adreno_device *adreno_dev);const char *(*iommu_fault_block)(struct kgsl_device *device,unsigned int fsynr1);int (*reset)(struct kgsl_device *device);bool (*sptprac_is_on)(struct adreno_device *adreno_dev);unsigned int (*ccu_invalidate)(struct adreno_device *adreno_dev,unsigned int *cmds);/** @read_alwayson: Return the current value of the alwayson counter */u64 (*read_alwayson)(struct adreno_device *adreno_dev);/*** @power_ops: Target specific function pointers to power up/down the* gpu*/const struct adreno_power_ops *power_ops;int (*clear_pending_transactions)(struct adreno_device *adreno_dev);void (*deassert_gbif_halt)(struct adreno_device *adreno_dev);void (*regulator_disable_poll)(struct kgsl_device *device);
};
2.2 adreno_perfcounters
/*** adreno_perfcounts: all available perfcounter groups* @groups: available groups for this device* @group_count: total groups for this device*/
struct adreno_perfcounters {// 性能计数器组[见2.2.1节]const struct adreno_perfcount_group *groups;// 性能计数器组个数unsigned int group_count;
};
2.2.1 adreno_perfcount_group
/*** struct adreno_perfcount_group: registers for a hardware group* @regs: available registers for this group* @reg_count: total registers for this group* @name: group name for this group*/
struct adreno_perfcount_group {// 性能计数器寄存器[见2.2.2节]struct adreno_perfcount_register *regs;// 性能计数器组寄存器个数unsigned int reg_count;// 性能计数器组名称const char *name;// 性能计数器组标志位unsigned long flags;int (*enable)(struct adreno_device *adreno_dev,const struct adreno_perfcount_group *group,unsigned int counter, unsigned int countable);u64 (*read)(struct adreno_device *adreno_dev,const struct adreno_perfcount_group *group,unsigned int counter);
};
2.2.2 adreno_perfcount_register
/*** struct adreno_perfcount_register: register state* @countable: countable the register holds* @kernelcount: number of user space users of the register* @usercount: number of kernel users of the register* @offset: register hardware offset* @load_bit: The bit number in LOAD register which corresponds to this counter* @select: The countable register offset* @value: The 64 bit countable register value*/
struct adreno_perfcount_register {unsigned int countable;// 内核空间引用计数unsigned int kernelcount;// 用户空间引用计数unsigned int usercount;// 寄存器低位偏移地址unsigned int offset;// 寄存器高位偏移地址unsigned int offset_hi;int load_bit;unsigned int select;// 寄存器值uint64_t value;
};
3. adreno gpu列表
// adreno系列gpu的核心定义
static const struct adreno_gpu_core *adreno_gpulist[] = {&adreno_gpu_core_a306.base,&adreno_gpu_core_a306a.base,&adreno_gpu_core_a304.base,&adreno_gpu_core_a405, /* Deprecated */&adreno_gpu_core_a418, /* Deprecated */&adreno_gpu_core_a420, /* Deprecated */&adreno_gpu_core_a430, /* Deprecated */&adreno_gpu_core_a530v1, /* Deprecated */&adreno_gpu_core_a530v2.base,&adreno_gpu_core_a530v3.base,&adreno_gpu_core_a505.base,&adreno_gpu_core_a506.base,&adreno_gpu_core_a510.base,&adreno_gpu_core_a540v1, /* Deprecated */&adreno_gpu_core_a540v2.base,&adreno_gpu_core_a512.base,&adreno_gpu_core_a508.base,&adreno_gpu_core_a630v1, /* Deprecated */&adreno_gpu_core_a630v2.base,&adreno_gpu_core_a615.base,&adreno_gpu_core_a618.base,&adreno_gpu_core_a619.base,&adreno_gpu_core_a619_variant.base,&adreno_gpu_core_a620.base,// 以8155搭载的Adreno640为例进行分析[见3.1节]&adreno_gpu_core_a640.base,&adreno_gpu_core_a650.base,&adreno_gpu_core_a650v2.base,&adreno_gpu_core_a660.base,&adreno_gpu_core_a660v2.base,&adreno_gpu_core_a680.base,&adreno_gpu_core_a612.base,&adreno_gpu_core_a616.base,&adreno_gpu_core_a610.base,&adreno_gpu_core_a642.base,&adreno_gpu_core_a642l.base,&adreno_gpu_core_a702.base,
};
3.1 adreno_gpu_core_a640
// adreno_a6xx_core是6xx系列GPU核心定义
static const struct adreno_a6xx_core adreno_gpu_core_a640 = {// base即adreno_gpu_core.base = {// 版本DEFINE_ADRENO_REV(ADRENO_REV_A640, 6, 4, 0, ANY_ID),// 特性.features = ADRENO_RPMH | ADRENO_GPMU |ADRENO_CONTENT_PROTECTION | ADRENO_IOCOHERENT |ADRENO_IFPC | ADRENO_PREEMPTION,// a640的adreno_gpudev[见3.2节].gpudev = &adreno_a6xx_gmu_gpudev,// a640的性能计数器[见3.3节].perfcounters = &adreno_a6xx_legacy_perfcounters,.gmem_size = SZ_1M, //Verified 1MB.bus_width = 32,.snapshot_size = 2 * SZ_1M,},.prim_fifo_threshold = 0x00200000,.gmu_major = 2,.gmu_minor = 0,.sqefw_name = "a630_sqe.fw",.gmufw_name = "a640_gmu.bin",.zap_name = "a640_zap",.hwcg = a640_hwcg_regs,.hwcg_count = ARRAY_SIZE(a640_hwcg_regs),.vbif = a640_vbif_regs,.vbif_count = ARRAY_SIZE(a640_vbif_regs),.hang_detect_cycles = 0xcfffff,.protected_regs = a630_protected_regs,.disable_tseskip = true,.highest_bank_bit = 15,
};
3.2 adreno_a6xx_gmu_gpudev
const struct adreno_gpudev adreno_a6xx_gmu_gpudev = {// 寄存器偏移量.reg_offsets = a6xx_register_offsets,// probe函数.probe = a6xx_gmu_device_probe,// 启动函数.start = a6xx_start,.snapshot = a6xx_gmu_snapshot,// 初始化函数.init = a6xx_init,// 中断处理函数.irq_handler = a6xx_irq_handler,// ringbuffer启动函数.rb_start = a6xx_rb_start,.regulator_enable = a6xx_gmu_sptprac_enable,.regulator_disable = a6xx_gmu_sptprac_disable,.read_throttling_counters = a6xx_read_throttling_counters,.microcode_read = a6xx_microcode_read,.gpu_keepalive = a6xx_gpu_keepalive,.hw_isidle = a6xx_hw_isidle,.iommu_fault_block = a6xx_iommu_fault_block,.reset = a6xx_gmu_restart,.preemption_pre_ibsubmit = a6xx_preemption_pre_ibsubmit,.preemption_post_ibsubmit = a6xx_preemption_post_ibsubmit,.preemption_init = a6xx_preemption_init,.preemption_schedule = a6xx_preemption_schedule,.set_marker = a6xx_set_marker,.preemption_context_init = a6xx_preemption_context_init,.sptprac_is_on = a6xx_gmu_sptprac_is_on,.ccu_invalidate = a6xx_ccu_invalidate,
#ifdef CONFIG_QCOM_KGSL_CORESIGHT.coresight = {&a6xx_coresight, &a6xx_coresight_cx},
#endif.read_alwayson = a6xx_read_alwayson,.power_ops = &a6xx_gmu_power_ops,
};
3.3 adreno_a6xx_legacy_perfcounters
/* a610, a612, a616, a618 and a619 do not have the GMU registers.* a605, a608, a615, a630, a640 and a680 don't have enough room in the* CP_PROTECT registers so the GMU counters are not accessible*/
const struct adreno_perfcounters adreno_a6xx_legacy_perfcounters = {a6xx_legacy_perfcounter_groups,ARRAY_SIZE(a6xx_legacy_perfcounter_groups),
};// a640性能计数器组定义
static const struct adreno_perfcount_group
a6xx_legacy_perfcounter_groups [KGSL_PERFCOUNTER_GROUP_MAX] = {A6XX_PERFCOUNTER_GROUP(CP, cp,a6xx_counter_enable, a6xx_counter_read),A6XX_PERFCOUNTER_GROUP_FLAGS(RBBM, rbbm, 0,a6xx_counter_enable, a6xx_counter_read),A6XX_PERFCOUNTER_GROUP(PC, pc,a6xx_counter_enable, a6xx_counter_read),A6XX_PERFCOUNTER_GROUP(VFD, vfd,a6xx_counter_enable, a6xx_counter_read),A6XX_PERFCOUNTER_GROUP(HLSQ, hlsq,a6xx_counter_inline_enable, a6xx_counter_read),A6XX_PERFCOUNTER_GROUP(VPC, vpc,a6xx_counter_enable, a6xx_counter_read),A6XX_PERFCOUNTER_GROUP(CCU, ccu,a6xx_counter_enable, a6xx_counter_read),A6XX_PERFCOUNTER_GROUP(CMP, cmp,a6xx_counter_enable, a6xx_counter_read),A6XX_PERFCOUNTER_GROUP(TSE, tse,a6xx_counter_enable, a6xx_counter_read),A6XX_PERFCOUNTER_GROUP(RAS, ras,a6xx_counter_enable, a6xx_counter_read),A6XX_PERFCOUNTER_GROUP(LRZ, lrz,a6xx_counter_enable, a6xx_counter_read),A6XX_PERFCOUNTER_GROUP(UCHE, uche,a6xx_counter_enable, a6xx_counter_read),A6XX_PERFCOUNTER_GROUP(TP, tp,a6xx_counter_inline_enable, a6xx_counter_read),A6XX_PERFCOUNTER_GROUP(SP, sp,a6xx_counter_inline_enable, a6xx_counter_read),A6XX_PERFCOUNTER_GROUP(RB, rb,a6xx_counter_enable, a6xx_counter_read),A6XX_PERFCOUNTER_GROUP(VSC, vsc,a6xx_counter_enable, a6xx_counter_read),A6XX_PERFCOUNTER_GROUP_FLAGS(VBIF, gbif, 0,a6xx_counter_gbif_enable, a6xx_counter_read_norestore),A6XX_PERFCOUNTER_GROUP_FLAGS(VBIF_PWR, gbif_pwr,ADRENO_PERFCOUNTER_GROUP_FIXED,a6xx_counter_gbif_pwr_enable, a6xx_counter_read_norestore),A6XX_PERFCOUNTER_GROUP_FLAGS(ALWAYSON, alwayson,ADRENO_PERFCOUNTER_GROUP_FIXED,a6xx_counter_alwayson_enable, a6xx_counter_alwayson_read),
};