blob: f48a9d5c45289092aa2cafaee310188dd3b9769f [file] [log] [blame]
Felix Held60a46432020-11-12 00:14:16 +01001/* SPDX-License-Identifier: GPL-2.0-only */
2
3#include <timer.h>
4#include <console/console.h>
Felix Helde9956842021-03-10 22:55:22 +01005#include <amdblocks/smn.h>
Felix Held60a46432020-11-12 00:14:16 +01006#include <amdblocks/smu.h>
Felix Held60a46432020-11-12 00:14:16 +01007#include <soc/smu.h>
8#include <types.h>
9
Felix Held60a46432020-11-12 00:14:16 +010010#define SMU_MESG_RESP_TIMEOUT 0x00
11#define SMU_MESG_RESP_OK 0x01
12
13/* returns SMU_MESG_RESP_OK, SMU_MESG_RESP_TIMEOUT or a negative number */
14static int32_t smu_poll_response(bool print_command_duration)
15{
16 struct stopwatch sw;
17 const long timeout_ms = 10 * MSECS_PER_SEC;
18 int32_t result;
19
20 stopwatch_init_msecs_expire(&sw, timeout_ms);
21
22 do {
Felix Held03a4bfc2021-03-10 23:29:11 +010023 result = smn_read32(SMN_SMU_MESG_RESP);
Felix Held60a46432020-11-12 00:14:16 +010024 if (result) {
25 if (print_command_duration)
26 printk(BIOS_SPEW, "SMU command consumed %ld usecs\n",
27 stopwatch_duration_usecs(&sw));
28 return result;
29 }
30 } while (!stopwatch_expired(&sw));
31
32 printk(BIOS_ERR, "Error: timeout sending SMU message\n");
33 return SMU_MESG_RESP_TIMEOUT;
34}
35
36/*
37 * Send a message and bi-directional payload to the SMU. SMU response, if any, is returned via
38 * *arg.
39 */
40enum cb_err send_smu_message(enum smu_message_id message_id, struct smu_payload *arg)
41{
42 size_t i;
43
44 /* wait until SMU can process a new request; don't care if an old request failed */
45 if (smu_poll_response(false) == SMU_MESG_RESP_TIMEOUT)
46 return CB_ERR;
47
48 /* clear response register */
Felix Held03a4bfc2021-03-10 23:29:11 +010049 smn_write32(SMN_SMU_MESG_RESP, 0);
Felix Held60a46432020-11-12 00:14:16 +010050
51 /* populate arguments */
52 for (i = 0 ; i < SMU_NUM_ARGS ; i++)
Felix Held03a4bfc2021-03-10 23:29:11 +010053 smn_write32(SMN_SMU_MESG_ARG(i), arg->msg[i]);
Felix Held60a46432020-11-12 00:14:16 +010054
55 /* send message to SMU */
Felix Held03a4bfc2021-03-10 23:29:11 +010056 smn_write32(SMN_SMU_MESG_ID, message_id);
Felix Held60a46432020-11-12 00:14:16 +010057
58 /* wait until SMU has processed the message and check if it was successful */
59 if (smu_poll_response(true) != SMU_MESG_RESP_OK)
60 return CB_ERR;
61
62 /* copy returned values */
63 for (i = 0 ; i < SMU_NUM_ARGS ; i++)
Felix Held03a4bfc2021-03-10 23:29:11 +010064 arg->msg[i] = smn_read32(SMN_SMU_MESG_ARG(i));
Felix Held60a46432020-11-12 00:14:16 +010065
66 return CB_SUCCESS;
67}