Skip to content

Commit 6c2b754

Browse files
akacprowjlawryno
authored andcommitted
accel/ivpu: Fix the NPU's DPU frequency calculation
Fix the frequency returned to the user space by the DRM_IVPU_PARAM_CORE_CLOCK_RATE GET_PARAM IOCTL. The kernel driver returned CPU frequency for MTL and bare PLL frequency for LNL - this was inconsistent and incorrect for both platforms. With this fix the driver returns maximum frequency of the NPU data processing unit (DPU) for all HW generations. This is what user space always expected. Also do not set CPU frequency in boot params - the firmware does not use frequency passed from the driver, it was only used by the early pre-production firmware. With that we can remove CPU frequency calculation code. Show NPU frequency in FREQ_CHANGE interrupt when frequency tracking is enabled. Fixes: 8a27ad8 ("accel/ivpu: Split IP and buttress code") Cc: stable@vger.kernel.org # v6.11+ Signed-off-by: Andrzej Kacprowski <Andrzej.Kacprowski@intel.com> Signed-off-by: Maciej Falkowski <maciej.falkowski@linux.intel.com> Reviewed-by: Jeff Hugo <jeff.hugo@oss.qualcomm.com> Signed-off-by: Jacek Lawrynowicz <jacek.lawrynowicz@linux.intel.com> Link: https://lore.kernel.org/r/20250401155912.4049340-2-maciej.falkowski@linux.intel.com
1 parent 082a29e commit 6c2b754

File tree

6 files changed

+66
-88
lines changed

6 files changed

+66
-88
lines changed

drivers/accel/ivpu/ivpu_drv.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// SPDX-License-Identifier: GPL-2.0-only
22
/*
3-
* Copyright (C) 2020-2024 Intel Corporation
3+
* Copyright (C) 2020-2025 Intel Corporation
44
*/
55

66
#include <linux/firmware.h>
@@ -164,7 +164,7 @@ static int ivpu_get_param_ioctl(struct drm_device *dev, void *data, struct drm_f
164164
args->value = vdev->platform;
165165
break;
166166
case DRM_IVPU_PARAM_CORE_CLOCK_RATE:
167-
args->value = ivpu_hw_ratio_to_freq(vdev, vdev->hw->pll.max_ratio);
167+
args->value = ivpu_hw_dpu_max_freq_get(vdev);
168168
break;
169169
case DRM_IVPU_PARAM_NUM_CONTEXTS:
170170
args->value = ivpu_get_context_count(vdev);

drivers/accel/ivpu/ivpu_fw.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// SPDX-License-Identifier: GPL-2.0-only
22
/*
3-
* Copyright (C) 2020-2024 Intel Corporation
3+
* Copyright (C) 2020-2025 Intel Corporation
44
*/
55

66
#include <linux/firmware.h>
@@ -576,7 +576,6 @@ void ivpu_fw_boot_params_setup(struct ivpu_device *vdev, struct vpu_boot_params
576576

577577
boot_params->magic = VPU_BOOT_PARAMS_MAGIC;
578578
boot_params->vpu_id = to_pci_dev(vdev->drm.dev)->bus->number;
579-
boot_params->frequency = ivpu_hw_pll_freq_get(vdev);
580579

581580
/*
582581
* This param is a debug firmware feature. It switches default clock

drivers/accel/ivpu/ivpu_hw.h

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* SPDX-License-Identifier: GPL-2.0-only */
22
/*
3-
* Copyright (C) 2020-2024 Intel Corporation
3+
* Copyright (C) 2020-2025 Intel Corporation
44
*/
55

66
#ifndef __IVPU_HW_H__
@@ -82,21 +82,16 @@ static inline u64 ivpu_hw_range_size(const struct ivpu_addr_range *range)
8282
return range->end - range->start;
8383
}
8484

85-
static inline u32 ivpu_hw_ratio_to_freq(struct ivpu_device *vdev, u32 ratio)
85+
static inline u32 ivpu_hw_dpu_max_freq_get(struct ivpu_device *vdev)
8686
{
87-
return ivpu_hw_btrs_ratio_to_freq(vdev, ratio);
87+
return ivpu_hw_btrs_dpu_max_freq_get(vdev);
8888
}
8989

9090
static inline void ivpu_hw_irq_clear(struct ivpu_device *vdev)
9191
{
9292
ivpu_hw_ip_irq_clear(vdev);
9393
}
9494

95-
static inline u32 ivpu_hw_pll_freq_get(struct ivpu_device *vdev)
96-
{
97-
return ivpu_hw_btrs_pll_freq_get(vdev);
98-
}
99-
10095
static inline u32 ivpu_hw_profiling_freq_get(struct ivpu_device *vdev)
10196
{
10297
return vdev->hw->pll.profiling_freq;

drivers/accel/ivpu/ivpu_hw_btrs.c

Lines changed: 56 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
// SPDX-License-Identifier: GPL-2.0-only
22
/*
3-
* Copyright (C) 2020-2024 Intel Corporation
3+
* Copyright (C) 2020-2025 Intel Corporation
44
*/
55

6+
#include <linux/units.h>
7+
68
#include "ivpu_drv.h"
79
#include "ivpu_hw.h"
810
#include "ivpu_hw_btrs.h"
@@ -28,17 +30,13 @@
2830

2931
#define BTRS_LNL_ALL_IRQ_MASK ((u32)-1)
3032

31-
#define BTRS_MTL_WP_CONFIG_1_TILE_5_3_RATIO WP_CONFIG(MTL_CONFIG_1_TILE, MTL_PLL_RATIO_5_3)
32-
#define BTRS_MTL_WP_CONFIG_1_TILE_4_3_RATIO WP_CONFIG(MTL_CONFIG_1_TILE, MTL_PLL_RATIO_4_3)
33-
#define BTRS_MTL_WP_CONFIG_2_TILE_5_3_RATIO WP_CONFIG(MTL_CONFIG_2_TILE, MTL_PLL_RATIO_5_3)
34-
#define BTRS_MTL_WP_CONFIG_2_TILE_4_3_RATIO WP_CONFIG(MTL_CONFIG_2_TILE, MTL_PLL_RATIO_4_3)
35-
#define BTRS_MTL_WP_CONFIG_0_TILE_PLL_OFF WP_CONFIG(0, 0)
3633

3734
#define PLL_CDYN_DEFAULT 0x80
3835
#define PLL_EPP_DEFAULT 0x80
3936
#define PLL_CONFIG_DEFAULT 0x0
40-
#define PLL_SIMULATION_FREQ 10000000
41-
#define PLL_REF_CLK_FREQ 50000000
37+
#define PLL_REF_CLK_FREQ 50000000ull
38+
#define PLL_RATIO_TO_FREQ(x) ((x) * PLL_REF_CLK_FREQ)
39+
4240
#define PLL_TIMEOUT_US (1500 * USEC_PER_MSEC)
4341
#define IDLE_TIMEOUT_US (5 * USEC_PER_MSEC)
4442
#define TIMEOUT_US (150 * USEC_PER_MSEC)
@@ -62,6 +60,8 @@
6260
#define DCT_ENABLE 0x1
6361
#define DCT_DISABLE 0x0
6462

63+
static u32 pll_ratio_to_dpu_freq(struct ivpu_device *vdev, u32 ratio);
64+
6565
int ivpu_hw_btrs_irqs_clear_with_0_mtl(struct ivpu_device *vdev)
6666
{
6767
REGB_WR32(VPU_HW_BTRS_MTL_INTERRUPT_STAT, BTRS_MTL_ALL_IRQ_MASK);
@@ -156,7 +156,7 @@ static int info_init_mtl(struct ivpu_device *vdev)
156156

157157
hw->tile_fuse = BTRS_MTL_TILE_FUSE_ENABLE_BOTH;
158158
hw->sku = BTRS_MTL_TILE_SKU_BOTH;
159-
hw->config = BTRS_MTL_WP_CONFIG_2_TILE_4_3_RATIO;
159+
hw->config = WP_CONFIG(MTL_CONFIG_2_TILE, MTL_PLL_RATIO_4_3);
160160

161161
return 0;
162162
}
@@ -334,8 +334,8 @@ int ivpu_hw_btrs_wp_drive(struct ivpu_device *vdev, bool enable)
334334

335335
prepare_wp_request(vdev, &wp, enable);
336336

337-
ivpu_dbg(vdev, PM, "PLL workpoint request: %u Hz, config: 0x%x, epp: 0x%x, cdyn: 0x%x\n",
338-
PLL_RATIO_TO_FREQ(wp.target), wp.cfg, wp.epp, wp.cdyn);
337+
ivpu_dbg(vdev, PM, "PLL workpoint request: %lu MHz, config: 0x%x, epp: 0x%x, cdyn: 0x%x\n",
338+
pll_ratio_to_dpu_freq(vdev, wp.target) / HZ_PER_MHZ, wp.cfg, wp.epp, wp.cdyn);
339339

340340
ret = wp_request_send(vdev, &wp);
341341
if (ret) {
@@ -573,6 +573,39 @@ int ivpu_hw_btrs_wait_for_idle(struct ivpu_device *vdev)
573573
return REGB_POLL_FLD(VPU_HW_BTRS_LNL_VPU_STATUS, IDLE, 0x1, IDLE_TIMEOUT_US);
574574
}
575575

576+
static u32 pll_config_get_mtl(struct ivpu_device *vdev)
577+
{
578+
return REGB_RD32(VPU_HW_BTRS_MTL_CURRENT_PLL);
579+
}
580+
581+
static u32 pll_config_get_lnl(struct ivpu_device *vdev)
582+
{
583+
return REGB_RD32(VPU_HW_BTRS_LNL_PLL_FREQ);
584+
}
585+
586+
static u32 pll_ratio_to_dpu_freq_mtl(u16 ratio)
587+
{
588+
return (PLL_RATIO_TO_FREQ(ratio) * 2) / 3;
589+
}
590+
591+
static u32 pll_ratio_to_dpu_freq_lnl(u16 ratio)
592+
{
593+
return PLL_RATIO_TO_FREQ(ratio) / 2;
594+
}
595+
596+
static u32 pll_ratio_to_dpu_freq(struct ivpu_device *vdev, u32 ratio)
597+
{
598+
if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
599+
return pll_ratio_to_dpu_freq_mtl(ratio);
600+
else
601+
return pll_ratio_to_dpu_freq_lnl(ratio);
602+
}
603+
604+
u32 ivpu_hw_btrs_dpu_max_freq_get(struct ivpu_device *vdev)
605+
{
606+
return pll_ratio_to_dpu_freq(vdev, vdev->hw->pll.max_ratio);
607+
}
608+
576609
/* Handler for IRQs from Buttress core (irqB) */
577610
bool ivpu_hw_btrs_irq_handler_mtl(struct ivpu_device *vdev, int irq)
578611
{
@@ -582,9 +615,12 @@ bool ivpu_hw_btrs_irq_handler_mtl(struct ivpu_device *vdev, int irq)
582615
if (!status)
583616
return false;
584617

585-
if (REG_TEST_FLD(VPU_HW_BTRS_MTL_INTERRUPT_STAT, FREQ_CHANGE, status))
586-
ivpu_dbg(vdev, IRQ, "FREQ_CHANGE irq: %08x",
587-
REGB_RD32(VPU_HW_BTRS_MTL_CURRENT_PLL));
618+
if (REG_TEST_FLD(VPU_HW_BTRS_MTL_INTERRUPT_STAT, FREQ_CHANGE, status)) {
619+
u32 pll = pll_config_get_mtl(vdev);
620+
621+
ivpu_dbg(vdev, IRQ, "FREQ_CHANGE irq, wp %08x, %lu MHz",
622+
pll, pll_ratio_to_dpu_freq_mtl(pll) / HZ_PER_MHZ);
623+
}
588624

589625
if (REG_TEST_FLD(VPU_HW_BTRS_MTL_INTERRUPT_STAT, ATS_ERR, status)) {
590626
ivpu_err(vdev, "ATS_ERR irq 0x%016llx", REGB_RD64(VPU_HW_BTRS_MTL_ATS_ERR_LOG_0));
@@ -633,8 +669,12 @@ bool ivpu_hw_btrs_irq_handler_lnl(struct ivpu_device *vdev, int irq)
633669
queue_work(system_wq, &vdev->irq_dct_work);
634670
}
635671

636-
if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, FREQ_CHANGE, status))
637-
ivpu_dbg(vdev, IRQ, "FREQ_CHANGE irq: %08x", REGB_RD32(VPU_HW_BTRS_LNL_PLL_FREQ));
672+
if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, FREQ_CHANGE, status)) {
673+
u32 pll = pll_config_get_lnl(vdev);
674+
675+
ivpu_dbg(vdev, IRQ, "FREQ_CHANGE irq, wp %08x, %lu MHz",
676+
pll, pll_ratio_to_dpu_freq_lnl(pll) / HZ_PER_MHZ);
677+
}
638678

639679
if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, ATS_ERR, status)) {
640680
ivpu_err(vdev, "ATS_ERR LOG1 0x%08x ATS_ERR_LOG2 0x%08x\n",
@@ -717,60 +757,6 @@ void ivpu_hw_btrs_dct_set_status(struct ivpu_device *vdev, bool enable, u32 acti
717757
REGB_WR32(VPU_HW_BTRS_LNL_PCODE_MAILBOX_STATUS, val);
718758
}
719759

720-
static u32 pll_ratio_to_freq_mtl(u32 ratio, u32 config)
721-
{
722-
u32 pll_clock = PLL_REF_CLK_FREQ * ratio;
723-
u32 cpu_clock;
724-
725-
if ((config & 0xff) == MTL_PLL_RATIO_4_3)
726-
cpu_clock = pll_clock * 2 / 4;
727-
else
728-
cpu_clock = pll_clock * 2 / 5;
729-
730-
return cpu_clock;
731-
}
732-
733-
u32 ivpu_hw_btrs_ratio_to_freq(struct ivpu_device *vdev, u32 ratio)
734-
{
735-
struct ivpu_hw_info *hw = vdev->hw;
736-
737-
if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
738-
return pll_ratio_to_freq_mtl(ratio, hw->config);
739-
else
740-
return PLL_RATIO_TO_FREQ(ratio);
741-
}
742-
743-
static u32 pll_freq_get_mtl(struct ivpu_device *vdev)
744-
{
745-
u32 pll_curr_ratio;
746-
747-
pll_curr_ratio = REGB_RD32(VPU_HW_BTRS_MTL_CURRENT_PLL);
748-
pll_curr_ratio &= VPU_HW_BTRS_MTL_CURRENT_PLL_RATIO_MASK;
749-
750-
if (!ivpu_is_silicon(vdev))
751-
return PLL_SIMULATION_FREQ;
752-
753-
return pll_ratio_to_freq_mtl(pll_curr_ratio, vdev->hw->config);
754-
}
755-
756-
static u32 pll_freq_get_lnl(struct ivpu_device *vdev)
757-
{
758-
u32 pll_curr_ratio;
759-
760-
pll_curr_ratio = REGB_RD32(VPU_HW_BTRS_LNL_PLL_FREQ);
761-
pll_curr_ratio &= VPU_HW_BTRS_LNL_PLL_FREQ_RATIO_MASK;
762-
763-
return PLL_RATIO_TO_FREQ(pll_curr_ratio);
764-
}
765-
766-
u32 ivpu_hw_btrs_pll_freq_get(struct ivpu_device *vdev)
767-
{
768-
if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
769-
return pll_freq_get_mtl(vdev);
770-
else
771-
return pll_freq_get_lnl(vdev);
772-
}
773-
774760
u32 ivpu_hw_btrs_telemetry_offset_get(struct ivpu_device *vdev)
775761
{
776762
if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)

drivers/accel/ivpu/ivpu_hw_btrs.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* SPDX-License-Identifier: GPL-2.0-only */
22
/*
3-
* Copyright (C) 2020-2024 Intel Corporation
3+
* Copyright (C) 2020-2025 Intel Corporation
44
*/
55

66
#ifndef __IVPU_HW_BTRS_H__
@@ -13,7 +13,6 @@
1313

1414
#define PLL_PROFILING_FREQ_DEFAULT 38400000
1515
#define PLL_PROFILING_FREQ_HIGH 400000000
16-
#define PLL_RATIO_TO_FREQ(x) ((x) * PLL_REF_CLK_FREQ)
1716

1817
#define DCT_DEFAULT_ACTIVE_PERCENT 15u
1918
#define DCT_PERIOD_US 35300u
@@ -32,12 +31,11 @@ int ivpu_hw_btrs_ip_reset(struct ivpu_device *vdev);
3231
void ivpu_hw_btrs_profiling_freq_reg_set_lnl(struct ivpu_device *vdev);
3332
void ivpu_hw_btrs_ats_print_lnl(struct ivpu_device *vdev);
3433
void ivpu_hw_btrs_clock_relinquish_disable_lnl(struct ivpu_device *vdev);
34+
u32 ivpu_hw_btrs_dpu_max_freq_get(struct ivpu_device *vdev);
3535
bool ivpu_hw_btrs_irq_handler_mtl(struct ivpu_device *vdev, int irq);
3636
bool ivpu_hw_btrs_irq_handler_lnl(struct ivpu_device *vdev, int irq);
3737
int ivpu_hw_btrs_dct_get_request(struct ivpu_device *vdev, bool *enable);
3838
void ivpu_hw_btrs_dct_set_status(struct ivpu_device *vdev, bool enable, u32 dct_percent);
39-
u32 ivpu_hw_btrs_pll_freq_get(struct ivpu_device *vdev);
40-
u32 ivpu_hw_btrs_ratio_to_freq(struct ivpu_device *vdev, u32 ratio);
4139
u32 ivpu_hw_btrs_telemetry_offset_get(struct ivpu_device *vdev);
4240
u32 ivpu_hw_btrs_telemetry_size_get(struct ivpu_device *vdev);
4341
u32 ivpu_hw_btrs_telemetry_enable_get(struct ivpu_device *vdev);

include/uapi/drm/ivpu_accel.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
22
/*
3-
* Copyright (C) 2020-2024 Intel Corporation
3+
* Copyright (C) 2020-2025 Intel Corporation
44
*/
55

66
#ifndef __UAPI_IVPU_DRM_H__
@@ -147,7 +147,7 @@ struct drm_ivpu_param {
147147
* platform type when executing on a simulator or emulator (read-only)
148148
*
149149
* %DRM_IVPU_PARAM_CORE_CLOCK_RATE:
150-
* Current PLL frequency (read-only)
150+
* Maximum frequency of the NPU data processing unit clock (read-only)
151151
*
152152
* %DRM_IVPU_PARAM_NUM_CONTEXTS:
153153
* Maximum number of simultaneously existing contexts (read-only)

0 commit comments

Comments
 (0)