/** * struct panthor_model - GPU model description
*/ struct panthor_model { /** @name: Model name. */ constchar *name;
/** @arch_major: Major version number of architecture. */
u8 arch_major;
/** @product_major: Major version number of product. */
u8 product_major;
};
/** * GPU_MODEL() - Define a GPU model. A GPU product can be uniquely identified * by a combination of the major architecture version and the major product * version. * @_name: Name for the GPU model. * @_arch_major: Architecture major. * @_product_major: Product major.
*/ #define GPU_MODEL(_name, _arch_major, _product_major) \
{\
.name = __stringify(_name), \
.arch_major = _arch_major, \
.product_major = _product_major, \
}
arch_major = GPU_ARCH_MAJOR(ptdev->gpu_info.gpu_id);
product_major = GPU_PROD_MAJOR(ptdev->gpu_info.gpu_id);
major = GPU_VER_MAJOR(ptdev->gpu_info.gpu_id);
minor = GPU_VER_MINOR(ptdev->gpu_info.gpu_id);
status = GPU_VER_STATUS(ptdev->gpu_info.gpu_id);
for (model = gpu_models; model->name; model++) { if (model->arch_major == arch_major &&
model->product_major == product_major) break;
}
drm_info(&ptdev->base, "mali-%s id 0x%x major 0x%x minor 0x%x status 0x%x",
model->name ?: "unknown", ptdev->gpu_info.gpu_id >> 16,
major, minor, status);
/** * panthor_gpu_unplug() - Called when the GPU is unplugged. * @ptdev: Device to unplug.
*/ void panthor_gpu_unplug(struct panthor_device *ptdev)
{ unsignedlong flags;
/* Make sure the IRQ handler is not running after that point. */ if (!IS_ENABLED(CONFIG_PM) || pm_runtime_active(ptdev->base.dev))
panthor_gpu_irq_suspend(&ptdev->gpu->irq);
dma_set_max_seg_size(ptdev->base.dev, UINT_MAX);
pa_bits = GPU_MMU_FEATURES_PA_BITS(ptdev->gpu_info.mmu_features);
ret = dma_set_mask_and_coherent(ptdev->base.dev, DMA_BIT_MASK(pa_bits)); if (ret) return ret;
irq = platform_get_irq_byname(to_platform_device(ptdev->base.dev), "gpu"); if (irq < 0) return irq;
ret = panthor_request_gpu_irq(ptdev, &ptdev->gpu->irq, irq, GPU_INTERRUPTS_MASK); if (ret) return ret;
return 0;
}
/** * panthor_gpu_block_power_off() - Power-off a specific block of the GPU * @ptdev: Device. * @blk_name: Block name. * @pwroff_reg: Power-off register for this block. * @pwrtrans_reg: Power transition register for this block. * @mask: Sub-elements to power-off. * @timeout_us: Timeout in microseconds. * * Return: 0 on success, a negative error code otherwise.
*/ int panthor_gpu_block_power_off(struct panthor_device *ptdev, constchar *blk_name,
u32 pwroff_reg, u32 pwrtrans_reg,
u64 mask, u32 timeout_us)
{
u32 val; int ret;
ret = gpu_read64_relaxed_poll_timeout(ptdev, pwrtrans_reg, val,
!(mask & val), 100, timeout_us); if (ret) {
drm_err(&ptdev->base, "timeout waiting on %s:%llx power transition", blk_name,
mask); return ret;
}
gpu_write64(ptdev, pwroff_reg, mask);
ret = gpu_read64_relaxed_poll_timeout(ptdev, pwrtrans_reg, val,
!(mask & val), 100, timeout_us); if (ret) {
drm_err(&ptdev->base, "timeout waiting on %s:%llx power transition", blk_name,
mask); return ret;
}
return 0;
}
/** * panthor_gpu_block_power_on() - Power-on a specific block of the GPU * @ptdev: Device. * @blk_name: Block name. * @pwron_reg: Power-on register for this block. * @pwrtrans_reg: Power transition register for this block. * @rdy_reg: Power transition ready register. * @mask: Sub-elements to power-on. * @timeout_us: Timeout in microseconds. * * Return: 0 on success, a negative error code otherwise.
*/ int panthor_gpu_block_power_on(struct panthor_device *ptdev, constchar *blk_name,
u32 pwron_reg, u32 pwrtrans_reg,
u32 rdy_reg, u64 mask, u32 timeout_us)
{
u32 val; int ret;
ret = gpu_read64_relaxed_poll_timeout(ptdev, pwrtrans_reg, val,
!(mask & val), 100, timeout_us); if (ret) {
drm_err(&ptdev->base, "timeout waiting on %s:%llx power transition", blk_name,
mask); return ret;
}
gpu_write64(ptdev, pwron_reg, mask);
ret = gpu_read64_relaxed_poll_timeout(ptdev, rdy_reg, val,
(mask & val) == val,
100, timeout_us); if (ret) {
drm_err(&ptdev->base, "timeout waiting on %s:%llx readiness",
blk_name, mask); return ret;
}
return 0;
}
/** * panthor_gpu_l2_power_on() - Power-on the L2-cache * @ptdev: Device. * * Return: 0 on success, a negative error code otherwise.
*/ int panthor_gpu_l2_power_on(struct panthor_device *ptdev)
{ if (ptdev->gpu_info.l2_present != 1) { /* * Only support one core group now. * ~(l2_present - 1) unsets all bits in l2_present except * the bottom bit. (l2_present - 2) has all the bits in * the first core group set. AND them together to generate * a mask of cores in the first core group.
*/
u64 core_mask = ~(ptdev->gpu_info.l2_present - 1) &
(ptdev->gpu_info.l2_present - 2);
drm_info_once(&ptdev->base, "using only 1st core group (%lu cores from %lu)\n",
hweight64(core_mask),
hweight64(ptdev->gpu_info.shader_present));
}
/* Set the desired coherency mode before the power up of L2 */
panthor_gpu_coherency_set(ptdev);
if (timedout) {
drm_err(&ptdev->base, "Soft reset timeout"); return -ETIMEDOUT;
}
return 0;
}
/** * panthor_gpu_suspend() - Suspend the GPU block. * @ptdev: Device. * * Suspend the GPU irq. This should be called last in the suspend procedure, * after all other blocks have been suspented.
*/ void panthor_gpu_suspend(struct panthor_device *ptdev)
{ /* On a fast reset, simply power down the L2. */ if (!ptdev->reset.fast)
panthor_gpu_soft_reset(ptdev); else
panthor_gpu_power_off(ptdev, L2, 1, 20000);
panthor_gpu_irq_suspend(&ptdev->gpu->irq);
}
/** * panthor_gpu_resume() - Resume the GPU block. * @ptdev: Device. * * Resume the IRQ handler and power-on the L2-cache. * The FW takes care of powering the other blocks.
*/ void panthor_gpu_resume(struct panthor_device *ptdev)
{
panthor_gpu_irq_resume(&ptdev->gpu->irq, GPU_INTERRUPTS_MASK);
panthor_gpu_l2_power_on(ptdev);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.