1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * AMD HSMP Platform Driver
4 * Copyright (c) 2024, AMD.
5 * All Rights Reserved.
6 *
7 * This file provides platform device implementations.
8 */
9
10 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
11
12 #include <asm/amd/hsmp.h>
13
14 #include <linux/acpi.h>
15 #include <linux/build_bug.h>
16 #include <linux/device.h>
17 #include <linux/dev_printk.h>
18 #include <linux/kconfig.h>
19 #include <linux/module.h>
20 #include <linux/pci.h>
21 #include <linux/platform_device.h>
22 #include <linux/sysfs.h>
23
24 #include <asm/amd/node.h>
25
26 #include "hsmp.h"
27
28 #define DRIVER_NAME "amd_hsmp"
29
30 /*
31 * To access specific HSMP mailbox register, s/w writes the SMN address of HSMP mailbox
32 * register into the SMN_INDEX register, and reads/writes the SMN_DATA reg.
33 * Below are required SMN address for HSMP Mailbox register offsets in SMU address space
34 */
35 #define SMN_HSMP_BASE 0x3B00000
36 #define SMN_HSMP_MSG_ID 0x0010534
37 #define SMN_HSMP_MSG_ID_F1A_M0H 0x0010934
38 #define SMN_HSMP_MSG_RESP 0x0010980
39 #define SMN_HSMP_MSG_DATA 0x00109E0
40
41 static struct hsmp_plat_device *hsmp_pdev;
42
amd_hsmp_pci_rdwr(struct hsmp_socket * sock,u32 offset,u32 * value,bool write)43 static int amd_hsmp_pci_rdwr(struct hsmp_socket *sock, u32 offset,
44 u32 *value, bool write)
45 {
46 return amd_smn_hsmp_rdwr(sock->sock_ind, sock->mbinfo.base_addr + offset, value, write);
47 }
48
hsmp_metric_tbl_plat_read(struct file * filp,struct kobject * kobj,const struct bin_attribute * bin_attr,char * buf,loff_t off,size_t count)49 static ssize_t hsmp_metric_tbl_plat_read(struct file *filp, struct kobject *kobj,
50 const struct bin_attribute *bin_attr, char *buf,
51 loff_t off, size_t count)
52 {
53 struct hsmp_socket *sock;
54 u16 sock_ind;
55
56 sock_ind = (uintptr_t)bin_attr->private;
57 if (sock_ind >= hsmp_pdev->num_sockets)
58 return -EINVAL;
59
60 sock = &hsmp_pdev->sock[sock_ind];
61
62 return hsmp_metric_tbl_read(sock, buf, count);
63 }
64
hsmp_is_sock_attr_visible(struct kobject * kobj,const struct bin_attribute * battr,int id)65 static umode_t hsmp_is_sock_attr_visible(struct kobject *kobj,
66 const struct bin_attribute *battr, int id)
67 {
68 u16 sock_ind;
69
70 sock_ind = (uintptr_t)battr->private;
71
72 if (id == 0 && sock_ind >= hsmp_pdev->num_sockets)
73 return SYSFS_GROUP_INVISIBLE;
74
75 if (hsmp_pdev->proto_ver == HSMP_PROTO_VER6)
76 return battr->attr.mode;
77
78 return 0;
79 }
80
81 /*
82 * AMD supports maximum of 8 sockets in a system.
83 * Static array of 8 + 1(for NULL) elements is created below
84 * to create sysfs groups for sockets.
85 * is_bin_visible function is used to show / hide the necessary groups.
86 *
87 * Validate the maximum number against MAX_AMD_NUM_NODES. If this changes,
88 * then the attributes and groups below must be adjusted.
89 */
90 static_assert(MAX_AMD_NUM_NODES == 8);
91
92 #define HSMP_BIN_ATTR(index, _list) \
93 static const struct bin_attribute attr##index = { \
94 .attr = { .name = HSMP_METRICS_TABLE_NAME, .mode = 0444}, \
95 .private = (void *)index, \
96 .read = hsmp_metric_tbl_plat_read, \
97 .size = sizeof(struct hsmp_metric_table), \
98 }; \
99 static const struct bin_attribute _list[] = { \
100 &attr##index, \
101 NULL \
102 }
103
104 HSMP_BIN_ATTR(0, *sock0_attr_list);
105 HSMP_BIN_ATTR(1, *sock1_attr_list);
106 HSMP_BIN_ATTR(2, *sock2_attr_list);
107 HSMP_BIN_ATTR(3, *sock3_attr_list);
108 HSMP_BIN_ATTR(4, *sock4_attr_list);
109 HSMP_BIN_ATTR(5, *sock5_attr_list);
110 HSMP_BIN_ATTR(6, *sock6_attr_list);
111 HSMP_BIN_ATTR(7, *sock7_attr_list);
112
113 #define HSMP_BIN_ATTR_GRP(index, _list, _name) \
114 static const struct attribute_group sock##index##_attr_grp = { \
115 .bin_attrs = _list, \
116 .is_bin_visible = hsmp_is_sock_attr_visible, \
117 .name = #_name, \
118 }
119
120 HSMP_BIN_ATTR_GRP(0, sock0_attr_list, socket0);
121 HSMP_BIN_ATTR_GRP(1, sock1_attr_list, socket1);
122 HSMP_BIN_ATTR_GRP(2, sock2_attr_list, socket2);
123 HSMP_BIN_ATTR_GRP(3, sock3_attr_list, socket3);
124 HSMP_BIN_ATTR_GRP(4, sock4_attr_list, socket4);
125 HSMP_BIN_ATTR_GRP(5, sock5_attr_list, socket5);
126 HSMP_BIN_ATTR_GRP(6, sock6_attr_list, socket6);
127 HSMP_BIN_ATTR_GRP(7, sock7_attr_list, socket7);
128
129 static const struct attribute_group *hsmp_groups[] = {
130 &sock0_attr_grp,
131 &sock1_attr_grp,
132 &sock2_attr_grp,
133 &sock3_attr_grp,
134 &sock4_attr_grp,
135 &sock5_attr_grp,
136 &sock6_attr_grp,
137 &sock7_attr_grp,
138 NULL
139 };
140
is_f1a_m0h(void)141 static inline bool is_f1a_m0h(void)
142 {
143 if (boot_cpu_data.x86 == 0x1A && boot_cpu_data.x86_model <= 0x0F)
144 return true;
145
146 return false;
147 }
148
init_platform_device(struct device * dev)149 static int init_platform_device(struct device *dev)
150 {
151 struct hsmp_socket *sock;
152 int ret, i;
153
154 for (i = 0; i < hsmp_pdev->num_sockets; i++) {
155 sock = &hsmp_pdev->sock[i];
156 sock->sock_ind = i;
157 sock->dev = dev;
158 sock->mbinfo.base_addr = SMN_HSMP_BASE;
159 sock->amd_hsmp_rdwr = amd_hsmp_pci_rdwr;
160
161 /*
162 * This is a transitional change from non-ACPI to ACPI, only
163 * family 0x1A, model 0x00 platform is supported for both ACPI and non-ACPI.
164 */
165 if (is_f1a_m0h())
166 sock->mbinfo.msg_id_off = SMN_HSMP_MSG_ID_F1A_M0H;
167 else
168 sock->mbinfo.msg_id_off = SMN_HSMP_MSG_ID;
169
170 sock->mbinfo.msg_resp_off = SMN_HSMP_MSG_RESP;
171 sock->mbinfo.msg_arg_off = SMN_HSMP_MSG_DATA;
172 sema_init(&sock->hsmp_sem, 1);
173
174 /* Test the hsmp interface on each socket */
175 ret = hsmp_test(i, 0xDEADBEEF);
176 if (ret) {
177 dev_err(dev, "HSMP test message failed on Fam:%x model:%x\n",
178 boot_cpu_data.x86, boot_cpu_data.x86_model);
179 dev_err(dev, "Is HSMP disabled in BIOS ?\n");
180 return ret;
181 }
182
183 ret = hsmp_cache_proto_ver(i);
184 if (ret) {
185 dev_err(dev, "Failed to read HSMP protocol version\n");
186 return ret;
187 }
188
189 if (hsmp_pdev->proto_ver == HSMP_PROTO_VER6) {
190 ret = hsmp_get_tbl_dram_base(i);
191 if (ret)
192 dev_err(dev, "Failed to init metric table\n");
193 }
194
195 /* Register with hwmon interface for reporting power */
196 ret = hsmp_create_sensor(dev, i);
197 if (ret)
198 dev_err(dev, "Failed to register HSMP sensors with hwmon\n");
199 }
200
201 return 0;
202 }
203
hsmp_pltdrv_probe(struct platform_device * pdev)204 static int hsmp_pltdrv_probe(struct platform_device *pdev)
205 {
206 int ret;
207
208 hsmp_pdev->sock = devm_kcalloc(&pdev->dev, hsmp_pdev->num_sockets,
209 sizeof(*hsmp_pdev->sock),
210 GFP_KERNEL);
211 if (!hsmp_pdev->sock)
212 return -ENOMEM;
213
214 ret = init_platform_device(&pdev->dev);
215 if (ret) {
216 dev_err(&pdev->dev, "Failed to init HSMP mailbox\n");
217 return ret;
218 }
219
220 ret = hsmp_misc_register(&pdev->dev);
221 if (ret) {
222 dev_err(&pdev->dev, "Failed to register misc device\n");
223 return ret;
224 }
225
226 dev_dbg(&pdev->dev, "AMD HSMP is probed successfully\n");
227 return 0;
228 }
229
hsmp_pltdrv_remove(struct platform_device * pdev)230 static void hsmp_pltdrv_remove(struct platform_device *pdev)
231 {
232 hsmp_misc_deregister();
233 }
234
235 static struct platform_driver amd_hsmp_driver = {
236 .probe = hsmp_pltdrv_probe,
237 .remove = hsmp_pltdrv_remove,
238 .driver = {
239 .name = DRIVER_NAME,
240 .dev_groups = hsmp_groups,
241 },
242 };
243
244 static struct platform_device *amd_hsmp_platdev;
245
hsmp_plat_dev_register(void)246 static int hsmp_plat_dev_register(void)
247 {
248 int ret;
249
250 amd_hsmp_platdev = platform_device_alloc(DRIVER_NAME, PLATFORM_DEVID_NONE);
251 if (!amd_hsmp_platdev)
252 return -ENOMEM;
253
254 ret = platform_device_add(amd_hsmp_platdev);
255 if (ret)
256 platform_device_put(amd_hsmp_platdev);
257
258 return ret;
259 }
260
261 /*
262 * This check is only needed for backward compatibility of previous platforms.
263 * All new platforms are expected to support ACPI based probing.
264 */
legacy_hsmp_support(void)265 static bool legacy_hsmp_support(void)
266 {
267 if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
268 return false;
269
270 switch (boot_cpu_data.x86) {
271 case 0x19:
272 switch (boot_cpu_data.x86_model) {
273 case 0x00 ... 0x1F:
274 case 0x30 ... 0x3F:
275 case 0x90 ... 0x9F:
276 case 0xA0 ... 0xAF:
277 return true;
278 default:
279 return false;
280 }
281 case 0x1A:
282 switch (boot_cpu_data.x86_model) {
283 case 0x00 ... 0x0F:
284 return true;
285 default:
286 return false;
287 }
288 default:
289 return false;
290 }
291
292 return false;
293 }
294
hsmp_plt_init(void)295 static int __init hsmp_plt_init(void)
296 {
297 int ret = -ENODEV;
298
299 if (acpi_dev_present(ACPI_HSMP_DEVICE_HID, NULL, -1)) {
300 if (IS_ENABLED(CONFIG_AMD_HSMP_ACPI))
301 pr_debug("HSMP is supported through ACPI on this platform, please use hsmp_acpi.ko\n");
302 else
303 pr_info("HSMP is supported through ACPI on this platform, please enable AMD_HSMP_ACPI config\n");
304 return -ENODEV;
305 }
306
307 if (!legacy_hsmp_support()) {
308 pr_info("HSMP interface is either disabled or not supported on family:%x model:%x\n",
309 boot_cpu_data.x86, boot_cpu_data.x86_model);
310 return ret;
311 }
312
313 hsmp_pdev = get_hsmp_pdev();
314 if (!hsmp_pdev)
315 return -ENOMEM;
316
317 /*
318 * amd_num_nodes() returns number of SMN/DF interfaces present in the system
319 * if we have N SMN/DF interfaces that ideally means N sockets
320 */
321 hsmp_pdev->num_sockets = amd_num_nodes();
322 if (hsmp_pdev->num_sockets == 0 || hsmp_pdev->num_sockets > MAX_AMD_NUM_NODES) {
323 pr_err("Wrong number of sockets\n");
324 return ret;
325 }
326
327 ret = platform_driver_register(&amd_hsmp_driver);
328 if (ret)
329 return ret;
330
331 ret = hsmp_plat_dev_register();
332 if (ret)
333 platform_driver_unregister(&amd_hsmp_driver);
334
335 return ret;
336 }
337
hsmp_plt_exit(void)338 static void __exit hsmp_plt_exit(void)
339 {
340 platform_device_unregister(amd_hsmp_platdev);
341 platform_driver_unregister(&amd_hsmp_driver);
342 }
343
344 device_initcall(hsmp_plt_init);
345 module_exit(hsmp_plt_exit);
346
347 MODULE_IMPORT_NS("AMD_HSMP");
348 MODULE_DESCRIPTION("AMD HSMP Platform Interface Driver");
349 MODULE_VERSION(DRIVER_VERSION);
350 MODULE_LICENSE("GPL");
351