Loading drivers/gpu/msm/adreno-gpulist.h +1 −0 Original line number Diff line number Diff line Loading @@ -1140,6 +1140,7 @@ static const struct adreno_a6xx_core adreno_gpu_core_a650 = { .vbif = a650_gbif_regs, .vbif_count = ARRAY_SIZE(a650_gbif_regs), .veto_fal10 = true, .pdc_in_aop = true, }; static const struct adreno_a6xx_core adreno_gpu_core_a680 = { Loading drivers/gpu/msm/adreno_a6xx.h +2 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,8 @@ struct adreno_a6xx_core { u32 vbif_count; /** @veto_fal10: veto status for fal10 feature */ bool veto_fal10; /** @pdc_in_aop: True if PDC programmed in AOP */ bool pdc_in_aop; }; #define CP_CLUSTER_FE 0x0 Loading drivers/gpu/msm/adreno_a6xx_gmu.c +78 −63 Original line number Diff line number Diff line Loading @@ -67,34 +67,60 @@ static void _regwrite(void __iomem *regbase, __raw_writel(value, reg); } /* * _load_gmu_rpmh_ucode() - Load the ucode into the GPU PDC/RSC blocks * PDC and RSC execute GPU power on/off RPMh sequence * @device: Pointer to KGSL device */ static int _load_gmu_rpmh_ucode(struct kgsl_device *device) static void a6xx_load_rsc_ucode(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); void __iomem *rscc; if (adreno_is_a650_family(adreno_dev)) rscc = adreno_dev->rscc_virt; else rscc = device->gmu_core.reg_virt + 0x23000; /* Disable SDE clock gating */ _regwrite(rscc, A6XX_GPU_RSCC_RSC_STATUS0_DRV0, BIT(24)); /* Setup RSC PDC handshake for sleep and wakeup */ _regwrite(rscc, A6XX_RSCC_PDC_SLAVE_ID_DRV0, 1); _regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_DATA, 0); _regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR, 0); _regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_DATA + RSC_CMD_OFFSET, 0); _regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR + RSC_CMD_OFFSET, 0); _regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_DATA + RSC_CMD_OFFSET * 2, 0x80000000); _regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR + RSC_CMD_OFFSET * 2, 0); _regwrite(rscc, A6XX_RSCC_OVERRIDE_START_ADDR, 0); _regwrite(rscc, A6XX_RSCC_PDC_SEQ_START_ADDR, 0x4520); _regwrite(rscc, A6XX_RSCC_PDC_MATCH_VALUE_LO, 0x4510); _regwrite(rscc, A6XX_RSCC_PDC_MATCH_VALUE_HI, 0x4514); /* Load RSC sequencer uCode for sleep and wakeup */ if (adreno_is_a650_family(adreno_dev)) { _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0, 0xEAAAE5A0); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 1, 0xE1A1EBAB); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 2, 0xA2E0A581); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 3, 0xECAC82E2); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 4, 0x0020EDAD); } else { _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0, 0xA7A506A0); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 1, 0xA1E6A6E7); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 2, 0xA2E081E1); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 3, 0xE9A982E2); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 4, 0x0020E8A8); } } static int a6xx_load_pdc_ucode(struct kgsl_device *device) { struct gmu_device *gmu = KGSL_GMU_DEVICE(device); struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct resource *res_pdc, *res_cfg, *res_seq; void __iomem *cfg = NULL, *seq = NULL, *rscc; unsigned int cfg_offset, seq_offset; void __iomem *cfg, *seq; const struct adreno_a6xx_core *a6xx_core = to_a6xx_core(adreno_dev); u32 vrm_resource_addr = cmd_db_read_addr("vrm.soc"); /* Offsets from the base PDC (if no PDC subsections in the DTSI) */ if (adreno_is_a640v2(adreno_dev)) { cfg_offset = 0x90000; seq_offset = 0x290000; } else { cfg_offset = 0x80000; seq_offset = 0x280000; } if (adreno_is_a650_family(adreno_dev)) rscc = adreno_dev->rscc_virt; else rscc = device->gmu_core.reg_virt + 0x23000; /* * Older A6x platforms specified PDC registers in the DT using a * single base pointer that encompassed the entire PDC range. Current Loading @@ -104,19 +130,29 @@ static int _load_gmu_rpmh_ucode(struct kgsl_device *device) * This code handles both possibilities and generates individual * pointers to the GPU PDC blocks, either as offsets from the single * base, or as directly specified ranges. * * PDC programming has moved to AOP for newer A6x platforms. * However registers to enable GPU PDC and set the sequence start * address still need to be programmed. */ /* Get pointers to each of the possible PDC resources */ res_pdc = platform_get_resource_byname(gmu->pdev, IORESOURCE_MEM, "kgsl_gmu_pdc_reg"); res_cfg = platform_get_resource_byname(gmu->pdev, IORESOURCE_MEM, "kgsl_gmu_pdc_cfg"); res_seq = platform_get_resource_byname(gmu->pdev, IORESOURCE_MEM, "kgsl_gmu_pdc_seq"); /* Offsets from the base PDC (if no PDC subsections in the DTSI) */ if (adreno_is_a640v2(adreno_dev)) { cfg_offset = 0x90000; seq_offset = 0x290000; } else { cfg_offset = 0x80000; seq_offset = 0x280000; } /* * Map the starting address for pdc_cfg programming. If the pdc_cfg * resource is not available use an offset from the base PDC resource. */ res_pdc = platform_get_resource_byname(gmu->pdev, IORESOURCE_MEM, "kgsl_gmu_pdc_reg"); res_cfg = platform_get_resource_byname(gmu->pdev, IORESOURCE_MEM, "kgsl_gmu_pdc_cfg"); if (res_cfg) cfg = ioremap(res_cfg->start, resource_size(res_cfg)); else if (res_pdc) Loading @@ -127,10 +163,16 @@ static int _load_gmu_rpmh_ucode(struct kgsl_device *device) return -ENODEV; } /* PDC is programmed in AOP for newer platforms */ if (a6xx_core->pdc_in_aop) goto done; /* * Map the starting address for pdc_seq programming. If the pdc_seq * resource is not available use an offset from the base PDC resource. */ res_seq = platform_get_resource_byname(gmu->pdev, IORESOURCE_MEM, "kgsl_gmu_pdc_seq"); if (res_seq) seq = ioremap(res_seq->start, resource_size(res_seq)); else if (res_pdc) Loading @@ -142,39 +184,6 @@ static int _load_gmu_rpmh_ucode(struct kgsl_device *device) return -ENODEV; } /* Disable SDE clock gating */ _regwrite(rscc, A6XX_GPU_RSCC_RSC_STATUS0_DRV0, BIT(24)); /* Setup RSC PDC handshake for sleep and wakeup */ _regwrite(rscc, A6XX_RSCC_PDC_SLAVE_ID_DRV0, 1); _regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_DATA, 0); _regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR, 0); _regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_DATA + RSC_CMD_OFFSET, 0); _regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR + RSC_CMD_OFFSET, 0); _regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_DATA + RSC_CMD_OFFSET * 2, 0x80000000); _regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR + RSC_CMD_OFFSET * 2, 0); _regwrite(rscc, A6XX_RSCC_OVERRIDE_START_ADDR, 0); _regwrite(rscc, A6XX_RSCC_PDC_SEQ_START_ADDR, 0x4520); _regwrite(rscc, A6XX_RSCC_PDC_MATCH_VALUE_LO, 0x4510); _regwrite(rscc, A6XX_RSCC_PDC_MATCH_VALUE_HI, 0x4514); /* Load RSC sequencer uCode for sleep and wakeup */ if (adreno_is_a650_family(adreno_dev)) { _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0, 0xEAAAE5A0); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 1, 0xE1A1EBAB); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 2, 0xA2E0A581); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 3, 0xECAC82E2); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 4, 0x0020EDAD); } else { _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0, 0xA7A506A0); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 1, 0xA1E6A6E7); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 2, 0xA2E081E1); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 3, 0xE9A982E2); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 4, 0x0020E8A8); } /* Load PDC sequencer uCode for power up and power down sequence */ _regwrite(seq, PDC_GPU_SEQ_MEM_0, 0xFEBEA1E1); _regwrite(seq, PDC_GPU_SEQ_MEM_0 + 1, 0xA5A4A3A2); Loading @@ -182,6 +191,8 @@ static int _load_gmu_rpmh_ucode(struct kgsl_device *device) _regwrite(seq, PDC_GPU_SEQ_MEM_0 + 3, 0xBCE3E284); _regwrite(seq, PDC_GPU_SEQ_MEM_0 + 4, 0x002081FC); iounmap(seq); /* Set TCS commands used by PDC sequence for low power modes */ _regwrite(cfg, PDC_GPU_TCS1_CMD_ENABLE_BANK, 7); _regwrite(cfg, PDC_GPU_TCS1_CMD_WAIT_FOR_CMPL_BANK, 0); Loading Loading @@ -238,19 +249,23 @@ static int _load_gmu_rpmh_ucode(struct kgsl_device *device) 0x1); } done: /* Setup GPU PDC */ _regwrite(cfg, PDC_GPU_SEQ_START_ADDR, 0); _regwrite(cfg, PDC_GPU_ENABLE_PDC, 0x80000001); /* ensure no writes happen before the uCode is fully written */ wmb(); iounmap(seq); iounmap(cfg); return 0; } static int _load_gmu_rpmh_ucode(struct kgsl_device *device) { a6xx_load_rsc_ucode(device); return a6xx_load_pdc_ucode(device); } /* GMU timeouts */ #define GMU_IDLE_TIMEOUT 100 /* ms */ #define GMU_START_TIMEOUT 100 /* ms */ Loading Loading
drivers/gpu/msm/adreno-gpulist.h +1 −0 Original line number Diff line number Diff line Loading @@ -1140,6 +1140,7 @@ static const struct adreno_a6xx_core adreno_gpu_core_a650 = { .vbif = a650_gbif_regs, .vbif_count = ARRAY_SIZE(a650_gbif_regs), .veto_fal10 = true, .pdc_in_aop = true, }; static const struct adreno_a6xx_core adreno_gpu_core_a680 = { Loading
drivers/gpu/msm/adreno_a6xx.h +2 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,8 @@ struct adreno_a6xx_core { u32 vbif_count; /** @veto_fal10: veto status for fal10 feature */ bool veto_fal10; /** @pdc_in_aop: True if PDC programmed in AOP */ bool pdc_in_aop; }; #define CP_CLUSTER_FE 0x0 Loading
drivers/gpu/msm/adreno_a6xx_gmu.c +78 −63 Original line number Diff line number Diff line Loading @@ -67,34 +67,60 @@ static void _regwrite(void __iomem *regbase, __raw_writel(value, reg); } /* * _load_gmu_rpmh_ucode() - Load the ucode into the GPU PDC/RSC blocks * PDC and RSC execute GPU power on/off RPMh sequence * @device: Pointer to KGSL device */ static int _load_gmu_rpmh_ucode(struct kgsl_device *device) static void a6xx_load_rsc_ucode(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); void __iomem *rscc; if (adreno_is_a650_family(adreno_dev)) rscc = adreno_dev->rscc_virt; else rscc = device->gmu_core.reg_virt + 0x23000; /* Disable SDE clock gating */ _regwrite(rscc, A6XX_GPU_RSCC_RSC_STATUS0_DRV0, BIT(24)); /* Setup RSC PDC handshake for sleep and wakeup */ _regwrite(rscc, A6XX_RSCC_PDC_SLAVE_ID_DRV0, 1); _regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_DATA, 0); _regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR, 0); _regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_DATA + RSC_CMD_OFFSET, 0); _regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR + RSC_CMD_OFFSET, 0); _regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_DATA + RSC_CMD_OFFSET * 2, 0x80000000); _regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR + RSC_CMD_OFFSET * 2, 0); _regwrite(rscc, A6XX_RSCC_OVERRIDE_START_ADDR, 0); _regwrite(rscc, A6XX_RSCC_PDC_SEQ_START_ADDR, 0x4520); _regwrite(rscc, A6XX_RSCC_PDC_MATCH_VALUE_LO, 0x4510); _regwrite(rscc, A6XX_RSCC_PDC_MATCH_VALUE_HI, 0x4514); /* Load RSC sequencer uCode for sleep and wakeup */ if (adreno_is_a650_family(adreno_dev)) { _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0, 0xEAAAE5A0); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 1, 0xE1A1EBAB); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 2, 0xA2E0A581); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 3, 0xECAC82E2); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 4, 0x0020EDAD); } else { _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0, 0xA7A506A0); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 1, 0xA1E6A6E7); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 2, 0xA2E081E1); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 3, 0xE9A982E2); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 4, 0x0020E8A8); } } static int a6xx_load_pdc_ucode(struct kgsl_device *device) { struct gmu_device *gmu = KGSL_GMU_DEVICE(device); struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct resource *res_pdc, *res_cfg, *res_seq; void __iomem *cfg = NULL, *seq = NULL, *rscc; unsigned int cfg_offset, seq_offset; void __iomem *cfg, *seq; const struct adreno_a6xx_core *a6xx_core = to_a6xx_core(adreno_dev); u32 vrm_resource_addr = cmd_db_read_addr("vrm.soc"); /* Offsets from the base PDC (if no PDC subsections in the DTSI) */ if (adreno_is_a640v2(adreno_dev)) { cfg_offset = 0x90000; seq_offset = 0x290000; } else { cfg_offset = 0x80000; seq_offset = 0x280000; } if (adreno_is_a650_family(adreno_dev)) rscc = adreno_dev->rscc_virt; else rscc = device->gmu_core.reg_virt + 0x23000; /* * Older A6x platforms specified PDC registers in the DT using a * single base pointer that encompassed the entire PDC range. Current Loading @@ -104,19 +130,29 @@ static int _load_gmu_rpmh_ucode(struct kgsl_device *device) * This code handles both possibilities and generates individual * pointers to the GPU PDC blocks, either as offsets from the single * base, or as directly specified ranges. * * PDC programming has moved to AOP for newer A6x platforms. * However registers to enable GPU PDC and set the sequence start * address still need to be programmed. */ /* Get pointers to each of the possible PDC resources */ res_pdc = platform_get_resource_byname(gmu->pdev, IORESOURCE_MEM, "kgsl_gmu_pdc_reg"); res_cfg = platform_get_resource_byname(gmu->pdev, IORESOURCE_MEM, "kgsl_gmu_pdc_cfg"); res_seq = platform_get_resource_byname(gmu->pdev, IORESOURCE_MEM, "kgsl_gmu_pdc_seq"); /* Offsets from the base PDC (if no PDC subsections in the DTSI) */ if (adreno_is_a640v2(adreno_dev)) { cfg_offset = 0x90000; seq_offset = 0x290000; } else { cfg_offset = 0x80000; seq_offset = 0x280000; } /* * Map the starting address for pdc_cfg programming. If the pdc_cfg * resource is not available use an offset from the base PDC resource. */ res_pdc = platform_get_resource_byname(gmu->pdev, IORESOURCE_MEM, "kgsl_gmu_pdc_reg"); res_cfg = platform_get_resource_byname(gmu->pdev, IORESOURCE_MEM, "kgsl_gmu_pdc_cfg"); if (res_cfg) cfg = ioremap(res_cfg->start, resource_size(res_cfg)); else if (res_pdc) Loading @@ -127,10 +163,16 @@ static int _load_gmu_rpmh_ucode(struct kgsl_device *device) return -ENODEV; } /* PDC is programmed in AOP for newer platforms */ if (a6xx_core->pdc_in_aop) goto done; /* * Map the starting address for pdc_seq programming. If the pdc_seq * resource is not available use an offset from the base PDC resource. */ res_seq = platform_get_resource_byname(gmu->pdev, IORESOURCE_MEM, "kgsl_gmu_pdc_seq"); if (res_seq) seq = ioremap(res_seq->start, resource_size(res_seq)); else if (res_pdc) Loading @@ -142,39 +184,6 @@ static int _load_gmu_rpmh_ucode(struct kgsl_device *device) return -ENODEV; } /* Disable SDE clock gating */ _regwrite(rscc, A6XX_GPU_RSCC_RSC_STATUS0_DRV0, BIT(24)); /* Setup RSC PDC handshake for sleep and wakeup */ _regwrite(rscc, A6XX_RSCC_PDC_SLAVE_ID_DRV0, 1); _regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_DATA, 0); _regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR, 0); _regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_DATA + RSC_CMD_OFFSET, 0); _regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR + RSC_CMD_OFFSET, 0); _regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_DATA + RSC_CMD_OFFSET * 2, 0x80000000); _regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR + RSC_CMD_OFFSET * 2, 0); _regwrite(rscc, A6XX_RSCC_OVERRIDE_START_ADDR, 0); _regwrite(rscc, A6XX_RSCC_PDC_SEQ_START_ADDR, 0x4520); _regwrite(rscc, A6XX_RSCC_PDC_MATCH_VALUE_LO, 0x4510); _regwrite(rscc, A6XX_RSCC_PDC_MATCH_VALUE_HI, 0x4514); /* Load RSC sequencer uCode for sleep and wakeup */ if (adreno_is_a650_family(adreno_dev)) { _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0, 0xEAAAE5A0); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 1, 0xE1A1EBAB); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 2, 0xA2E0A581); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 3, 0xECAC82E2); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 4, 0x0020EDAD); } else { _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0, 0xA7A506A0); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 1, 0xA1E6A6E7); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 2, 0xA2E081E1); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 3, 0xE9A982E2); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 4, 0x0020E8A8); } /* Load PDC sequencer uCode for power up and power down sequence */ _regwrite(seq, PDC_GPU_SEQ_MEM_0, 0xFEBEA1E1); _regwrite(seq, PDC_GPU_SEQ_MEM_0 + 1, 0xA5A4A3A2); Loading @@ -182,6 +191,8 @@ static int _load_gmu_rpmh_ucode(struct kgsl_device *device) _regwrite(seq, PDC_GPU_SEQ_MEM_0 + 3, 0xBCE3E284); _regwrite(seq, PDC_GPU_SEQ_MEM_0 + 4, 0x002081FC); iounmap(seq); /* Set TCS commands used by PDC sequence for low power modes */ _regwrite(cfg, PDC_GPU_TCS1_CMD_ENABLE_BANK, 7); _regwrite(cfg, PDC_GPU_TCS1_CMD_WAIT_FOR_CMPL_BANK, 0); Loading Loading @@ -238,19 +249,23 @@ static int _load_gmu_rpmh_ucode(struct kgsl_device *device) 0x1); } done: /* Setup GPU PDC */ _regwrite(cfg, PDC_GPU_SEQ_START_ADDR, 0); _regwrite(cfg, PDC_GPU_ENABLE_PDC, 0x80000001); /* ensure no writes happen before the uCode is fully written */ wmb(); iounmap(seq); iounmap(cfg); return 0; } static int _load_gmu_rpmh_ucode(struct kgsl_device *device) { a6xx_load_rsc_ucode(device); return a6xx_load_pdc_ucode(device); } /* GMU timeouts */ #define GMU_IDLE_TIMEOUT 100 /* ms */ #define GMU_START_TIMEOUT 100 /* ms */ Loading