mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 01:53:29 +02:00
drm/panthor: Introduce panthor_pwr API and power control framework
Add the new panthor_pwr module, which provides basic power control management for Mali-G1 GPUs. The initial implementation includes infrastructure for initializing the PWR_CONTROL block, requesting and handling its IRQ, and checking for PWR_CONTROL support based on GPU architecture. The patch also integrates panthor_pwr with the device lifecycle (init, suspend, resume, and unplug) through the new API functions. It also registers the IRQ handler under the 'gpu' IRQ as the PWR_CONTROL block is located within the GPU_CONTROL block. Reviewed-by: Steven Price <steven.price@arm.com> Signed-off-by: Karunika Choo <karunika.choo@arm.com> Link: https://patch.msgid.link/20251125125548.3282320-4-karunika.choo@arm.com Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
This commit is contained in:
parent
7d334f5c0b
commit
c27787f2b7
|
|
@ -10,6 +10,7 @@ panthor-y := \
|
|||
panthor_heap.o \
|
||||
panthor_hw.o \
|
||||
panthor_mmu.o \
|
||||
panthor_pwr.o \
|
||||
panthor_sched.o
|
||||
|
||||
obj-$(CONFIG_DRM_PANTHOR) += panthor.o
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include "panthor_gpu.h"
|
||||
#include "panthor_hw.h"
|
||||
#include "panthor_mmu.h"
|
||||
#include "panthor_pwr.h"
|
||||
#include "panthor_regs.h"
|
||||
#include "panthor_sched.h"
|
||||
|
||||
|
|
@ -113,6 +114,7 @@ void panthor_device_unplug(struct panthor_device *ptdev)
|
|||
panthor_fw_unplug(ptdev);
|
||||
panthor_mmu_unplug(ptdev);
|
||||
panthor_gpu_unplug(ptdev);
|
||||
panthor_pwr_unplug(ptdev);
|
||||
|
||||
pm_runtime_dont_use_autosuspend(ptdev->base.dev);
|
||||
pm_runtime_put_sync_suspend(ptdev->base.dev);
|
||||
|
|
@ -268,10 +270,14 @@ int panthor_device_init(struct panthor_device *ptdev)
|
|||
if (ret)
|
||||
goto err_rpm_put;
|
||||
|
||||
ret = panthor_gpu_init(ptdev);
|
||||
ret = panthor_pwr_init(ptdev);
|
||||
if (ret)
|
||||
goto err_rpm_put;
|
||||
|
||||
ret = panthor_gpu_init(ptdev);
|
||||
if (ret)
|
||||
goto err_unplug_pwr;
|
||||
|
||||
ret = panthor_gpu_coherency_init(ptdev);
|
||||
if (ret)
|
||||
goto err_unplug_gpu;
|
||||
|
|
@ -312,6 +318,9 @@ int panthor_device_init(struct panthor_device *ptdev)
|
|||
err_unplug_gpu:
|
||||
panthor_gpu_unplug(ptdev);
|
||||
|
||||
err_unplug_pwr:
|
||||
panthor_pwr_unplug(ptdev);
|
||||
|
||||
err_rpm_put:
|
||||
pm_runtime_put_sync_suspend(ptdev->base.dev);
|
||||
return ret;
|
||||
|
|
@ -465,6 +474,7 @@ static int panthor_device_resume_hw_components(struct panthor_device *ptdev)
|
|||
{
|
||||
int ret;
|
||||
|
||||
panthor_pwr_resume(ptdev);
|
||||
panthor_gpu_resume(ptdev);
|
||||
panthor_mmu_resume(ptdev);
|
||||
|
||||
|
|
@ -474,6 +484,7 @@ static int panthor_device_resume_hw_components(struct panthor_device *ptdev)
|
|||
|
||||
panthor_mmu_suspend(ptdev);
|
||||
panthor_gpu_suspend(ptdev);
|
||||
panthor_pwr_suspend(ptdev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -587,6 +598,7 @@ int panthor_device_suspend(struct device *dev)
|
|||
panthor_fw_suspend(ptdev);
|
||||
panthor_mmu_suspend(ptdev);
|
||||
panthor_gpu_suspend(ptdev);
|
||||
panthor_pwr_suspend(ptdev);
|
||||
drm_dev_exit(cookie);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ struct panthor_job;
|
|||
struct panthor_mmu;
|
||||
struct panthor_fw;
|
||||
struct panthor_perfcnt;
|
||||
struct panthor_pwr;
|
||||
struct panthor_vm;
|
||||
struct panthor_vm_pool;
|
||||
|
||||
|
|
@ -138,6 +139,9 @@ struct panthor_device {
|
|||
/** @hw: GPU-specific data. */
|
||||
struct panthor_hw *hw;
|
||||
|
||||
/** @pwr: Power control management data. */
|
||||
struct panthor_pwr *pwr;
|
||||
|
||||
/** @gpu: GPU management data. */
|
||||
struct panthor_gpu *gpu;
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#define __PANTHOR_HW_H__
|
||||
|
||||
#include "panthor_device.h"
|
||||
#include "panthor_regs.h"
|
||||
|
||||
/**
|
||||
* struct panthor_hw_ops - HW operations that are specific to a GPU
|
||||
|
|
@ -47,4 +48,9 @@ static inline void panthor_hw_l2_power_off(struct panthor_device *ptdev)
|
|||
ptdev->hw->ops.l2_power_off(ptdev);
|
||||
}
|
||||
|
||||
static inline bool panthor_hw_has_pwr_ctrl(struct panthor_device *ptdev)
|
||||
{
|
||||
return GPU_ARCH_MAJOR(ptdev->gpu_info.gpu_id) >= 14;
|
||||
}
|
||||
|
||||
#endif /* __PANTHOR_HW_H__ */
|
||||
|
|
|
|||
121
drivers/gpu/drm/panthor/panthor_pwr.c
Normal file
121
drivers/gpu/drm/panthor/panthor_pwr.c
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 or MIT
|
||||
/* Copyright 2025 ARM Limited. All rights reserved. */
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/wait.h>
|
||||
|
||||
#include <drm/drm_managed.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "panthor_device.h"
|
||||
#include "panthor_hw.h"
|
||||
#include "panthor_pwr.h"
|
||||
#include "panthor_regs.h"
|
||||
|
||||
#define PWR_INTERRUPTS_MASK \
|
||||
(PWR_IRQ_POWER_CHANGED_SINGLE | \
|
||||
PWR_IRQ_POWER_CHANGED_ALL | \
|
||||
PWR_IRQ_DELEGATION_CHANGED | \
|
||||
PWR_IRQ_RESET_COMPLETED | \
|
||||
PWR_IRQ_RETRACT_COMPLETED | \
|
||||
PWR_IRQ_INSPECT_COMPLETED | \
|
||||
PWR_IRQ_COMMAND_NOT_ALLOWED | \
|
||||
PWR_IRQ_COMMAND_INVALID)
|
||||
|
||||
/**
|
||||
* struct panthor_pwr - PWR_CONTROL block management data.
|
||||
*/
|
||||
struct panthor_pwr {
|
||||
/** @irq: PWR irq. */
|
||||
struct panthor_irq irq;
|
||||
|
||||
/** @reqs_lock: Lock protecting access to pending_reqs. */
|
||||
spinlock_t reqs_lock;
|
||||
|
||||
/** @pending_reqs: Pending PWR requests. */
|
||||
u32 pending_reqs;
|
||||
|
||||
/** @reqs_acked: PWR request wait queue. */
|
||||
wait_queue_head_t reqs_acked;
|
||||
};
|
||||
|
||||
static void panthor_pwr_irq_handler(struct panthor_device *ptdev, u32 status)
|
||||
{
|
||||
spin_lock(&ptdev->pwr->reqs_lock);
|
||||
gpu_write(ptdev, PWR_INT_CLEAR, status);
|
||||
|
||||
if (unlikely(status & PWR_IRQ_COMMAND_NOT_ALLOWED))
|
||||
drm_err(&ptdev->base, "PWR_IRQ: COMMAND_NOT_ALLOWED");
|
||||
|
||||
if (unlikely(status & PWR_IRQ_COMMAND_INVALID))
|
||||
drm_err(&ptdev->base, "PWR_IRQ: COMMAND_INVALID");
|
||||
|
||||
if (status & ptdev->pwr->pending_reqs) {
|
||||
ptdev->pwr->pending_reqs &= ~status;
|
||||
wake_up_all(&ptdev->pwr->reqs_acked);
|
||||
}
|
||||
spin_unlock(&ptdev->pwr->reqs_lock);
|
||||
}
|
||||
PANTHOR_IRQ_HANDLER(pwr, PWR, panthor_pwr_irq_handler);
|
||||
|
||||
void panthor_pwr_unplug(struct panthor_device *ptdev)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (!ptdev->pwr)
|
||||
return;
|
||||
|
||||
/* Make sure the IRQ handler is not running after that point. */
|
||||
panthor_pwr_irq_suspend(&ptdev->pwr->irq);
|
||||
|
||||
/* Wake-up all waiters. */
|
||||
spin_lock_irqsave(&ptdev->pwr->reqs_lock, flags);
|
||||
ptdev->pwr->pending_reqs = 0;
|
||||
wake_up_all(&ptdev->pwr->reqs_acked);
|
||||
spin_unlock_irqrestore(&ptdev->pwr->reqs_lock, flags);
|
||||
}
|
||||
|
||||
int panthor_pwr_init(struct panthor_device *ptdev)
|
||||
{
|
||||
struct panthor_pwr *pwr;
|
||||
int err, irq;
|
||||
|
||||
if (!panthor_hw_has_pwr_ctrl(ptdev))
|
||||
return 0;
|
||||
|
||||
pwr = drmm_kzalloc(&ptdev->base, sizeof(*pwr), GFP_KERNEL);
|
||||
if (!pwr)
|
||||
return -ENOMEM;
|
||||
|
||||
spin_lock_init(&pwr->reqs_lock);
|
||||
init_waitqueue_head(&pwr->reqs_acked);
|
||||
ptdev->pwr = pwr;
|
||||
|
||||
irq = platform_get_irq_byname(to_platform_device(ptdev->base.dev), "gpu");
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
err = panthor_request_pwr_irq(ptdev, &pwr->irq, irq, PWR_INTERRUPTS_MASK);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void panthor_pwr_suspend(struct panthor_device *ptdev)
|
||||
{
|
||||
if (!ptdev->pwr)
|
||||
return;
|
||||
|
||||
panthor_pwr_irq_suspend(&ptdev->pwr->irq);
|
||||
}
|
||||
|
||||
void panthor_pwr_resume(struct panthor_device *ptdev)
|
||||
{
|
||||
if (!ptdev->pwr)
|
||||
return;
|
||||
|
||||
panthor_pwr_irq_resume(&ptdev->pwr->irq, PWR_INTERRUPTS_MASK);
|
||||
}
|
||||
17
drivers/gpu/drm/panthor/panthor_pwr.h
Normal file
17
drivers/gpu/drm/panthor/panthor_pwr.h
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 or MIT */
|
||||
/* Copyright 2025 ARM Limited. All rights reserved. */
|
||||
|
||||
#ifndef __PANTHOR_PWR_H__
|
||||
#define __PANTHOR_PWR_H__
|
||||
|
||||
struct panthor_device;
|
||||
|
||||
void panthor_pwr_unplug(struct panthor_device *ptdev);
|
||||
|
||||
int panthor_pwr_init(struct panthor_device *ptdev);
|
||||
|
||||
void panthor_pwr_suspend(struct panthor_device *ptdev);
|
||||
|
||||
void panthor_pwr_resume(struct panthor_device *ptdev);
|
||||
|
||||
#endif /* __PANTHOR_PWR_H__ */
|
||||
|
|
@ -209,4 +209,82 @@
|
|||
#define CSF_DOORBELL(i) (0x80000 + ((i) * 0x10000))
|
||||
#define CSF_GLB_DOORBELL_ID 0
|
||||
|
||||
/* PWR Control registers */
|
||||
|
||||
#define PWR_CONTROL_BASE 0x800
|
||||
#define PWR_CTRL_REG(x) (PWR_CONTROL_BASE + (x))
|
||||
|
||||
#define PWR_INT_RAWSTAT PWR_CTRL_REG(0x0)
|
||||
#define PWR_INT_CLEAR PWR_CTRL_REG(0x4)
|
||||
#define PWR_INT_MASK PWR_CTRL_REG(0x8)
|
||||
#define PWR_INT_STAT PWR_CTRL_REG(0xc)
|
||||
#define PWR_IRQ_POWER_CHANGED_SINGLE BIT(0)
|
||||
#define PWR_IRQ_POWER_CHANGED_ALL BIT(1)
|
||||
#define PWR_IRQ_DELEGATION_CHANGED BIT(2)
|
||||
#define PWR_IRQ_RESET_COMPLETED BIT(3)
|
||||
#define PWR_IRQ_RETRACT_COMPLETED BIT(4)
|
||||
#define PWR_IRQ_INSPECT_COMPLETED BIT(5)
|
||||
#define PWR_IRQ_COMMAND_NOT_ALLOWED BIT(30)
|
||||
#define PWR_IRQ_COMMAND_INVALID BIT(31)
|
||||
|
||||
#define PWR_STATUS PWR_CTRL_REG(0x20)
|
||||
#define PWR_STATUS_ALLOW_L2 BIT_U64(0)
|
||||
#define PWR_STATUS_ALLOW_TILER BIT_U64(1)
|
||||
#define PWR_STATUS_ALLOW_SHADER BIT_U64(8)
|
||||
#define PWR_STATUS_ALLOW_BASE BIT_U64(14)
|
||||
#define PWR_STATUS_ALLOW_STACK BIT_U64(15)
|
||||
#define PWR_STATUS_DOMAIN_ALLOWED(x) BIT_U64(x)
|
||||
#define PWR_STATUS_DELEGATED_L2 BIT_U64(16)
|
||||
#define PWR_STATUS_DELEGATED_TILER BIT_U64(17)
|
||||
#define PWR_STATUS_DELEGATED_SHADER BIT_U64(24)
|
||||
#define PWR_STATUS_DELEGATED_BASE BIT_U64(30)
|
||||
#define PWR_STATUS_DELEGATED_STACK BIT_U64(31)
|
||||
#define PWR_STATUS_DELEGATED_SHIFT 16
|
||||
#define PWR_STATUS_DOMAIN_DELEGATED(x) BIT_U64((x) + PWR_STATUS_DELEGATED_SHIFT)
|
||||
#define PWR_STATUS_ALLOW_SOFT_RESET BIT_U64(33)
|
||||
#define PWR_STATUS_ALLOW_FAST_RESET BIT_U64(34)
|
||||
#define PWR_STATUS_POWER_PENDING BIT_U64(41)
|
||||
#define PWR_STATUS_RESET_PENDING BIT_U64(42)
|
||||
#define PWR_STATUS_RETRACT_PENDING BIT_U64(43)
|
||||
#define PWR_STATUS_INSPECT_PENDING BIT_U64(44)
|
||||
|
||||
#define PWR_COMMAND PWR_CTRL_REG(0x28)
|
||||
#define PWR_COMMAND_POWER_UP 0x10
|
||||
#define PWR_COMMAND_POWER_DOWN 0x11
|
||||
#define PWR_COMMAND_DELEGATE 0x20
|
||||
#define PWR_COMMAND_RETRACT 0x21
|
||||
#define PWR_COMMAND_RESET_SOFT 0x31
|
||||
#define PWR_COMMAND_RESET_FAST 0x32
|
||||
#define PWR_COMMAND_INSPECT 0xF0
|
||||
#define PWR_COMMAND_DOMAIN_L2 0
|
||||
#define PWR_COMMAND_DOMAIN_TILER 1
|
||||
#define PWR_COMMAND_DOMAIN_SHADER 8
|
||||
#define PWR_COMMAND_DOMAIN_BASE 14
|
||||
#define PWR_COMMAND_DOMAIN_STACK 15
|
||||
#define PWR_COMMAND_SUBDOMAIN_RTU BIT(0)
|
||||
#define PWR_COMMAND_DEF(cmd, domain, subdomain) \
|
||||
(((subdomain) << 16) | ((domain) << 8) | (cmd))
|
||||
|
||||
#define PWR_CMDARG PWR_CTRL_REG(0x30)
|
||||
|
||||
#define PWR_L2_PRESENT PWR_CTRL_REG(0x100)
|
||||
#define PWR_L2_READY PWR_CTRL_REG(0x108)
|
||||
#define PWR_L2_PWRTRANS PWR_CTRL_REG(0x110)
|
||||
#define PWR_L2_PWRACTIVE PWR_CTRL_REG(0x118)
|
||||
#define PWR_TILER_PRESENT PWR_CTRL_REG(0x140)
|
||||
#define PWR_TILER_READY PWR_CTRL_REG(0x148)
|
||||
#define PWR_TILER_PWRTRANS PWR_CTRL_REG(0x150)
|
||||
#define PWR_TILER_PWRACTIVE PWR_CTRL_REG(0x158)
|
||||
#define PWR_SHADER_PRESENT PWR_CTRL_REG(0x200)
|
||||
#define PWR_SHADER_READY PWR_CTRL_REG(0x208)
|
||||
#define PWR_SHADER_PWRTRANS PWR_CTRL_REG(0x210)
|
||||
#define PWR_SHADER_PWRACTIVE PWR_CTRL_REG(0x218)
|
||||
#define PWR_BASE_PRESENT PWR_CTRL_REG(0x380)
|
||||
#define PWR_BASE_READY PWR_CTRL_REG(0x388)
|
||||
#define PWR_BASE_PWRTRANS PWR_CTRL_REG(0x390)
|
||||
#define PWR_BASE_PWRACTIVE PWR_CTRL_REG(0x398)
|
||||
#define PWR_STACK_PRESENT PWR_CTRL_REG(0x3c0)
|
||||
#define PWR_STACK_READY PWR_CTRL_REG(0x3c8)
|
||||
#define PWR_STACK_PWRTRANS PWR_CTRL_REG(0x3d0)
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user