summaryrefslogtreecommitdiff
path: root/driver/amd_stt.c
blob: a80220033cb25cf68a328654a5e87080968e6fa7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/* Copyright 2021 The ChromiumOS Authors
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "amd_stt.h"
#include "chipset.h"
#include "common.h"
#include "console.h"
#include "driver/sb_rmi.h"
#include "hooks.h"
#include "math_util.h"
#include "temp_sensor.h"
#include "util.h"

/* Debug flag can be toggled with console command: stt debug */
static bool amd_stt_debug;

/* Console output macros */
#define CPUTS(outstr) cputs(CC_THERMAL, outstr)
#define CPRINTS(format, args...) cprints(CC_THERMAL, format, ##args)

static const char *const amd_stt_sensor_name[] = {
	[AMD_STT_PCB_SENSOR_APU] = "APU",
	[AMD_STT_PCB_SENSOR_REMOTE] = "Ambient",
	[AMD_STT_PCB_SENSOR_GPU] = "GPU",
};

/**
 * Write temperature sensor value to AP via SB-RMI
 *
 * sensor:
 *	AMD_STT_PCB_SENSOR_APU
 *	AMD_STT_PCB_SENSOR_REMOTE
 *	AMD_STT_PCB_SENSOR_GPU
 *
 * temp_mk:
 *	Temperature in degrees milli kelvin
 */
static int write_stt_sensor_val(enum amd_stt_pcb_sensor sensor, int temp_mk)
{
	uint32_t msgIn = 0;
	uint32_t msgOut;
	int temp_mc;
	int temp_c_fp_msb;
	int temp_c_fp_lsb;

	temp_mc = MILLI_KELVIN_TO_MILLI_CELSIUS(temp_mk);

	if (amd_stt_debug)
		CPRINTS("STT: %s = %d.%d °C", amd_stt_sensor_name[sensor],
			temp_mc / 1000, temp_mc % 1000);

	/* Divide by 1000 to get MSB of fixed point temp */
	temp_c_fp_msb = temp_mc / 1000;
	/* Modulus 1000 and multiply by 256/1000 to get LSB of fixed point*/
	temp_c_fp_lsb = ((temp_mc % 1000) << 8) / 1000;

	/*
	 * [15:0]: temperature as signed integer with 8 fractional bits.
	 * [23:16]: sensor index
	 * [31:24]: unused
	 */
	msgIn |= (temp_c_fp_lsb & 0xff);
	msgIn |= (temp_c_fp_msb & 0xff) << 8;
	msgIn |= (sensor & 0xff) << 16;
	return sb_rmi_mailbox_xfer(SB_RMI_WRITE_STT_SENSOR_CMD, msgIn, &msgOut);
}

static void amd_stt_handler(void)
{
	int rv;
	int soc_temp_mk;
	int ambient_temp_mk;

	/* STT interface is only active in S0 */
	if (!chipset_in_state(CHIPSET_STATE_ON))
		return;

	/*
	 * TODO(b/192391025): Replace with temp_sensor_read_mk(TEMP_SENSOR_SOC)
	 */
	rv = board_get_soc_temp_mk(&soc_temp_mk);
	if (rv) {
		CPRINTS("STT: Failed to read SOC temp rv:%d", rv);
		return;
	}

	rv = write_stt_sensor_val(AMD_STT_PCB_SENSOR_APU, soc_temp_mk);
	if (rv) {
		CPRINTS("STT: Failed to write SOC temp rv:%d", rv);
		return;
	}

	/*
	 * TODO(b/192391025): Replace with
	 *	temp_sensor_read_mk(TEMP_SENSOR_AMBIENT)
	 */
	rv = board_get_ambient_temp_mk(&ambient_temp_mk);
	if (rv) {
		CPRINTS("STT: Failed to read AMBIENT temp rv:%d", rv);
		return;
	}

	rv = write_stt_sensor_val(AMD_STT_PCB_SENSOR_REMOTE, ambient_temp_mk);
	if (rv) {
		CPRINTS("STT: Failed to write AMBIENT temp rv:%d", rv);
		return;
	}
}
DECLARE_HOOK(HOOK_SECOND, amd_stt_handler, HOOK_PRIO_TEMP_SENSOR + 1);

static int command_stt(int argc, const char **argv)
{
	int sensor_id;
	int temp;

	if (argc < 2)
		return EC_ERROR_PARAM1;
	else if (!strcasecmp(argv[1], "debug")) {
		amd_stt_debug = !amd_stt_debug;
		return EC_SUCCESS;
	} else if (argc != 3)
		return EC_ERROR_PARAM2;
	else if (!strcasecmp(argv[1],
			     amd_stt_sensor_name[AMD_STT_PCB_SENSOR_APU]))
		sensor_id = AMD_STT_PCB_SENSOR_APU;
	else if (!strcasecmp(argv[1],
			     amd_stt_sensor_name[AMD_STT_PCB_SENSOR_REMOTE]))
		sensor_id = AMD_STT_PCB_SENSOR_REMOTE;
	else if (!strcasecmp(argv[1],
			     amd_stt_sensor_name[AMD_STT_PCB_SENSOR_GPU]))
		sensor_id = AMD_STT_PCB_SENSOR_GPU;
	else
		return EC_ERROR_PARAM2;

	temp = atoi(argv[2]);

	return write_stt_sensor_val(sensor_id, temp);
}
DECLARE_CONSOLE_COMMAND(stt, command_stt,
			"<apu|ambient|gpu|debug> <temp in mK>",
			"Write an STT mK temperature to AP");