To make sure that we don't unintentionally perform any unclocked and/or unpowered R/W operation on GPU registers, before turning off clocks and regulators we must make sure that no GPU, JOB or MMU ISR execution is pending: doing that requires to add a mechanism to synchronize the interrupts on suspend. Add functions panfrost_{gpu,job,mmu}_suspend_irq() which will perform interrupts masking and ISR execution synchronization, and then call those in the panfrost_device_runtime_suspend() handler in the exact sequence of job (may require mmu!) -> mmu -> gpu. As a side note, JOB and MMU suspend_irq functions needed some special treatment: as their interrupt handlers will unmask interrupts, it was necessary to add an `is_suspended` bitmap which is used to address the possible corner case of unintentional IRQ unmasking because of ISR execution after a call to synchronize_irq(). At resume, clear each is_suspended bit in the reset path of JOB/MMU to allow unmasking the interrupts. Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com> Tested-by: Marek Szyprowski <m.szyprowski@samsung.com> Reviewed-by: Steven Price <steven.price@arm.com> Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com> Link: https://patchwork.freedesktop.org/patch/msgid/20231204114215.54575-4-angelogioacchino.delregno@collabora.com
26 lines
921 B
C
26 lines
921 B
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/* Copyright 2018 Marty E. Plummer <hanetzer@startmail.com> */
|
|
/* Copyright 2019 Collabora ltd. */
|
|
|
|
#ifndef __PANFROST_GPU_H__
|
|
#define __PANFROST_GPU_H__
|
|
|
|
struct panfrost_device;
|
|
|
|
int panfrost_gpu_init(struct panfrost_device *pfdev);
|
|
void panfrost_gpu_fini(struct panfrost_device *pfdev);
|
|
|
|
u32 panfrost_gpu_get_latest_flush_id(struct panfrost_device *pfdev);
|
|
|
|
int panfrost_gpu_soft_reset(struct panfrost_device *pfdev);
|
|
void panfrost_gpu_power_on(struct panfrost_device *pfdev);
|
|
void panfrost_gpu_power_off(struct panfrost_device *pfdev);
|
|
void panfrost_gpu_suspend_irq(struct panfrost_device *pfdev);
|
|
|
|
void panfrost_cycle_counter_get(struct panfrost_device *pfdev);
|
|
void panfrost_cycle_counter_put(struct panfrost_device *pfdev);
|
|
unsigned long long panfrost_cycle_counter_read(struct panfrost_device *pfdev);
|
|
|
|
void panfrost_gpu_amlogic_quirk(struct panfrost_device *pfdev);
|
|
|
|
#endif
|