1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Intel Speed Select -- Enumerate and control features for Mailbox Interface
4  * Copyright (c) 2023 Intel Corporation.
5  */
6 #include "isst.h"
7 
8 static int mbox_get_disp_freq_multiplier(void)
9 {
10         return DISP_FREQ_MULTIPLIER;
11 }
12 
13 static int mbox_get_trl_max_levels(void)
14 {
15         return 3;
16 }
17 
18 static char *mbox_get_trl_level_name(int level)
19 {
20         switch (level) {
21         case 0:
22                 return "sse";
23         case 1:
24                 return "avx2";
25         case 2:
26                 return "avx512";
27         default:
28                 return NULL;
29         }
30 }
31 
32 static int mbox_is_punit_valid(struct isst_id *id)
33 {
34 	if (id->cpu < 0)
35 		return 0;
36 
37 	if (id->pkg < 0 || id->die < 0 || id->punit)
38 		return 0;
39 
40 	return 1;
41 }
42 
43 static int mbox_get_config_levels(struct isst_id *id, struct isst_pkg_ctdp *pkg_dev)
44 {
45 	unsigned int resp;
46 	int ret;
47 
48 	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP,
49 				     CONFIG_TDP_GET_LEVELS_INFO, 0, 0, &resp);
50 	if (ret) {
51 		pkg_dev->levels = 0;
52 		pkg_dev->locked = 1;
53 		pkg_dev->current_level = 0;
54 		pkg_dev->version = 0;
55 		pkg_dev->enabled = 0;
56 		return 0;
57 	}
58 
59 	debug_printf("cpu:%d CONFIG_TDP_GET_LEVELS_INFO resp:%x\n", id->cpu, resp);
60 
61 	pkg_dev->version = resp & 0xff;
62 	pkg_dev->levels = (resp >> 8) & 0xff;
63 	pkg_dev->current_level = (resp >> 16) & 0xff;
64 	pkg_dev->locked = !!(resp & BIT(24));
65 	pkg_dev->enabled = !!(resp & BIT(31));
66 
67 	return 0;
68 }
69 
70 static int mbox_get_ctdp_control(struct isst_id *id, int config_index,
71 			  struct isst_pkg_ctdp_level_info *ctdp_level)
72 {
73 	int cp_state, cp_cap;
74 	unsigned int resp;
75 	int ret;
76 
77 	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP,
78 				     CONFIG_TDP_GET_TDP_CONTROL, 0,
79 				     config_index, &resp);
80 	if (ret)
81 		return ret;
82 
83 	ctdp_level->fact_support = resp & BIT(0);
84 	ctdp_level->pbf_support = !!(resp & BIT(1));
85 	ctdp_level->fact_enabled = !!(resp & BIT(16));
86 	ctdp_level->pbf_enabled = !!(resp & BIT(17));
87 
88 	ret = isst_read_pm_config(id, &cp_state, &cp_cap);
89 	if (ret) {
90 		debug_printf("cpu:%d pm_config is not supported\n", id->cpu);
91 	} else {
92 		debug_printf("cpu:%d pm_config SST-CP state:%d cap:%d\n", id->cpu, cp_state, cp_cap);
93 		ctdp_level->sst_cp_support = cp_cap;
94 		ctdp_level->sst_cp_enabled = cp_state;
95 	}
96 
97 	debug_printf(
98 		"cpu:%d CONFIG_TDP_GET_TDP_CONTROL resp:%x fact_support:%d pbf_support: %d fact_enabled:%d pbf_enabled:%d\n",
99 		id->cpu, resp, ctdp_level->fact_support, ctdp_level->pbf_support,
100 		ctdp_level->fact_enabled, ctdp_level->pbf_enabled);
101 
102 	return 0;
103 }
104 
105 static int mbox_get_tdp_info(struct isst_id *id, int config_index,
106 		      struct isst_pkg_ctdp_level_info *ctdp_level)
107 {
108 	unsigned int resp;
109 	int ret;
110 
111 	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_TDP_INFO,
112 				     0, config_index, &resp);
113 	if (ret) {
114 		isst_display_error_info_message(1, "Invalid level, Can't get TDP information at level", 1, config_index);
115 		return ret;
116 	}
117 
118 	ctdp_level->pkg_tdp = resp & GENMASK(14, 0);
119 	ctdp_level->tdp_ratio = (resp & GENMASK(23, 16)) >> 16;
120 
121 	debug_printf(
122 		"cpu:%d ctdp:%d CONFIG_TDP_GET_TDP_INFO resp:%x tdp_ratio:%d pkg_tdp:%d\n",
123 		id->cpu, config_index, resp, ctdp_level->tdp_ratio,
124 		ctdp_level->pkg_tdp);
125 	return 0;
126 }
127 
128 static int mbox_get_pwr_info(struct isst_id *id, int config_index,
129 		      struct isst_pkg_ctdp_level_info *ctdp_level)
130 {
131 	unsigned int resp;
132 	int ret;
133 
134 	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_PWR_INFO,
135 				     0, config_index, &resp);
136 	if (ret)
137 		return ret;
138 
139 	ctdp_level->pkg_max_power = resp & GENMASK(14, 0);
140 	ctdp_level->pkg_min_power = (resp & GENMASK(30, 16)) >> 16;
141 
142 	debug_printf(
143 		"cpu:%d ctdp:%d CONFIG_TDP_GET_PWR_INFO resp:%x pkg_max_power:%d pkg_min_power:%d\n",
144 		id->cpu, config_index, resp, ctdp_level->pkg_max_power,
145 		ctdp_level->pkg_min_power);
146 
147 	return 0;
148 }
149 
150 
151 static struct isst_platform_ops mbox_ops = {
152 	.get_disp_freq_multiplier = mbox_get_disp_freq_multiplier,
153 	.get_trl_max_levels = mbox_get_trl_max_levels,
154 	.get_trl_level_name = mbox_get_trl_level_name,
155 	.is_punit_valid = mbox_is_punit_valid,
156 	.get_config_levels = mbox_get_config_levels,
157 	.get_ctdp_control = mbox_get_ctdp_control,
158 	.get_tdp_info = mbox_get_tdp_info,
159 	.get_pwr_info = mbox_get_pwr_info,
160 };
161 
162 struct isst_platform_ops *mbox_get_platform_ops(void)
163 {
164 	return &mbox_ops;
165 }
166