xref: /linux/drivers/platform/x86/amd/hsmp/acpi.c (revision 7a9b709e7cc5ce1ffb84ce07bf6d157e1de758df)
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 an ACPI based driver implementation for HSMP interface.
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/device.h>
16 #include <linux/dev_printk.h>
17 #include <linux/ioport.h>
18 #include <linux/kstrtox.h>
19 #include <linux/module.h>
20 #include <linux/platform_device.h>
21 #include <linux/sysfs.h>
22 #include <linux/uuid.h>
23 
24 #include <uapi/asm-generic/errno-base.h>
25 
26 #include <asm/amd_node.h>
27 
28 #include "hsmp.h"
29 
30 #define DRIVER_NAME		"amd_hsmp"
31 #define DRIVER_VERSION		"2.3"
32 #define ACPI_HSMP_DEVICE_HID	"AMDI0097"
33 
34 /* These are the strings specified in ACPI table */
35 #define MSG_IDOFF_STR		"MsgIdOffset"
36 #define MSG_ARGOFF_STR		"MsgArgOffset"
37 #define MSG_RESPOFF_STR		"MsgRspOffset"
38 
39 static struct hsmp_plat_device *hsmp_pdev;
40 
41 static int amd_hsmp_acpi_rdwr(struct hsmp_socket *sock, u32 offset,
42 			      u32 *value, bool write)
43 {
44 	if (write)
45 		iowrite32(*value, sock->virt_base_addr + offset);
46 	else
47 		*value = ioread32(sock->virt_base_addr + offset);
48 
49 	return 0;
50 }
51 
52 /* This is the UUID used for HSMP */
53 static const guid_t acpi_hsmp_uuid = GUID_INIT(0xb74d619d, 0x5707, 0x48bd,
54 						0xa6, 0x9f, 0x4e, 0xa2,
55 						0x87, 0x1f, 0xc2, 0xf6);
56 
57 static inline bool is_acpi_hsmp_uuid(union acpi_object *obj)
58 {
59 	if (obj->type == ACPI_TYPE_BUFFER && obj->buffer.length == UUID_SIZE)
60 		return guid_equal((guid_t *)obj->buffer.pointer, &acpi_hsmp_uuid);
61 
62 	return false;
63 }
64 
65 static inline int hsmp_get_uid(struct device *dev, u16 *sock_ind)
66 {
67 	char *uid;
68 
69 	/*
70 	 * UID (ID00, ID01..IDXX) is used for differentiating sockets,
71 	 * read it and strip the "ID" part of it and convert the remaining
72 	 * bytes to integer.
73 	 */
74 	uid = acpi_device_uid(ACPI_COMPANION(dev));
75 
76 	return kstrtou16(uid + 2, 10, sock_ind);
77 }
78 
79 static acpi_status hsmp_resource(struct acpi_resource *res, void *data)
80 {
81 	struct hsmp_socket *sock = data;
82 	struct resource r;
83 
84 	switch (res->type) {
85 	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
86 		if (!acpi_dev_resource_memory(res, &r))
87 			return AE_ERROR;
88 		if (!r.start || r.end < r.start || !(r.flags & IORESOURCE_MEM_WRITEABLE))
89 			return AE_ERROR;
90 		sock->mbinfo.base_addr = r.start;
91 		sock->mbinfo.size = resource_size(&r);
92 		break;
93 	case ACPI_RESOURCE_TYPE_END_TAG:
94 		break;
95 	default:
96 		return AE_ERROR;
97 	}
98 
99 	return AE_OK;
100 }
101 
102 static int hsmp_read_acpi_dsd(struct hsmp_socket *sock)
103 {
104 	struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
105 	union acpi_object *guid, *mailbox_package;
106 	union acpi_object *dsd;
107 	acpi_status status;
108 	int ret = 0;
109 	int j;
110 
111 	status = acpi_evaluate_object_typed(ACPI_HANDLE(sock->dev), "_DSD", NULL,
112 					    &buf, ACPI_TYPE_PACKAGE);
113 	if (ACPI_FAILURE(status)) {
114 		dev_err(sock->dev, "Failed to read mailbox reg offsets from DSD table, err: %s\n",
115 			acpi_format_exception(status));
116 		return -ENODEV;
117 	}
118 
119 	dsd = buf.pointer;
120 
121 	/* HSMP _DSD property should contain 2 objects.
122 	 * 1. guid which is an acpi object of type ACPI_TYPE_BUFFER
123 	 * 2. mailbox which is an acpi object of type ACPI_TYPE_PACKAGE
124 	 *    This mailbox object contains 3 more acpi objects of type
125 	 *    ACPI_TYPE_PACKAGE for holding msgid, msgresp, msgarg offsets
126 	 *    these packages inturn contain 2 acpi objects of type
127 	 *    ACPI_TYPE_STRING and ACPI_TYPE_INTEGER
128 	 */
129 	if (!dsd || dsd->type != ACPI_TYPE_PACKAGE || dsd->package.count != 2) {
130 		ret = -EINVAL;
131 		goto free_buf;
132 	}
133 
134 	guid = &dsd->package.elements[0];
135 	mailbox_package = &dsd->package.elements[1];
136 	if (!is_acpi_hsmp_uuid(guid) || mailbox_package->type != ACPI_TYPE_PACKAGE) {
137 		dev_err(sock->dev, "Invalid hsmp _DSD table data\n");
138 		ret = -EINVAL;
139 		goto free_buf;
140 	}
141 
142 	for (j = 0; j < mailbox_package->package.count; j++) {
143 		union acpi_object *msgobj, *msgstr, *msgint;
144 
145 		msgobj	= &mailbox_package->package.elements[j];
146 		msgstr	= &msgobj->package.elements[0];
147 		msgint	= &msgobj->package.elements[1];
148 
149 		/* package should have 1 string and 1 integer object */
150 		if (msgobj->type != ACPI_TYPE_PACKAGE ||
151 		    msgstr->type != ACPI_TYPE_STRING ||
152 		    msgint->type != ACPI_TYPE_INTEGER) {
153 			ret = -EINVAL;
154 			goto free_buf;
155 		}
156 
157 		if (!strncmp(msgstr->string.pointer, MSG_IDOFF_STR,
158 			     msgstr->string.length)) {
159 			sock->mbinfo.msg_id_off = msgint->integer.value;
160 		} else if (!strncmp(msgstr->string.pointer, MSG_RESPOFF_STR,
161 				    msgstr->string.length)) {
162 			sock->mbinfo.msg_resp_off =  msgint->integer.value;
163 		} else if (!strncmp(msgstr->string.pointer, MSG_ARGOFF_STR,
164 				    msgstr->string.length)) {
165 			sock->mbinfo.msg_arg_off = msgint->integer.value;
166 		} else {
167 			ret = -ENOENT;
168 			goto free_buf;
169 		}
170 	}
171 
172 	if (!sock->mbinfo.msg_id_off || !sock->mbinfo.msg_resp_off ||
173 	    !sock->mbinfo.msg_arg_off)
174 		ret = -EINVAL;
175 
176 free_buf:
177 	ACPI_FREE(buf.pointer);
178 	return ret;
179 }
180 
181 static int hsmp_read_acpi_crs(struct hsmp_socket *sock)
182 {
183 	acpi_status status;
184 
185 	status = acpi_walk_resources(ACPI_HANDLE(sock->dev), METHOD_NAME__CRS,
186 				     hsmp_resource, sock);
187 	if (ACPI_FAILURE(status)) {
188 		dev_err(sock->dev, "Failed to look up MP1 base address from CRS method, err: %s\n",
189 			acpi_format_exception(status));
190 		return -EINVAL;
191 	}
192 	if (!sock->mbinfo.base_addr || !sock->mbinfo.size)
193 		return -EINVAL;
194 
195 	/* The mapped region should be un-cached */
196 	sock->virt_base_addr = devm_ioremap_uc(sock->dev, sock->mbinfo.base_addr,
197 					       sock->mbinfo.size);
198 	if (!sock->virt_base_addr) {
199 		dev_err(sock->dev, "Failed to ioremap MP1 base address\n");
200 		return -ENOMEM;
201 	}
202 
203 	return 0;
204 }
205 
206 /* Parse the ACPI table to read the data */
207 static int hsmp_parse_acpi_table(struct device *dev, u16 sock_ind)
208 {
209 	struct hsmp_socket *sock = &hsmp_pdev->sock[sock_ind];
210 	int ret;
211 
212 	sock->sock_ind		= sock_ind;
213 	sock->dev		= dev;
214 	sock->amd_hsmp_rdwr	= amd_hsmp_acpi_rdwr;
215 
216 	sema_init(&sock->hsmp_sem, 1);
217 
218 	dev_set_drvdata(dev, sock);
219 
220 	/* Read MP1 base address from CRS method */
221 	ret = hsmp_read_acpi_crs(sock);
222 	if (ret)
223 		return ret;
224 
225 	/* Read mailbox offsets from DSD table */
226 	return hsmp_read_acpi_dsd(sock);
227 }
228 
229 static ssize_t hsmp_metric_tbl_acpi_read(struct file *filp, struct kobject *kobj,
230 					 const struct bin_attribute *bin_attr, char *buf,
231 					 loff_t off, size_t count)
232 {
233 	struct device *dev = container_of(kobj, struct device, kobj);
234 	struct hsmp_socket *sock = dev_get_drvdata(dev);
235 
236 	return hsmp_metric_tbl_read(sock, buf, count);
237 }
238 
239 static umode_t hsmp_is_sock_attr_visible(struct kobject *kobj,
240 					 const struct bin_attribute *battr, int id)
241 {
242 	if (hsmp_pdev->proto_ver == HSMP_PROTO_VER6)
243 		return battr->attr.mode;
244 
245 	return 0;
246 }
247 
248 static int init_acpi(struct device *dev)
249 {
250 	u16 sock_ind;
251 	int ret;
252 
253 	ret = hsmp_get_uid(dev, &sock_ind);
254 	if (ret)
255 		return ret;
256 	if (sock_ind >= hsmp_pdev->num_sockets)
257 		return -EINVAL;
258 
259 	ret = hsmp_parse_acpi_table(dev, sock_ind);
260 	if (ret) {
261 		dev_err(dev, "Failed to parse ACPI table\n");
262 		return ret;
263 	}
264 
265 	/* Test the hsmp interface */
266 	ret = hsmp_test(sock_ind, 0xDEADBEEF);
267 	if (ret) {
268 		dev_err(dev, "HSMP test message failed on Fam:%x model:%x\n",
269 			boot_cpu_data.x86, boot_cpu_data.x86_model);
270 		dev_err(dev, "Is HSMP disabled in BIOS ?\n");
271 		return ret;
272 	}
273 
274 	ret = hsmp_cache_proto_ver(sock_ind);
275 	if (ret) {
276 		dev_err(dev, "Failed to read HSMP protocol version\n");
277 		return ret;
278 	}
279 
280 	if (hsmp_pdev->proto_ver == HSMP_PROTO_VER6) {
281 		ret = hsmp_get_tbl_dram_base(sock_ind);
282 		if (ret)
283 			dev_err(dev, "Failed to init metric table\n");
284 	}
285 
286 	return ret;
287 }
288 
289 static const struct bin_attribute  hsmp_metric_tbl_attr = {
290 	.attr = { .name = HSMP_METRICS_TABLE_NAME, .mode = 0444},
291 	.read_new = hsmp_metric_tbl_acpi_read,
292 	.size = sizeof(struct hsmp_metric_table),
293 };
294 
295 static const struct bin_attribute *hsmp_attr_list[] = {
296 	&hsmp_metric_tbl_attr,
297 	NULL
298 };
299 
300 static const struct attribute_group hsmp_attr_grp = {
301 	.bin_attrs_new = hsmp_attr_list,
302 	.is_bin_visible = hsmp_is_sock_attr_visible,
303 };
304 
305 static const struct attribute_group *hsmp_groups[] = {
306 	&hsmp_attr_grp,
307 	NULL
308 };
309 
310 static const struct acpi_device_id amd_hsmp_acpi_ids[] = {
311 	{ACPI_HSMP_DEVICE_HID, 0},
312 	{}
313 };
314 MODULE_DEVICE_TABLE(acpi, amd_hsmp_acpi_ids);
315 
316 static int hsmp_acpi_probe(struct platform_device *pdev)
317 {
318 	int ret;
319 
320 	hsmp_pdev = get_hsmp_pdev();
321 	if (!hsmp_pdev)
322 		return -ENOMEM;
323 
324 	if (!hsmp_pdev->is_probed) {
325 		hsmp_pdev->num_sockets = amd_num_nodes();
326 		if (hsmp_pdev->num_sockets == 0 || hsmp_pdev->num_sockets > MAX_AMD_NUM_NODES)
327 			return -ENODEV;
328 
329 		hsmp_pdev->sock = devm_kcalloc(&pdev->dev, hsmp_pdev->num_sockets,
330 					       sizeof(*hsmp_pdev->sock),
331 					       GFP_KERNEL);
332 		if (!hsmp_pdev->sock)
333 			return -ENOMEM;
334 	}
335 
336 	ret = init_acpi(&pdev->dev);
337 	if (ret) {
338 		dev_err(&pdev->dev, "Failed to initialize HSMP interface.\n");
339 		return ret;
340 	}
341 
342 	if (!hsmp_pdev->is_probed) {
343 		ret = hsmp_misc_register(&pdev->dev);
344 		if (ret)
345 			return ret;
346 		hsmp_pdev->is_probed = true;
347 	}
348 
349 	return 0;
350 }
351 
352 static void hsmp_acpi_remove(struct platform_device *pdev)
353 {
354 	/*
355 	 * We register only one misc_device even on multi-socket system.
356 	 * So, deregister should happen only once.
357 	 */
358 	if (hsmp_pdev->is_probed) {
359 		hsmp_misc_deregister();
360 		hsmp_pdev->is_probed = false;
361 	}
362 }
363 
364 static struct platform_driver amd_hsmp_driver = {
365 	.probe		= hsmp_acpi_probe,
366 	.remove		= hsmp_acpi_remove,
367 	.driver		= {
368 		.name	= DRIVER_NAME,
369 		.acpi_match_table = amd_hsmp_acpi_ids,
370 		.dev_groups = hsmp_groups,
371 	},
372 };
373 
374 module_platform_driver(amd_hsmp_driver);
375 
376 MODULE_IMPORT_NS("AMD_HSMP");
377 MODULE_DESCRIPTION("AMD HSMP Platform Interface Driver");
378 MODULE_VERSION(DRIVER_VERSION);
379 MODULE_LICENSE("GPL");
380