File Index
Files and directories
Sign in
FILE

aie2_smu.c

File preview with syntax highlighting.

linux-6.19.14/drivers/accel/amdxdna/aie2_smu.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Copyright (C) 2022-2024, Advanced Micro Devices, Inc.
  4 */
  5
  6#include <drm/drm_device.h>
  7#include <drm/drm_gem_shmem_helper.h>
  8#include <drm/drm_print.h>
  9#include <drm/gpu_scheduler.h>
 10#include <linux/iopoll.h>
 11
 12#include "aie2_pci.h"
 13#include "amdxdna_pci_drv.h"
 14
 15#define SMU_RESULT_OK		1
 16
 17/* SMU commands */
 18#define AIE2_SMU_POWER_ON		0x3
 19#define AIE2_SMU_POWER_OFF		0x4
 20#define AIE2_SMU_SET_MPNPUCLK_FREQ	0x5
 21#define AIE2_SMU_SET_HCLK_FREQ		0x6
 22#define AIE2_SMU_SET_SOFT_DPMLEVEL	0x7
 23#define AIE2_SMU_SET_HARD_DPMLEVEL	0x8
 24
 25#define NPU4_DPM_TOPS(ndev, dpm_level) \
 26({ \
 27	typeof(ndev) _ndev = ndev; \
 28	(4096 * (_ndev)->total_col * \
 29	 (_ndev)->priv->dpm_clk_tbl[dpm_level].hclk / 1000000); \
 30})
 31
 32static int aie2_smu_exec(struct amdxdna_dev_hdl *ndev, u32 reg_cmd,
 33			 u32 reg_arg, u32 *out)
 34{
 35	u32 resp;
 36	int ret;
 37
 38	writel(0, SMU_REG(ndev, SMU_RESP_REG));
 39	writel(reg_arg, SMU_REG(ndev, SMU_ARG_REG));
 40	writel(reg_cmd, SMU_REG(ndev, SMU_CMD_REG));
 41
 42	/* Clear and set SMU_INTR_REG to kick off */
 43	writel(0, SMU_REG(ndev, SMU_INTR_REG));
 44	writel(1, SMU_REG(ndev, SMU_INTR_REG));
 45
 46	ret = readx_poll_timeout(readl, SMU_REG(ndev, SMU_RESP_REG), resp,
 47				 resp, AIE2_INTERVAL, AIE2_TIMEOUT);
 48	if (ret) {
 49		XDNA_ERR(ndev->xdna, "smu cmd %d timed out", reg_cmd);
 50		return ret;
 51	}
 52
 53	if (out)
 54		*out = readl(SMU_REG(ndev, SMU_OUT_REG));
 55
 56	if (resp != SMU_RESULT_OK) {
 57		XDNA_ERR(ndev->xdna, "smu cmd %d failed, 0x%x", reg_cmd, resp);
 58		return -EINVAL;
 59	}
 60
 61	return 0;
 62}
 63
 64int npu1_set_dpm(struct amdxdna_dev_hdl *ndev, u32 dpm_level)
 65{
 66	u32 freq;
 67	int ret;
 68
 69	ret = aie2_smu_exec(ndev, AIE2_SMU_SET_MPNPUCLK_FREQ,
 70			    ndev->priv->dpm_clk_tbl[dpm_level].npuclk, &freq);
 71	if (ret) {
 72		XDNA_ERR(ndev->xdna, "Set npu clock to %d failed, ret %d\n",
 73			 ndev->priv->dpm_clk_tbl[dpm_level].npuclk, ret);
 74		return ret;
 75	}
 76	ndev->npuclk_freq = freq;
 77
 78	ret = aie2_smu_exec(ndev, AIE2_SMU_SET_HCLK_FREQ,
 79			    ndev->priv->dpm_clk_tbl[dpm_level].hclk, &freq);
 80	if (ret) {
 81		XDNA_ERR(ndev->xdna, "Set h clock to %d failed, ret %d\n",
 82			 ndev->priv->dpm_clk_tbl[dpm_level].hclk, ret);
 83		return ret;
 84	}
 85
 86	ndev->hclk_freq = freq;
 87	ndev->max_tops = 2 * ndev->total_col;
 88	ndev->curr_tops = ndev->max_tops * freq / 1028;
 89
 90	XDNA_DBG(ndev->xdna, "MP-NPU clock %d, H clock %d\n",
 91		 ndev->npuclk_freq, ndev->hclk_freq);
 92
 93	return 0;
 94}
 95
 96int npu4_set_dpm(struct amdxdna_dev_hdl *ndev, u32 dpm_level)
 97{
 98	int ret;
 99
100	ret = aie2_smu_exec(ndev, AIE2_SMU_SET_HARD_DPMLEVEL, dpm_level, NULL);
101	if (ret) {
102		XDNA_ERR(ndev->xdna, "Set hard dpm level %d failed, ret %d ",
103			 dpm_level, ret);
104		return ret;
105	}
106
107	ret = aie2_smu_exec(ndev, AIE2_SMU_SET_SOFT_DPMLEVEL, dpm_level, NULL);
108	if (ret) {
109		XDNA_ERR(ndev->xdna, "Set soft dpm level %d failed, ret %d",
110			 dpm_level, ret);
111		return ret;
112	}
113
114	ndev->npuclk_freq = ndev->priv->dpm_clk_tbl[dpm_level].npuclk;
115	ndev->hclk_freq = ndev->priv->dpm_clk_tbl[dpm_level].hclk;
116	ndev->max_tops = NPU4_DPM_TOPS(ndev, ndev->max_dpm_level);
117	ndev->curr_tops = NPU4_DPM_TOPS(ndev, dpm_level);
118
119	XDNA_DBG(ndev->xdna, "MP-NPU clock %d, H clock %d\n",
120		 ndev->npuclk_freq, ndev->hclk_freq);
121
122	return 0;
123}
124
125int aie2_smu_init(struct amdxdna_dev_hdl *ndev)
126{
127	int ret;
128
129	/*
130	 * Failing to set power off indicates an unrecoverable hardware or
131	 * firmware error.
132	 */
133	ret = aie2_smu_exec(ndev, AIE2_SMU_POWER_OFF, 0, NULL);
134	if (ret) {
135		XDNA_ERR(ndev->xdna, "Access power failed, ret %d", ret);
136		return ret;
137	}
138
139	ret = aie2_smu_exec(ndev, AIE2_SMU_POWER_ON, 0, NULL);
140	if (ret) {
141		XDNA_ERR(ndev->xdna, "Power on failed, ret %d", ret);
142		return ret;
143	}
144
145	return 0;
146}
147
148void aie2_smu_fini(struct amdxdna_dev_hdl *ndev)
149{
150	int ret;
151
152	ndev->priv->hw_ops.set_dpm(ndev, 0);
153	ret = aie2_smu_exec(ndev, AIE2_SMU_POWER_OFF, 0, NULL);
154	if (ret)
155		XDNA_ERR(ndev->xdna, "Power off failed, ret %d", ret);
156}
~/ Read-only file preview.