xref: /linux/drivers/platform/x86/amd/hsmp/plat.c (revision 8e75dff56e003cdd38643024c4f5f8ba227100c8)
1e47c018aSSuma Hegde // SPDX-License-Identifier: GPL-2.0
2e47c018aSSuma Hegde /*
3e47c018aSSuma Hegde  * AMD HSMP Platform Driver
4e47c018aSSuma Hegde  * Copyright (c) 2024, AMD.
5e47c018aSSuma Hegde  * All Rights Reserved.
6e47c018aSSuma Hegde  *
7e47c018aSSuma Hegde  * This file provides platform device implementations.
8e47c018aSSuma Hegde  */
9e47c018aSSuma Hegde 
10e47c018aSSuma Hegde #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
11e47c018aSSuma Hegde 
12e47c018aSSuma Hegde #include <asm/amd_nb.h>
13e47c018aSSuma Hegde 
14e47c018aSSuma Hegde #include <linux/device.h>
15e47c018aSSuma Hegde #include <linux/pci.h>
16e47c018aSSuma Hegde #include <linux/sysfs.h>
17e47c018aSSuma Hegde 
18e47c018aSSuma Hegde #include "hsmp.h"
19e47c018aSSuma Hegde 
20e47c018aSSuma Hegde /*
21e47c018aSSuma Hegde  * To access specific HSMP mailbox register, s/w writes the SMN address of HSMP mailbox
22e47c018aSSuma Hegde  * register into the SMN_INDEX register, and reads/writes the SMN_DATA reg.
23e47c018aSSuma Hegde  * Below are required SMN address for HSMP Mailbox register offsets in SMU address space
24e47c018aSSuma Hegde  */
25e47c018aSSuma Hegde #define SMN_HSMP_BASE		0x3B00000
26e47c018aSSuma Hegde #define SMN_HSMP_MSG_ID		0x0010534
27e47c018aSSuma Hegde #define SMN_HSMP_MSG_ID_F1A_M0H	0x0010934
28e47c018aSSuma Hegde #define SMN_HSMP_MSG_RESP	0x0010980
29e47c018aSSuma Hegde #define SMN_HSMP_MSG_DATA	0x00109E0
30e47c018aSSuma Hegde 
31e47c018aSSuma Hegde #define HSMP_INDEX_REG		0xc4
32e47c018aSSuma Hegde #define HSMP_DATA_REG		0xc8
33e47c018aSSuma Hegde 
34e47c018aSSuma Hegde static int amd_hsmp_pci_rdwr(struct hsmp_socket *sock, u32 offset,
35e47c018aSSuma Hegde 			     u32 *value, bool write)
36e47c018aSSuma Hegde {
37e47c018aSSuma Hegde 	int ret;
38e47c018aSSuma Hegde 
39e47c018aSSuma Hegde 	if (!sock->root)
40e47c018aSSuma Hegde 		return -ENODEV;
41e47c018aSSuma Hegde 
42e47c018aSSuma Hegde 	ret = pci_write_config_dword(sock->root, HSMP_INDEX_REG,
43e47c018aSSuma Hegde 				     sock->mbinfo.base_addr + offset);
44e47c018aSSuma Hegde 	if (ret)
45e47c018aSSuma Hegde 		return ret;
46e47c018aSSuma Hegde 
47e47c018aSSuma Hegde 	ret = (write ? pci_write_config_dword(sock->root, HSMP_DATA_REG, *value)
48e47c018aSSuma Hegde 		     : pci_read_config_dword(sock->root, HSMP_DATA_REG, value));
49e47c018aSSuma Hegde 
50e47c018aSSuma Hegde 	return ret;
51e47c018aSSuma Hegde }
52e47c018aSSuma Hegde 
53e47c018aSSuma Hegde int hsmp_create_non_acpi_sysfs_if(struct device *dev)
54e47c018aSSuma Hegde {
55e47c018aSSuma Hegde 	const struct attribute_group **hsmp_attr_grps;
56e47c018aSSuma Hegde 	struct attribute_group *attr_grp;
57e47c018aSSuma Hegde 	u16 i;
58e47c018aSSuma Hegde 
59*8e75dff5SSuma Hegde 	hsmp_attr_grps = devm_kcalloc(dev, hsmp_pdev.num_sockets + 1,
60e47c018aSSuma Hegde 				      sizeof(*hsmp_attr_grps),
61e47c018aSSuma Hegde 				      GFP_KERNEL);
62e47c018aSSuma Hegde 	if (!hsmp_attr_grps)
63e47c018aSSuma Hegde 		return -ENOMEM;
64e47c018aSSuma Hegde 
65e47c018aSSuma Hegde 	/* Create a sysfs directory for each socket */
66*8e75dff5SSuma Hegde 	for (i = 0; i < hsmp_pdev.num_sockets; i++) {
67e47c018aSSuma Hegde 		attr_grp = devm_kzalloc(dev, sizeof(struct attribute_group),
68e47c018aSSuma Hegde 					GFP_KERNEL);
69e47c018aSSuma Hegde 		if (!attr_grp)
70e47c018aSSuma Hegde 			return -ENOMEM;
71e47c018aSSuma Hegde 
72*8e75dff5SSuma Hegde 		snprintf(hsmp_pdev.sock[i].name, HSMP_ATTR_GRP_NAME_SIZE, "socket%u", (u8)i);
73*8e75dff5SSuma Hegde 		attr_grp->name			= hsmp_pdev.sock[i].name;
74e47c018aSSuma Hegde 		attr_grp->is_bin_visible	= hsmp_is_sock_attr_visible;
75e47c018aSSuma Hegde 		hsmp_attr_grps[i]		= attr_grp;
76e47c018aSSuma Hegde 
77e47c018aSSuma Hegde 		hsmp_create_attr_list(attr_grp, dev, i);
78e47c018aSSuma Hegde 	}
79e47c018aSSuma Hegde 
80e47c018aSSuma Hegde 	return device_add_groups(dev, hsmp_attr_grps);
81e47c018aSSuma Hegde }
82e47c018aSSuma Hegde 
83e47c018aSSuma Hegde static inline bool is_f1a_m0h(void)
84e47c018aSSuma Hegde {
85e47c018aSSuma Hegde 	if (boot_cpu_data.x86 == 0x1A && boot_cpu_data.x86_model <= 0x0F)
86e47c018aSSuma Hegde 		return true;
87e47c018aSSuma Hegde 
88e47c018aSSuma Hegde 	return false;
89e47c018aSSuma Hegde }
90e47c018aSSuma Hegde 
91e47c018aSSuma Hegde int init_platform_device(struct device *dev)
92e47c018aSSuma Hegde {
93e47c018aSSuma Hegde 	struct hsmp_socket *sock;
94e47c018aSSuma Hegde 	int ret, i;
95e47c018aSSuma Hegde 
96*8e75dff5SSuma Hegde 	for (i = 0; i < hsmp_pdev.num_sockets; i++) {
97e47c018aSSuma Hegde 		if (!node_to_amd_nb(i))
98e47c018aSSuma Hegde 			return -ENODEV;
99*8e75dff5SSuma Hegde 		sock = &hsmp_pdev.sock[i];
100e47c018aSSuma Hegde 		sock->root			= node_to_amd_nb(i)->root;
101e47c018aSSuma Hegde 		sock->sock_ind			= i;
102e47c018aSSuma Hegde 		sock->dev			= dev;
103e47c018aSSuma Hegde 		sock->mbinfo.base_addr		= SMN_HSMP_BASE;
104e47c018aSSuma Hegde 		sock->amd_hsmp_rdwr		= amd_hsmp_pci_rdwr;
105e47c018aSSuma Hegde 
106e47c018aSSuma Hegde 		/*
107e47c018aSSuma Hegde 		 * This is a transitional change from non-ACPI to ACPI, only
108e47c018aSSuma Hegde 		 * family 0x1A, model 0x00 platform is supported for both ACPI and non-ACPI.
109e47c018aSSuma Hegde 		 */
110e47c018aSSuma Hegde 		if (is_f1a_m0h())
111e47c018aSSuma Hegde 			sock->mbinfo.msg_id_off	= SMN_HSMP_MSG_ID_F1A_M0H;
112e47c018aSSuma Hegde 		else
113e47c018aSSuma Hegde 			sock->mbinfo.msg_id_off	= SMN_HSMP_MSG_ID;
114e47c018aSSuma Hegde 
115e47c018aSSuma Hegde 		sock->mbinfo.msg_resp_off	= SMN_HSMP_MSG_RESP;
116e47c018aSSuma Hegde 		sock->mbinfo.msg_arg_off	= SMN_HSMP_MSG_DATA;
117e47c018aSSuma Hegde 		sema_init(&sock->hsmp_sem, 1);
118e47c018aSSuma Hegde 
119e47c018aSSuma Hegde 		/* Test the hsmp interface on each socket */
120e47c018aSSuma Hegde 		ret = hsmp_test(i, 0xDEADBEEF);
121e47c018aSSuma Hegde 		if (ret) {
122e47c018aSSuma Hegde 			dev_err(dev, "HSMP test message failed on Fam:%x model:%x\n",
123e47c018aSSuma Hegde 				boot_cpu_data.x86, boot_cpu_data.x86_model);
124e47c018aSSuma Hegde 			dev_err(dev, "Is HSMP disabled in BIOS ?\n");
125e47c018aSSuma Hegde 			return ret;
126e47c018aSSuma Hegde 		}
127e47c018aSSuma Hegde 
128e47c018aSSuma Hegde 		ret = hsmp_cache_proto_ver(i);
129e47c018aSSuma Hegde 		if (ret) {
130e47c018aSSuma Hegde 			dev_err(dev, "Failed to read HSMP protocol version\n");
131e47c018aSSuma Hegde 			return ret;
132e47c018aSSuma Hegde 		}
133e47c018aSSuma Hegde 	}
134e47c018aSSuma Hegde 
135e47c018aSSuma Hegde 	return 0;
136e47c018aSSuma Hegde }
137